Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Bugfix: the result of waitany calls should be determined by SIMIX_comm_finish
[simgrid.git] / src / simix / smx_smurf.c
1 #include "private.h"
2 #include "xbt/fifo.h"
3 #include "xbt/xbt_os_thread.h"
4
5 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_smurf, simix,
6                                 "Logging specific to SIMIX (SMURF)");
7
8 /* Requests to handle at the end of this round of scheduling user processes */
9 static xbt_heap_t req_todo;
10 /* to protect the write actions in the heap */
11 static xbt_os_mutex_t sync_req_positions;
12
13 void SIMIX_request_init(void)
14 {
15   req_todo = xbt_heap_new(5,NULL);
16   sync_req_positions = xbt_os_mutex_init();
17 }
18
19 void SIMIX_request_destroy(void)
20 {
21   xbt_heap_free(req_todo);
22   xbt_os_mutex_destroy(sync_req_positions);
23 }
24
25 /* FIXME: we may want to save the initialization of issuer... */
26 XBT_INLINE smx_req_t SIMIX_req_mine() {
27   smx_process_t issuer = SIMIX_process_self();
28   return &issuer->request;
29 }
30
31 void SIMIX_request_push()
32 {
33   smx_process_t issuer = SIMIX_process_self();
34   if (issuer != simix_global->maestro_process){
35     issuer->request.issuer = issuer;
36
37     if (smx_parallel_contexts)
38       xbt_os_mutex_acquire(sync_req_positions);
39     xbt_heap_push(req_todo,&issuer->request,issuer->pid);
40     DEBUG4("Pushed request %s (%d) of %s; now %d requests waiting",
41         SIMIX_request_name(issuer->request.call), issuer->request.call,
42         issuer->name,xbt_heap_size(req_todo));
43     if (smx_parallel_contexts)
44       xbt_os_mutex_release(sync_req_positions);
45
46     DEBUG3("Yield process '%s' on request of type %s (%d)", issuer->name,
47         SIMIX_request_name(issuer->request.call), issuer->request.call);
48     SIMIX_process_yield();
49   } else {
50     SIMIX_request_pre(&issuer->request, 0);
51   }
52 }
53
54 smx_req_t SIMIX_request_pop(void)
55 {
56   smx_req_t req = xbt_heap_pop(req_todo);
57   if(req)
58     DEBUG4("Popped request %s (%d) of %s; now %d requests waiting",
59         SIMIX_request_name(req->issuer->request.call),
60         req->issuer->request.call,
61         req->issuer->name,xbt_heap_size(req_todo));
62   return req;
63 }
64
65 void SIMIX_request_answer(smx_req_t req)
66 {
67   if (req->issuer != simix_global->maestro_process){
68     DEBUG2("Answer request %s (%d)", SIMIX_request_name(req->call), req->call);
69     req->issuer->request.call = REQ_NO_REQ;
70     xbt_dynar_push_as(simix_global->process_to_run, smx_process_t, req->issuer);
71   }
72 }
73
74 int SIMIX_request_is_visible(smx_req_t req)
75 {
76   return req->call == REQ_COMM_ISEND
77      || req->call == REQ_COMM_IRECV
78      || req->call == REQ_COMM_WAIT
79      || req->call == REQ_COMM_WAITANY
80      || req->call == REQ_COMM_TEST
81      || req->call == REQ_COMM_TESTANY;
82 }
83
84 int SIMIX_request_is_enabled(smx_req_t req)
85 {
86   unsigned int index = 0;
87   smx_action_t act;
88
89   switch (req->call) {
90
91     case REQ_COMM_WAIT:
92       /* FIXME: check also that src and dst processes are not suspended */
93       act = req->comm_wait.comm;
94       return (act->comm.src_proc && act->comm.dst_proc);
95       break;
96
97     case REQ_COMM_WAITANY:
98       xbt_dynar_foreach(req->comm_waitany.comms, index, act) {
99         if (act->comm.src_proc && act->comm.dst_proc){
100           return TRUE;
101         }
102       }
103       return FALSE;
104       break;
105
106     default:    
107       return TRUE;
108   }
109 }
110
111 int SIMIX_request_is_enabled_by_idx(smx_req_t req, unsigned int idx)
112 {
113   smx_action_t act;
114
115   switch (req->call) {
116
117     case REQ_COMM_WAIT:
118       /* FIXME: check also that src and dst processes are not suspended */
119       act = req->comm_wait.comm;
120       return (act->comm.src_proc && act->comm.dst_proc);
121       break;
122
123     case REQ_COMM_WAITANY:
124       act = xbt_dynar_get_as(req->comm_waitany.comms, idx, smx_action_t);
125       return (act->comm.src_proc && act->comm.dst_proc);
126       break;
127
128     default:
129       return TRUE;
130   }
131 }
132
133 void SIMIX_request_pre(smx_req_t req, unsigned int value)
134 {
135   switch (req->call) {
136   case REQ_NO_REQ:
137     THROW2(arg_error,0,"Asked to do the noop syscall on %s@%s",
138         SIMIX_process_get_name(req->issuer),
139         SIMIX_host_get_name(SIMIX_process_get_host(req->issuer))
140         );
141     break;
142
143     case REQ_HOST_GET_BY_NAME:
144       req->host_get_by_name.result =
145         SIMIX_host_get_by_name(req->host_get_by_name.name);
146       SIMIX_request_answer(req);
147       break;
148
149     case REQ_HOST_GET_NAME:
150       req->host_get_name.result =       SIMIX_host_get_name(req->host_get_name.host);
151       SIMIX_request_answer(req);
152       break;
153
154     case REQ_HOST_GET_PROPERTIES:
155       req->host_get_properties.result =
156         SIMIX_host_get_properties(req->host_get_properties.host);
157       SIMIX_request_answer(req);
158       break;
159
160     case REQ_HOST_GET_SPEED:
161       req->host_get_speed.result = 
162         SIMIX_host_get_speed(req->host_get_speed.host);
163       SIMIX_request_answer(req);
164       break;
165
166     case REQ_HOST_GET_AVAILABLE_SPEED:
167       req->host_get_available_speed.result =
168         SIMIX_host_get_available_speed(req->host_get_available_speed.host);
169       SIMIX_request_answer(req);
170       break;
171
172     case REQ_HOST_GET_STATE:
173       req->host_get_state.result = 
174         SIMIX_host_get_state(req->host_get_state.host);
175       SIMIX_request_answer(req);
176       break;
177
178     case REQ_HOST_GET_DATA:
179       req->host_get_data.result =       SIMIX_host_get_data(req->host_get_data.host);
180       SIMIX_request_answer(req);
181       break;
182
183     case REQ_HOST_SET_DATA:
184       SIMIX_host_set_data(req->host_set_data.host, req->host_set_data.data);
185       SIMIX_request_answer(req);
186       break;
187
188     case REQ_HOST_EXECUTE:
189       req->host_execute.result = SIMIX_host_execute(
190           req->host_execute.name,
191           req->host_execute.host,
192           req->host_execute.computation_amount);
193       SIMIX_request_answer(req);
194       break;
195
196     case REQ_HOST_PARALLEL_EXECUTE:
197       req->host_parallel_execute.result = SIMIX_host_parallel_execute(
198           req->host_parallel_execute.name,
199           req->host_parallel_execute.host_nb,
200           req->host_parallel_execute.host_list,
201           req->host_parallel_execute.computation_amount,
202           req->host_parallel_execute.communication_amount,
203           req->host_parallel_execute.amount,
204           req->host_parallel_execute.rate);
205       SIMIX_request_answer(req);
206       break;
207
208     case REQ_HOST_EXECUTION_DESTROY:
209       SIMIX_host_execution_destroy(req->host_execution_destroy.execution);
210       SIMIX_request_answer(req);
211       break;
212
213     case REQ_HOST_EXECUTION_CANCEL:
214       SIMIX_host_execution_cancel(req->host_execution_cancel.execution);
215       SIMIX_request_answer(req);
216       break;
217
218     case REQ_HOST_EXECUTION_GET_REMAINS:
219       req->host_execution_get_remains.result =
220         SIMIX_host_execution_get_remains(req->host_execution_get_remains.execution);
221       SIMIX_request_answer(req);
222       break;
223
224     case REQ_HOST_EXECUTION_GET_STATE:
225       req->host_execution_get_state.result =
226         SIMIX_host_execution_get_state(req->host_execution_get_state.execution);
227       SIMIX_request_answer(req);
228       break;
229
230     case REQ_HOST_EXECUTION_SET_PRIORITY:
231       SIMIX_host_execution_set_priority(
232           req->host_execution_set_priority.execution,
233           req->host_execution_set_priority.priority);
234       SIMIX_request_answer(req);
235       break;
236
237     case REQ_HOST_EXECUTION_WAIT:
238       SIMIX_pre_host_execution_wait(req);
239       break;
240
241     case REQ_PROCESS_CREATE:
242       req->process_create.result = SIMIX_process_create(
243           req->process_create.name,
244           req->process_create.code,
245           req->process_create.data,
246           req->process_create.hostname,
247           req->process_create.argc,
248           req->process_create.argv,
249           req->process_create.properties);
250       SIMIX_request_answer(req);
251       break;
252
253     case REQ_PROCESS_KILL:
254       SIMIX_process_kill(req->process_kill.process, req->issuer);
255       SIMIX_request_answer(req);
256       break;
257
258     case REQ_PROCESS_CHANGE_HOST:
259       SIMIX_process_change_host(
260           req->process_change_host.process,
261           req->process_change_host.source,
262           req->process_change_host.dest);
263       SIMIX_request_answer(req);
264       break;
265
266     case REQ_PROCESS_SUSPEND:
267       SIMIX_pre_process_suspend(req);
268       break;
269
270     case REQ_PROCESS_RESUME:
271       SIMIX_process_resume(req->process_resume.process, req->issuer);
272       SIMIX_request_answer(req);
273       break;
274
275     case REQ_PROCESS_COUNT:
276       req->process_count.result = SIMIX_process_count();
277       SIMIX_request_answer(req);
278       break;
279
280     case REQ_PROCESS_GET_DATA:
281       req->process_get_data.result =
282         SIMIX_process_get_data(req->process_get_data.process);
283       SIMIX_request_answer(req);
284       break;
285
286     case REQ_PROCESS_SET_DATA:
287       SIMIX_process_set_data(
288           req->process_set_data.process,
289           req->process_set_data.data);
290       SIMIX_request_answer(req);
291       break;
292
293     case REQ_PROCESS_GET_HOST:
294       req->process_get_host.result = SIMIX_process_get_host(req->process_get_host.process);
295       SIMIX_request_answer(req);
296       break;
297
298     case REQ_PROCESS_GET_NAME:
299       req->process_get_name.result = SIMIX_process_get_name(req->process_get_name.process);
300       SIMIX_request_answer(req);
301       break;
302
303     case REQ_PROCESS_IS_SUSPENDED:
304       req->process_is_suspended.result =
305         SIMIX_process_is_suspended(req->process_is_suspended.process);
306       SIMIX_request_answer(req);
307       break;
308
309     case REQ_PROCESS_GET_PROPERTIES:
310       req->process_get_properties.result =
311         SIMIX_process_get_properties(req->process_get_properties.process);
312       SIMIX_request_answer(req);
313       break;
314
315     case REQ_PROCESS_SLEEP:
316       SIMIX_pre_process_sleep(req);
317       break;
318
319     case REQ_RDV_CREATE:
320       req->rdv_create.result = SIMIX_rdv_create(req->rdv_create.name);
321       SIMIX_request_answer(req);
322       break;
323
324     case REQ_RDV_DESTROY:
325       SIMIX_rdv_destroy(req->rdv_destroy.rdv);
326       SIMIX_request_answer(req);
327       break;
328
329     case REQ_RDV_GEY_BY_NAME:
330       req->rdv_get_by_name.result = 
331         SIMIX_rdv_get_by_name(req->rdv_get_by_name.name);
332       SIMIX_request_answer(req);
333       break;
334
335     case REQ_RDV_COMM_COUNT_BY_HOST:
336       req->rdv_comm_count_by_host.result = SIMIX_rdv_comm_count_by_host(
337           req->rdv_comm_count_by_host.rdv,
338           req->rdv_comm_count_by_host.host);
339       SIMIX_request_answer(req);
340       break;
341
342     case REQ_RDV_GET_HEAD:
343       req->rdv_get_head.result =        SIMIX_rdv_get_head(req->rdv_get_head.rdv);
344       SIMIX_request_answer(req);
345       break;
346
347     case REQ_COMM_ISEND:
348       req->comm_isend.result = SIMIX_comm_isend(
349           req->issuer,
350           req->comm_isend.rdv,
351           req->comm_isend.task_size,
352           req->comm_isend.rate,
353           req->comm_isend.src_buff,
354           req->comm_isend.src_buff_size,
355           req->comm_isend.match_fun,
356           req->comm_isend.data);
357       SIMIX_request_answer(req);
358       break;
359
360     case REQ_COMM_IRECV:
361       req->comm_irecv.result = SIMIX_comm_irecv(
362           req->issuer,
363           req->comm_irecv.rdv,
364           req->comm_irecv.dst_buff,
365           req->comm_irecv.dst_buff_size,
366           req->comm_irecv.match_fun,
367           req->comm_irecv.data);
368       SIMIX_request_answer(req);
369       break;
370
371     case REQ_COMM_DESTROY:
372       SIMIX_comm_destroy(req->comm_destroy.comm);
373       SIMIX_request_answer(req);
374       break;
375
376     case REQ_COMM_CANCEL:
377       SIMIX_comm_cancel(req->comm_cancel.comm);
378       SIMIX_request_answer(req);
379       break;
380
381     case REQ_COMM_WAITANY:
382       SIMIX_pre_comm_waitany(req, value);
383       break;
384
385     case REQ_COMM_WAIT:
386       SIMIX_pre_comm_wait(req);
387       break;
388
389     case REQ_COMM_TEST:
390       SIMIX_pre_comm_test(req);
391       break;
392
393     case REQ_COMM_TESTANY:
394       SIMIX_pre_comm_testany(req, value);
395       break;
396
397     case REQ_COMM_GET_REMAINS:
398       req->comm_get_remains.result = 
399         SIMIX_comm_get_remains(req->comm_get_remains.comm);
400       SIMIX_request_answer(req);
401       break;
402
403     case REQ_COMM_GET_STATE:
404       req->comm_get_state.result = 
405         SIMIX_comm_get_state(req->comm_get_state.comm);
406       SIMIX_request_answer(req);
407       break;
408
409     case REQ_COMM_GET_SRC_DATA:
410       req->comm_get_src_data.result = SIMIX_comm_get_src_data(req->comm_get_src_data.comm);
411       SIMIX_request_answer(req);
412       break;
413
414     case REQ_COMM_GET_DST_DATA:
415       req->comm_get_dst_data.result = SIMIX_comm_get_dst_data(req->comm_get_dst_data.comm);
416       SIMIX_request_answer(req);
417       break;
418
419     case REQ_COMM_GET_SRC_BUFF:
420       req->comm_get_src_buff.result =
421         SIMIX_comm_get_src_buff(req->comm_get_src_buff.comm);
422       SIMIX_request_answer(req);
423       break;
424
425     case REQ_COMM_GET_DST_BUFF:
426       req->comm_get_dst_buff.result =
427         SIMIX_comm_get_dst_buff(req->comm_get_dst_buff.comm);
428       SIMIX_request_answer(req);
429       break;
430
431     case REQ_COMM_GET_SRC_BUFF_SIZE:
432       req->comm_get_src_buff_size.result = 
433         SIMIX_comm_get_src_buff_size(req->comm_get_src_buff_size.comm);
434       SIMIX_request_answer(req);
435       break;
436
437     case REQ_COMM_GET_DST_BUFF_SIZE:
438       req->comm_get_dst_buff_size.result =
439         SIMIX_comm_get_dst_buff_size(req->comm_get_dst_buff_size.comm);
440       SIMIX_request_answer(req);
441       break;
442
443     case REQ_COMM_GET_SRC_PROC:
444       req->comm_get_src_proc.result = 
445         SIMIX_comm_get_src_proc(req->comm_get_src_proc.comm);
446       SIMIX_request_answer(req);
447       break;
448
449     case REQ_COMM_GET_DST_PROC:
450       req->comm_get_dst_proc.result =
451         SIMIX_comm_get_dst_proc(req->comm_get_dst_proc.comm);
452       SIMIX_request_answer(req);
453       break;
454
455 #ifdef HAVE_LATENCY_BOUND_TRACKING
456     case REQ_COMM_IS_LATENCY_BOUNDED:
457       req->comm_is_latency_bounded.result =
458         SIMIX_comm_is_latency_bounded(req->comm_is_latency_bounded.comm);
459       SIMIX_request_answer(req);
460       break;
461 #endif
462
463 #ifdef HAVE_TRACING
464     case REQ_SET_CATEGORY:
465       SIMIX_set_category(
466           req->set_category.action,
467           req->set_category.category);
468       SIMIX_request_answer(req);
469       break;
470 #endif
471
472     case REQ_MUTEX_INIT:
473       req->mutex_init.result = SIMIX_mutex_init();
474       SIMIX_request_answer(req);
475       break;
476
477     case REQ_MUTEX_DESTROY:
478       SIMIX_mutex_destroy(req->mutex_destroy.mutex);
479       SIMIX_request_answer(req);
480       break;
481
482     case REQ_MUTEX_LOCK:
483       SIMIX_pre_mutex_lock(req);
484       break;
485
486     case REQ_MUTEX_TRYLOCK:
487       req->mutex_trylock.result =
488               SIMIX_mutex_trylock(req->mutex_trylock.mutex, req->issuer);
489       SIMIX_request_answer(req);
490       break;
491
492     case REQ_MUTEX_UNLOCK:
493       SIMIX_mutex_unlock(req->mutex_unlock.mutex, req->issuer);
494       SIMIX_request_answer(req);
495       break;
496
497     case REQ_COND_INIT:
498       req->cond_init.result = SIMIX_cond_init();
499       SIMIX_request_answer(req);
500       break;
501
502     case REQ_COND_DESTROY:
503       SIMIX_cond_destroy(req->cond_destroy.cond);
504       SIMIX_request_answer(req);
505       break;
506
507     case REQ_COND_SIGNAL:
508       SIMIX_cond_signal(req->cond_signal.cond);
509       SIMIX_request_answer(req);
510       break;
511
512     case REQ_COND_WAIT:
513       SIMIX_pre_cond_wait(req);
514       break;
515
516     case REQ_COND_WAIT_TIMEOUT:
517       SIMIX_pre_cond_wait_timeout(req);
518       break;
519
520     case REQ_COND_BROADCAST:
521       SIMIX_cond_broadcast(req->cond_broadcast.cond);
522       SIMIX_request_answer(req);
523       break;
524
525     case REQ_SEM_INIT:
526       req->sem_init.result = SIMIX_sem_init(req->sem_init.capacity);
527       SIMIX_request_answer(req);
528       break;
529
530     case REQ_SEM_DESTROY:
531       SIMIX_sem_destroy(req->sem_destroy.sem);
532       SIMIX_request_answer(req);
533       break;
534
535     case REQ_SEM_RELEASE:
536       SIMIX_sem_release(req->sem_release.sem);
537       SIMIX_request_answer(req);
538       break;
539
540     case REQ_SEM_WOULD_BLOCK:
541       req->sem_would_block.result =
542         SIMIX_sem_would_block(req->sem_would_block.sem);
543       SIMIX_request_answer(req);
544       break;
545
546     case REQ_SEM_ACQUIRE:
547       SIMIX_pre_sem_acquire(req);
548       break;
549
550     case REQ_SEM_ACQUIRE_TIMEOUT:
551       SIMIX_pre_sem_acquire_timeout(req);
552       break;
553
554     case REQ_SEM_GET_CAPACITY:
555       req->sem_get_capacity.result = 
556         SIMIX_sem_get_capacity(req->sem_get_capacity.sem);
557       SIMIX_request_answer(req);
558       break;
559   }
560 }
561
562 void SIMIX_request_post(smx_action_t action)
563 {
564   switch (action->type) {
565
566     case SIMIX_ACTION_EXECUTE:
567     case SIMIX_ACTION_PARALLEL_EXECUTE:
568       SIMIX_post_host_execute(action);
569       break;
570
571     case SIMIX_ACTION_COMMUNICATE:
572       SIMIX_post_comm(action);
573       break;
574
575     case SIMIX_ACTION_SLEEP:
576       SIMIX_post_process_sleep(action);
577       break;
578
579     case SIMIX_ACTION_SYNCHRO:
580       SIMIX_post_synchro(action);
581       break;
582
583     case SIMIX_ACTION_IO:
584       break;
585   }
586 }