/[dynamips]/upstream/dynamips-0.2.5/cpu.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /upstream/dynamips-0.2.5/cpu.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (hide annotations)
Sat Oct 6 16:01:44 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 5718 byte(s)
import 0.2.5 from upstream

1 dpavlin 1 /*
2     * Cisco 7200 (Predator) simulation platform.
3     * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)
4     *
5     * Management of CPU groups (for MP systems).
6     */
7    
8     #define _GNU_SOURCE
9     #include <stdio.h>
10     #include <stdlib.h>
11     #include <unistd.h>
12     #include <string.h>
13     #include <stdarg.h>
14     #include <sys/types.h>
15     #include <sys/stat.h>
16     #include <sys/mman.h>
17     #include <fcntl.h>
18     #include <pthread.h>
19    
20     #include "mips64.h"
21     #include "dynamips.h"
22     #include "cpu.h"
23     #include "memory.h"
24     #include "device.h"
25     #include "cp0.h"
26     #include "mips64_exec.h"
27     #include "vm.h"
28    
29     /* Find a CPU in a group given its ID */
30     cpu_mips_t *cpu_group_find_id(cpu_group_t *group,u_int id)
31     {
32     cpu_mips_t *cpu;
33    
34     for(cpu=group->cpu_list;cpu;cpu=cpu->next)
35     if (cpu->id == id)
36     return cpu;
37    
38     return NULL;
39     }
40    
41     /* Find the highest CPU ID in a CPU group */
42     int cpu_group_find_highest_id(cpu_group_t *group,u_int *highest_id)
43     {
44     cpu_mips_t *cpu;
45     u_int max_id = 0;
46    
47     if (!group || group->cpu_list)
48     return(-1);
49    
50     for(cpu=group->cpu_list;cpu;cpu=cpu->next)
51     if (cpu->id >= max_id)
52     max_id = cpu->id;
53    
54     *highest_id = max_id;
55     return(0);
56     }
57    
58     /* Add a CPU in a CPU group */
59     int cpu_group_add(cpu_group_t *group,cpu_mips_t *cpu)
60     {
61     /* check that we don't already have a CPU with this id */
62     if (cpu_group_find_id(group,cpu->id) != NULL) {
63     fprintf(stderr,"cpu_group_add: CPU%u already present in group.\n",
64     cpu->id);
65     return(-1);
66     }
67    
68     cpu->next = group->cpu_list;
69     group->cpu_list = cpu;
70     return(0);
71     }
72    
73     /* Create a new CPU group */
74     cpu_group_t *cpu_group_create(char *name)
75     {
76     cpu_group_t *group;
77    
78     if (!(group = malloc(sizeof(*group))))
79     return NULL;
80    
81     group->name = name;
82     group->cpu_list = NULL;
83     return group;
84     }
85    
86     /* Delete a CPU group */
87     void cpu_group_delete(cpu_group_t *group)
88     {
89     cpu_mips_t *cpu,*next;
90    
91     if (group != NULL) {
92     for(cpu=group->cpu_list;cpu;cpu=next) {
93     next = cpu->next;
94     cpu_delete(cpu);
95     }
96    
97     free(group);
98     }
99     }
100    
101     /* Rebuild the MTS subsystem for a CPU group */
102     int cpu_group_rebuild_mts(cpu_group_t *group)
103     {
104     cpu_mips_t *cpu;
105    
106     for(cpu=group->cpu_list;cpu;cpu=cpu->next)
107     cpu->mts_rebuild(cpu);
108    
109     return(0);
110     }
111    
112     /* Log a message for a CPU */
113     void cpu_log(cpu_mips_t *cpu,char *module,char *format,...)
114     {
115     char buffer[256];
116     va_list ap;
117    
118     va_start(ap,format);
119     snprintf(buffer,sizeof(buffer),"CPU%u: %s",cpu->id,module);
120     vm_flog(cpu->vm,buffer,format,ap);
121     va_end(ap);
122     }
123    
124     /* Create a new CPU */
125     cpu_mips_t *cpu_create(vm_instance_t *vm,u_int id)
126     {
127     void *(*cpu_run_fn)(void *);
128     cpu_mips_t *cpu;
129    
130     if (!(cpu = malloc(sizeof(*cpu))))
131     return NULL;
132    
133     memset(cpu,0,sizeof(*cpu));
134     cpu->vm = vm;
135    
136     /* by default, use a standard initialization (CPU exec is suspended) */
137     mips64_init(cpu);
138     cpu->id = id;
139     cpu->state = MIPS_CPU_SUSPENDED;
140    
141     cpu_run_fn = (void *)insn_block_execute;
142     #if __GNUC__ > 2
143     if (!cpu->vm->jit_use) {
144     cpu_run_fn = (void *)mips64_exec_run_cpu;
145     } else {
146     mips64_jit_init(cpu);
147     }
148     #endif
149    
150     /* create the CPU thread execution */
151     if (pthread_create(&cpu->cpu_thread,NULL,cpu_run_fn,cpu) != 0) {
152     fprintf(stderr,"cpu_create: unable to create thread for CPU%u\n",id);
153     free(cpu);
154     return NULL;
155     }
156    
157     return cpu;
158     }
159    
160     /* Delete a CPU */
161     void cpu_delete(cpu_mips_t *cpu)
162     {
163     if (cpu) {
164     /* Stop activity of this CPU */
165     cpu_stop(cpu);
166     pthread_join(cpu->cpu_thread,NULL);
167    
168     /* Free resources */
169     mips64_delete(cpu);
170     }
171     }
172    
173     /* Start a CPU */
174     void cpu_start(cpu_mips_t *cpu)
175     {
176     if (cpu) {
177     cpu_log(cpu,"CPU_STATE","Starting CPU (old state=%u)...\n",cpu->state);
178     cpu->state = MIPS_CPU_RUNNING;
179     }
180     }
181    
182     /* Stop a CPU */
183     void cpu_stop(cpu_mips_t *cpu)
184     {
185     if (cpu) {
186     cpu_log(cpu,"CPU_STATE","Halting CPU (old state=%u)...\n",cpu->state);
187     cpu->state = MIPS_CPU_HALTED;
188     }
189     }
190    
191     /* Start all CPUs of a CPU group */
192     void cpu_group_start_all_cpu(cpu_group_t *group)
193     {
194     cpu_mips_t *cpu;
195    
196     for(cpu=group->cpu_list;cpu;cpu=cpu->next)
197     cpu_start(cpu);
198     }
199    
200     /* Stop all CPUs of a CPU group */
201     void cpu_group_stop_all_cpu(cpu_group_t *group)
202     {
203     cpu_mips_t *cpu;
204    
205     for(cpu=group->cpu_list;cpu;cpu=cpu->next)
206     cpu_stop(cpu);
207     }
208    
209     /* Set a state of all CPUs of a CPU group */
210     void cpu_group_set_state(cpu_group_t *group,u_int state)
211     {
212     cpu_mips_t *cpu;
213    
214     for(cpu=group->cpu_list;cpu;cpu=cpu->next)
215     cpu->state = state;
216     }
217    
218     /* Returns TRUE if all CPUs in a CPU group are inactive */
219     static int cpu_group_check_activity(cpu_group_t *group)
220     {
221     cpu_mips_t *cpu;
222    
223     for(cpu=group->cpu_list;cpu;cpu=cpu->next) {
224     if (!cpu->cpu_thread_running)
225     continue;
226    
227     if ((cpu->state == MIPS_CPU_RUNNING) || !cpu->seq_state)
228     return(FALSE);
229     }
230    
231     return(TRUE);
232     }
233    
234     /* Synchronize on CPUs (all CPUs must be inactive) */
235     int cpu_group_sync_state(cpu_group_t *group)
236     {
237     cpu_mips_t *cpu;
238     m_tmcnt_t t1,t2;
239    
240     /* Check that CPU activity is really suspended */
241     t1 = m_gettime();
242    
243     for(cpu=group->cpu_list;cpu;cpu=cpu->next)
244     cpu->seq_state = 0;
245    
246     while(!cpu_group_check_activity(group)) {
247     t2 = m_gettime();
248    
249     if (t2 > (t1 + 10000))
250     return(-1);
251    
252     usleep(50000);
253     }
254    
255     return(0);
256     }
257    
258     /* Save state of all CPUs */
259     int cpu_group_save_state(cpu_group_t *group)
260     {
261     cpu_mips_t *cpu;
262    
263     for(cpu=group->cpu_list;cpu;cpu=cpu->next)
264     cpu->prev_state = cpu->state;
265    
266     return(TRUE);
267     }
268    
269     /* Restore state of all CPUs */
270     int cpu_group_restore_state(cpu_group_t *group)
271     {
272     cpu_mips_t *cpu;
273    
274     for(cpu=group->cpu_list;cpu;cpu=cpu->next)
275     cpu->state = cpu->prev_state;
276    
277     return(TRUE);
278     }

  ViewVC Help
Powered by ViewVC 1.1.26