/[dynamips]/trunk/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 /trunk/cpu.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 8 - (hide annotations)
Sat Oct 6 16:24:54 2007 UTC (16 years, 6 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.7-RC2/cpu.c
File MIME type: text/plain
File size: 7206 byte(s)
dynamips-0.2.7-RC2

1 dpavlin 1 /*
2 dpavlin 7 * Cisco router simulation platform.
3 dpavlin 1 * 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 "cpu.h"
21     #include "memory.h"
22     #include "device.h"
23 dpavlin 7 #include "mips64.h"
24     #include "mips64_cp0.h"
25 dpavlin 1 #include "mips64_exec.h"
26 dpavlin 7 #include "mips64_jit.h"
27     #include "ppc32.h"
28     #include "ppc32_exec.h"
29     #include "ppc32_jit.h"
30     #include "dynamips.h"
31 dpavlin 1 #include "vm.h"
32    
33     /* Find a CPU in a group given its ID */
34 dpavlin 7 cpu_gen_t *cpu_group_find_id(cpu_group_t *group,u_int id)
35 dpavlin 1 {
36 dpavlin 7 cpu_gen_t *cpu;
37 dpavlin 1
38 dpavlin 6 if (!group)
39     return NULL;
40    
41 dpavlin 1 for(cpu=group->cpu_list;cpu;cpu=cpu->next)
42     if (cpu->id == id)
43     return cpu;
44    
45     return NULL;
46     }
47    
48     /* Find the highest CPU ID in a CPU group */
49     int cpu_group_find_highest_id(cpu_group_t *group,u_int *highest_id)
50     {
51 dpavlin 7 cpu_gen_t *cpu;
52 dpavlin 1 u_int max_id = 0;
53    
54     if (!group || group->cpu_list)
55     return(-1);
56    
57     for(cpu=group->cpu_list;cpu;cpu=cpu->next)
58     if (cpu->id >= max_id)
59     max_id = cpu->id;
60    
61     *highest_id = max_id;
62     return(0);
63     }
64    
65     /* Add a CPU in a CPU group */
66 dpavlin 7 int cpu_group_add(cpu_group_t *group,cpu_gen_t *cpu)
67 dpavlin 1 {
68 dpavlin 6 if (!group)
69     return(-1);
70    
71 dpavlin 1 /* check that we don't already have a CPU with this id */
72     if (cpu_group_find_id(group,cpu->id) != NULL) {
73     fprintf(stderr,"cpu_group_add: CPU%u already present in group.\n",
74     cpu->id);
75     return(-1);
76     }
77    
78     cpu->next = group->cpu_list;
79     group->cpu_list = cpu;
80     return(0);
81     }
82    
83     /* Create a new CPU group */
84     cpu_group_t *cpu_group_create(char *name)
85     {
86     cpu_group_t *group;
87    
88     if (!(group = malloc(sizeof(*group))))
89     return NULL;
90    
91     group->name = name;
92     group->cpu_list = NULL;
93     return group;
94     }
95    
96     /* Delete a CPU group */
97     void cpu_group_delete(cpu_group_t *group)
98     {
99 dpavlin 7 cpu_gen_t *cpu,*next;
100 dpavlin 1
101     if (group != NULL) {
102     for(cpu=group->cpu_list;cpu;cpu=next) {
103     next = cpu->next;
104     cpu_delete(cpu);
105     }
106    
107     free(group);
108     }
109     }
110    
111     /* Rebuild the MTS subsystem for a CPU group */
112     int cpu_group_rebuild_mts(cpu_group_t *group)
113     {
114 dpavlin 7 cpu_gen_t *cpu;
115 dpavlin 1
116     for(cpu=group->cpu_list;cpu;cpu=cpu->next)
117     cpu->mts_rebuild(cpu);
118    
119     return(0);
120     }
121    
122     /* Log a message for a CPU */
123 dpavlin 7 void cpu_log(cpu_gen_t *cpu,char *module,char *format,...)
124 dpavlin 1 {
125     char buffer[256];
126     va_list ap;
127    
128     va_start(ap,format);
129     snprintf(buffer,sizeof(buffer),"CPU%u: %s",cpu->id,module);
130     vm_flog(cpu->vm,buffer,format,ap);
131     va_end(ap);
132     }
133    
134     /* Create a new CPU */
135 dpavlin 7 cpu_gen_t *cpu_create(vm_instance_t *vm,u_int type,u_int id)
136 dpavlin 1 {
137     void *(*cpu_run_fn)(void *);
138 dpavlin 7 cpu_gen_t *cpu;
139 dpavlin 1
140     if (!(cpu = malloc(sizeof(*cpu))))
141     return NULL;
142    
143     memset(cpu,0,sizeof(*cpu));
144     cpu->vm = vm;
145     cpu->id = id;
146 dpavlin 7 cpu->type = type;
147     cpu->state = CPU_STATE_SUSPENDED;
148 dpavlin 1
149 dpavlin 7 switch(cpu->type) {
150     case CPU_TYPE_MIPS64:
151     CPU_MIPS64(cpu)->vm = vm;
152     CPU_MIPS64(cpu)->gen = cpu;
153     mips64_init(CPU_MIPS64(cpu));
154    
155     cpu_run_fn = (void *)mips64_jit_run_cpu;
156    
157     if (!cpu->vm->jit_use)
158     cpu_run_fn = (void *)mips64_exec_run_cpu;
159     else
160     mips64_jit_init(CPU_MIPS64(cpu));
161     break;
162    
163     case CPU_TYPE_PPC32:
164     CPU_PPC32(cpu)->vm = vm;
165     CPU_PPC32(cpu)->gen = cpu;
166     ppc32_init(CPU_PPC32(cpu));
167    
168     cpu_run_fn = (void *)ppc32_jit_run_cpu;
169    
170     if (!cpu->vm->jit_use)
171     cpu_run_fn = (void *)ppc32_exec_run_cpu;
172     else
173     ppc32_jit_init(CPU_PPC32(cpu));
174     break;
175    
176     default:
177     fprintf(stderr,"CPU type %u is not supported yet\n",cpu->type);
178     abort();
179     break;
180 dpavlin 1 }
181    
182     /* create the CPU thread execution */
183     if (pthread_create(&cpu->cpu_thread,NULL,cpu_run_fn,cpu) != 0) {
184     fprintf(stderr,"cpu_create: unable to create thread for CPU%u\n",id);
185     free(cpu);
186     return NULL;
187     }
188    
189     return cpu;
190     }
191    
192     /* Delete a CPU */
193 dpavlin 7 void cpu_delete(cpu_gen_t *cpu)
194 dpavlin 1 {
195     if (cpu) {
196     /* Stop activity of this CPU */
197     cpu_stop(cpu);
198     pthread_join(cpu->cpu_thread,NULL);
199    
200     /* Free resources */
201 dpavlin 7 switch(cpu->type) {
202     case CPU_TYPE_MIPS64:
203     mips64_delete(CPU_MIPS64(cpu));
204     break;
205    
206     case CPU_TYPE_PPC32:
207     ppc32_delete(CPU_PPC32(cpu));
208     break;
209     }
210    
211     free(cpu);
212 dpavlin 1 }
213     }
214    
215     /* Start a CPU */
216 dpavlin 7 void cpu_start(cpu_gen_t *cpu)
217 dpavlin 1 {
218     if (cpu) {
219     cpu_log(cpu,"CPU_STATE","Starting CPU (old state=%u)...\n",cpu->state);
220 dpavlin 7 cpu->state = CPU_STATE_RUNNING;
221 dpavlin 1 }
222     }
223    
224     /* Stop a CPU */
225 dpavlin 7 void cpu_stop(cpu_gen_t *cpu)
226 dpavlin 1 {
227     if (cpu) {
228     cpu_log(cpu,"CPU_STATE","Halting CPU (old state=%u)...\n",cpu->state);
229 dpavlin 7 cpu->state = CPU_STATE_HALTED;
230 dpavlin 1 }
231     }
232    
233     /* Start all CPUs of a CPU group */
234     void cpu_group_start_all_cpu(cpu_group_t *group)
235     {
236 dpavlin 7 cpu_gen_t *cpu;
237 dpavlin 1
238     for(cpu=group->cpu_list;cpu;cpu=cpu->next)
239     cpu_start(cpu);
240     }
241    
242     /* Stop all CPUs of a CPU group */
243     void cpu_group_stop_all_cpu(cpu_group_t *group)
244     {
245 dpavlin 7 cpu_gen_t *cpu;
246 dpavlin 1
247     for(cpu=group->cpu_list;cpu;cpu=cpu->next)
248     cpu_stop(cpu);
249     }
250    
251     /* Set a state of all CPUs of a CPU group */
252     void cpu_group_set_state(cpu_group_t *group,u_int state)
253     {
254 dpavlin 7 cpu_gen_t *cpu;
255 dpavlin 1
256     for(cpu=group->cpu_list;cpu;cpu=cpu->next)
257     cpu->state = state;
258     }
259    
260     /* Returns TRUE if all CPUs in a CPU group are inactive */
261     static int cpu_group_check_activity(cpu_group_t *group)
262     {
263 dpavlin 7 cpu_gen_t *cpu;
264 dpavlin 1
265     for(cpu=group->cpu_list;cpu;cpu=cpu->next) {
266     if (!cpu->cpu_thread_running)
267     continue;
268    
269 dpavlin 7 if ((cpu->state == CPU_STATE_RUNNING) || !cpu->seq_state)
270 dpavlin 1 return(FALSE);
271     }
272    
273     return(TRUE);
274     }
275    
276     /* Synchronize on CPUs (all CPUs must be inactive) */
277     int cpu_group_sync_state(cpu_group_t *group)
278     {
279 dpavlin 7 cpu_gen_t *cpu;
280 dpavlin 1 m_tmcnt_t t1,t2;
281    
282     /* Check that CPU activity is really suspended */
283     t1 = m_gettime();
284    
285     for(cpu=group->cpu_list;cpu;cpu=cpu->next)
286     cpu->seq_state = 0;
287    
288     while(!cpu_group_check_activity(group)) {
289     t2 = m_gettime();
290    
291     if (t2 > (t1 + 10000))
292     return(-1);
293    
294     usleep(50000);
295     }
296    
297     return(0);
298     }
299    
300     /* Save state of all CPUs */
301     int cpu_group_save_state(cpu_group_t *group)
302     {
303 dpavlin 7 cpu_gen_t *cpu;
304 dpavlin 1
305     for(cpu=group->cpu_list;cpu;cpu=cpu->next)
306     cpu->prev_state = cpu->state;
307    
308     return(TRUE);
309     }
310    
311     /* Restore state of all CPUs */
312     int cpu_group_restore_state(cpu_group_t *group)
313     {
314 dpavlin 7 cpu_gen_t *cpu;
315 dpavlin 1
316     for(cpu=group->cpu_list;cpu;cpu=cpu->next)
317     cpu->state = cpu->prev_state;
318    
319     return(TRUE);
320     }
321 dpavlin 7
322     /* Virtual idle loop */
323     void cpu_idle_loop(cpu_gen_t *cpu)
324     {
325     struct timespec t_spc;
326     m_tmcnt_t expire;
327    
328     expire = m_gettime_usec() + cpu->idle_sleep_time;
329    
330     pthread_mutex_lock(&cpu->idle_mutex);
331     t_spc.tv_sec = expire / 1000000;
332     t_spc.tv_nsec = (expire % 1000000) * 1000;
333     pthread_cond_timedwait(&cpu->idle_cond,&cpu->idle_mutex,&t_spc);
334     pthread_mutex_unlock(&cpu->idle_mutex);
335     }
336    
337     /* Break idle wait state */
338     void cpu_idle_break_wait(cpu_gen_t *cpu)
339     {
340     pthread_cond_signal(&cpu->idle_cond);
341     cpu->idle_count = 0;
342     }

  ViewVC Help
Powered by ViewVC 1.1.26