/[dynamips]/upstream/dynamips-0.2.7-RC1/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

Contents of /upstream/dynamips-0.2.7-RC1/cpu.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 7 - (show annotations)
Sat Oct 6 16:23:47 2007 UTC (12 years, 1 month ago) by dpavlin
File MIME type: text/plain
File size: 7206 byte(s)
dynamips-0.2.7-RC1

1 /*
2 * Cisco router 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 "cpu.h"
21 #include "memory.h"
22 #include "device.h"
23 #include "mips64.h"
24 #include "mips64_cp0.h"
25 #include "mips64_exec.h"
26 #include "mips64_jit.h"
27 #include "ppc32.h"
28 #include "ppc32_exec.h"
29 #include "ppc32_jit.h"
30 #include "dynamips.h"
31 #include "vm.h"
32
33 /* Find a CPU in a group given its ID */
34 cpu_gen_t *cpu_group_find_id(cpu_group_t *group,u_int id)
35 {
36 cpu_gen_t *cpu;
37
38 if (!group)
39 return NULL;
40
41 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 cpu_gen_t *cpu;
52 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 int cpu_group_add(cpu_group_t *group,cpu_gen_t *cpu)
67 {
68 if (!group)
69 return(-1);
70
71 /* 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 cpu_gen_t *cpu,*next;
100
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 cpu_gen_t *cpu;
115
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 void cpu_log(cpu_gen_t *cpu,char *module,char *format,...)
124 {
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 cpu_gen_t *cpu_create(vm_instance_t *vm,u_int type,u_int id)
136 {
137 void *(*cpu_run_fn)(void *);
138 cpu_gen_t *cpu;
139
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 cpu->type = type;
147 cpu->state = CPU_STATE_SUSPENDED;
148
149 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 }
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 void cpu_delete(cpu_gen_t *cpu)
194 {
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 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 }
213 }
214
215 /* Start a CPU */
216 void cpu_start(cpu_gen_t *cpu)
217 {
218 if (cpu) {
219 cpu_log(cpu,"CPU_STATE","Starting CPU (old state=%u)...\n",cpu->state);
220 cpu->state = CPU_STATE_RUNNING;
221 }
222 }
223
224 /* Stop a CPU */
225 void cpu_stop(cpu_gen_t *cpu)
226 {
227 if (cpu) {
228 cpu_log(cpu,"CPU_STATE","Halting CPU (old state=%u)...\n",cpu->state);
229 cpu->state = CPU_STATE_HALTED;
230 }
231 }
232
233 /* Start all CPUs of a CPU group */
234 void cpu_group_start_all_cpu(cpu_group_t *group)
235 {
236 cpu_gen_t *cpu;
237
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 cpu_gen_t *cpu;
246
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 cpu_gen_t *cpu;
255
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 cpu_gen_t *cpu;
264
265 for(cpu=group->cpu_list;cpu;cpu=cpu->next) {
266 if (!cpu->cpu_thread_running)
267 continue;
268
269 if ((cpu->state == CPU_STATE_RUNNING) || !cpu->seq_state)
270 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 cpu_gen_t *cpu;
280 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 cpu_gen_t *cpu;
304
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 cpu_gen_t *cpu;
315
316 for(cpu=group->cpu_list;cpu;cpu=cpu->next)
317 cpu->state = cpu->prev_state;
318
319 return(TRUE);
320 }
321
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