Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
a80a17fb9952bd610ca107007f052f9d5d9240e9
[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       /* If there is a timeout it will be always enabled because, if the
94        * communication is not ready, it can timeout.
95        * This avoids false positives on dead-locks */
96       if(req->comm_wait.timeout >= 0)
97         return TRUE;
98
99       act = req->comm_wait.comm;
100       return (act->comm.src_proc && act->comm.dst_proc);
101       break;
102
103     case REQ_COMM_WAITANY:
104       xbt_dynar_foreach(req->comm_waitany.comms, index, act) {
105         if (act->comm.src_proc && act->comm.dst_proc){
106           return TRUE;
107         }
108       }
109       return FALSE;
110       break;
111
112     default:    
113       return TRUE;
114   }
115 }
116
117 int SIMIX_request_is_enabled_by_idx(smx_req_t req, unsigned int idx)
118 {
119   smx_action_t act;
120
121   switch (req->call) {
122
123     case REQ_COMM_WAIT:
124       /* FIXME: check also that src and dst processes are not suspended */
125       act = req->comm_wait.comm;
126       return (act->comm.src_proc && act->comm.dst_proc);
127       break;
128
129     case REQ_COMM_WAITANY:
130       act = xbt_dynar_get_as(req->comm_waitany.comms, idx, smx_action_t);
131       return (act->comm.src_proc && act->comm.dst_proc);
132       break;
133
134     default:
135       return TRUE;
136   }
137 }
138
139 void SIMIX_request_pre(smx_req_t req, unsigned int value)
140 {
141   switch (req->call) {
142   case REQ_NO_REQ:
143     THROW2(arg_error,0,"Asked to do the noop syscall on %s@%s",
144         SIMIX_process_get_name(req->issuer),
145         SIMIX_host_get_name(SIMIX_process_get_host(req->issuer))
146         );
147     break;
148
149     case REQ_HOST_GET_BY_NAME:
150       req->host_get_by_name.result =
151         SIMIX_host_get_by_name(req->host_get_by_name.name);
152       SIMIX_request_answer(req);
153       break;
154
155     case REQ_HOST_GET_NAME:
156       req->host_get_name.result =       SIMIX_host_get_name(req->host_get_name.host);
157       SIMIX_request_answer(req);
158       break;
159
160     case REQ_HOST_GET_PROPERTIES:
161       req->host_get_properties.result =
162         SIMIX_host_get_properties(req->host_get_properties.host);
163       SIMIX_request_answer(req);
164       break;
165
166     case REQ_HOST_GET_SPEED:
167       req->host_get_speed.result = 
168         SIMIX_host_get_speed(req->host_get_speed.host);
169       SIMIX_request_answer(req);
170       break;
171
172     case REQ_HOST_GET_AVAILABLE_SPEED:
173       req->host_get_available_speed.result =
174         SIMIX_host_get_available_speed(req->host_get_available_speed.host);
175       SIMIX_request_answer(req);
176       break;
177
178     case REQ_HOST_GET_STATE:
179       req->host_get_state.result = 
180         SIMIX_host_get_state(req->host_get_state.host);
181       SIMIX_request_answer(req);
182       break;
183
184     case REQ_HOST_GET_DATA:
185       req->host_get_data.result =       SIMIX_host_get_data(req->host_get_data.host);
186       SIMIX_request_answer(req);
187       break;
188
189     case REQ_HOST_SET_DATA:
190       SIMIX_host_set_data(req->host_set_data.host, req->host_set_data.data);
191       SIMIX_request_answer(req);
192       break;
193
194     case REQ_HOST_EXECUTE:
195       req->host_execute.result = SIMIX_host_execute(
196           req->host_execute.name,
197           req->host_execute.host,
198           req->host_execute.computation_amount);
199       SIMIX_request_answer(req);
200       break;
201
202     case REQ_HOST_PARALLEL_EXECUTE:
203       req->host_parallel_execute.result = SIMIX_host_parallel_execute(
204           req->host_parallel_execute.name,
205           req->host_parallel_execute.host_nb,
206           req->host_parallel_execute.host_list,
207           req->host_parallel_execute.computation_amount,
208           req->host_parallel_execute.communication_amount,
209           req->host_parallel_execute.amount,
210           req->host_parallel_execute.rate);
211       SIMIX_request_answer(req);
212       break;
213
214     case REQ_HOST_EXECUTION_DESTROY:
215       SIMIX_host_execution_destroy(req->host_execution_destroy.execution);
216       SIMIX_request_answer(req);
217       break;
218
219     case REQ_HOST_EXECUTION_CANCEL:
220       SIMIX_host_execution_cancel(req->host_execution_cancel.execution);
221       SIMIX_request_answer(req);
222       break;
223
224     case REQ_HOST_EXECUTION_GET_REMAINS:
225       req->host_execution_get_remains.result =
226         SIMIX_host_execution_get_remains(req->host_execution_get_remains.execution);
227       SIMIX_request_answer(req);
228       break;
229
230     case REQ_HOST_EXECUTION_GET_STATE:
231       req->host_execution_get_state.result =
232         SIMIX_host_execution_get_state(req->host_execution_get_state.execution);
233       SIMIX_request_answer(req);
234       break;
235
236     case REQ_HOST_EXECUTION_SET_PRIORITY:
237       SIMIX_host_execution_set_priority(
238           req->host_execution_set_priority.execution,
239           req->host_execution_set_priority.priority);
240       SIMIX_request_answer(req);
241       break;
242
243     case REQ_HOST_EXECUTION_WAIT:
244       SIMIX_pre_host_execution_wait(req);
245       break;
246
247     case REQ_PROCESS_CREATE:
248       req->process_create.result = SIMIX_process_create(
249           req->process_create.name,
250           req->process_create.code,
251           req->process_create.data,
252           req->process_create.hostname,
253           req->process_create.argc,
254           req->process_create.argv,
255           req->process_create.properties);
256       SIMIX_request_answer(req);
257       break;
258
259     case REQ_PROCESS_KILL:
260       SIMIX_process_kill(req->process_kill.process, req->issuer);
261       SIMIX_request_answer(req);
262       break;
263
264     case REQ_PROCESS_CHANGE_HOST:
265       SIMIX_process_change_host(
266           req->process_change_host.process,
267           req->process_change_host.source,
268           req->process_change_host.dest);
269       SIMIX_request_answer(req);
270       break;
271
272     case REQ_PROCESS_SUSPEND:
273       SIMIX_pre_process_suspend(req);
274       break;
275
276     case REQ_PROCESS_RESUME:
277       SIMIX_process_resume(req->process_resume.process, req->issuer);
278       SIMIX_request_answer(req);
279       break;
280
281     case REQ_PROCESS_COUNT:
282       req->process_count.result = SIMIX_process_count();
283       SIMIX_request_answer(req);
284       break;
285
286     case REQ_PROCESS_GET_DATA:
287       req->process_get_data.result =
288         SIMIX_process_get_data(req->process_get_data.process);
289       SIMIX_request_answer(req);
290       break;
291
292     case REQ_PROCESS_SET_DATA:
293       SIMIX_process_set_data(
294           req->process_set_data.process,
295           req->process_set_data.data);
296       SIMIX_request_answer(req);
297       break;
298
299     case REQ_PROCESS_GET_HOST:
300       req->process_get_host.result = SIMIX_process_get_host(req->process_get_host.process);
301       SIMIX_request_answer(req);
302       break;
303
304     case REQ_PROCESS_GET_NAME:
305       req->process_get_name.result = SIMIX_process_get_name(req->process_get_name.process);
306       SIMIX_request_answer(req);
307       break;
308
309     case REQ_PROCESS_IS_SUSPENDED:
310       req->process_is_suspended.result =
311         SIMIX_process_is_suspended(req->process_is_suspended.process);
312       SIMIX_request_answer(req);
313       break;
314
315     case REQ_PROCESS_GET_PROPERTIES:
316       req->process_get_properties.result =
317         SIMIX_process_get_properties(req->process_get_properties.process);
318       SIMIX_request_answer(req);
319       break;
320
321     case REQ_PROCESS_SLEEP:
322       SIMIX_pre_process_sleep(req);
323       break;
324
325     case REQ_RDV_CREATE:
326       req->rdv_create.result = SIMIX_rdv_create(req->rdv_create.name);
327       SIMIX_request_answer(req);
328       break;
329
330     case REQ_RDV_DESTROY:
331       SIMIX_rdv_destroy(req->rdv_destroy.rdv);
332       SIMIX_request_answer(req);
333       break;
334
335     case REQ_RDV_GEY_BY_NAME:
336       req->rdv_get_by_name.result = 
337         SIMIX_rdv_get_by_name(req->rdv_get_by_name.name);
338       SIMIX_request_answer(req);
339       break;
340
341     case REQ_RDV_COMM_COUNT_BY_HOST:
342       req->rdv_comm_count_by_host.result = SIMIX_rdv_comm_count_by_host(
343           req->rdv_comm_count_by_host.rdv,
344           req->rdv_comm_count_by_host.host);
345       SIMIX_request_answer(req);
346       break;
347
348     case REQ_RDV_GET_HEAD:
349       req->rdv_get_head.result =        SIMIX_rdv_get_head(req->rdv_get_head.rdv);
350       SIMIX_request_answer(req);
351       break;
352
353     case REQ_COMM_ISEND:
354       req->comm_isend.result = SIMIX_comm_isend(
355           req->issuer,
356           req->comm_isend.rdv,
357           req->comm_isend.task_size,
358           req->comm_isend.rate,
359           req->comm_isend.src_buff,
360           req->comm_isend.src_buff_size,
361           req->comm_isend.match_fun,
362           req->comm_isend.data);
363       SIMIX_request_answer(req);
364       break;
365
366     case REQ_COMM_IRECV:
367       req->comm_irecv.result = SIMIX_comm_irecv(
368           req->issuer,
369           req->comm_irecv.rdv,
370           req->comm_irecv.dst_buff,
371           req->comm_irecv.dst_buff_size,
372           req->comm_irecv.match_fun,
373           req->comm_irecv.data);
374       SIMIX_request_answer(req);
375       break;
376
377     case REQ_COMM_DESTROY:
378       SIMIX_comm_destroy(req->comm_destroy.comm);
379       SIMIX_request_answer(req);
380       break;
381
382     case REQ_COMM_CANCEL:
383       SIMIX_comm_cancel(req->comm_cancel.comm);
384       SIMIX_request_answer(req);
385       break;
386
387     case REQ_COMM_WAITANY:
388       SIMIX_pre_comm_waitany(req, value);
389       break;
390
391     case REQ_COMM_WAIT:
392       SIMIX_pre_comm_wait(req);
393       break;
394
395     case REQ_COMM_TEST:
396       SIMIX_pre_comm_test(req);
397       break;
398
399     case REQ_COMM_TESTANY:
400       SIMIX_pre_comm_testany(req, value);
401       break;
402
403     case REQ_COMM_GET_REMAINS:
404       req->comm_get_remains.result = 
405         SIMIX_comm_get_remains(req->comm_get_remains.comm);
406       SIMIX_request_answer(req);
407       break;
408
409     case REQ_COMM_GET_STATE:
410       req->comm_get_state.result = 
411         SIMIX_comm_get_state(req->comm_get_state.comm);
412       SIMIX_request_answer(req);
413       break;
414
415     case REQ_COMM_GET_SRC_DATA:
416       req->comm_get_src_data.result = SIMIX_comm_get_src_data(req->comm_get_src_data.comm);
417       SIMIX_request_answer(req);
418       break;
419
420     case REQ_COMM_GET_DST_DATA:
421       req->comm_get_dst_data.result = SIMIX_comm_get_dst_data(req->comm_get_dst_data.comm);
422       SIMIX_request_answer(req);
423       break;
424
425     case REQ_COMM_GET_SRC_BUFF:
426       req->comm_get_src_buff.result =
427         SIMIX_comm_get_src_buff(req->comm_get_src_buff.comm);
428       SIMIX_request_answer(req);
429       break;
430
431     case REQ_COMM_GET_DST_BUFF:
432       req->comm_get_dst_buff.result =
433         SIMIX_comm_get_dst_buff(req->comm_get_dst_buff.comm);
434       SIMIX_request_answer(req);
435       break;
436
437     case REQ_COMM_GET_SRC_BUFF_SIZE:
438       req->comm_get_src_buff_size.result = 
439         SIMIX_comm_get_src_buff_size(req->comm_get_src_buff_size.comm);
440       SIMIX_request_answer(req);
441       break;
442
443     case REQ_COMM_GET_DST_BUFF_SIZE:
444       req->comm_get_dst_buff_size.result =
445         SIMIX_comm_get_dst_buff_size(req->comm_get_dst_buff_size.comm);
446       SIMIX_request_answer(req);
447       break;
448
449     case REQ_COMM_GET_SRC_PROC:
450       req->comm_get_src_proc.result = 
451         SIMIX_comm_get_src_proc(req->comm_get_src_proc.comm);
452       SIMIX_request_answer(req);
453       break;
454
455     case REQ_COMM_GET_DST_PROC:
456       req->comm_get_dst_proc.result =
457         SIMIX_comm_get_dst_proc(req->comm_get_dst_proc.comm);
458       SIMIX_request_answer(req);
459       break;
460
461 #ifdef HAVE_LATENCY_BOUND_TRACKING
462     case REQ_COMM_IS_LATENCY_BOUNDED:
463       req->comm_is_latency_bounded.result =
464         SIMIX_comm_is_latency_bounded(req->comm_is_latency_bounded.comm);
465       SIMIX_request_answer(req);
466       break;
467 #endif
468
469 #ifdef HAVE_TRACING
470     case REQ_SET_CATEGORY:
471       SIMIX_set_category(
472           req->set_category.action,
473           req->set_category.category);
474       SIMIX_request_answer(req);
475       break;
476 #endif
477
478     case REQ_MUTEX_INIT:
479       req->mutex_init.result = SIMIX_mutex_init();
480       SIMIX_request_answer(req);
481       break;
482
483     case REQ_MUTEX_DESTROY:
484       SIMIX_mutex_destroy(req->mutex_destroy.mutex);
485       SIMIX_request_answer(req);
486       break;
487
488     case REQ_MUTEX_LOCK:
489       SIMIX_pre_mutex_lock(req);
490       break;
491
492     case REQ_MUTEX_TRYLOCK:
493       req->mutex_trylock.result =
494               SIMIX_mutex_trylock(req->mutex_trylock.mutex, req->issuer);
495       SIMIX_request_answer(req);
496       break;
497
498     case REQ_MUTEX_UNLOCK:
499       SIMIX_mutex_unlock(req->mutex_unlock.mutex, req->issuer);
500       SIMIX_request_answer(req);
501       break;
502
503     case REQ_COND_INIT:
504       req->cond_init.result = SIMIX_cond_init();
505       SIMIX_request_answer(req);
506       break;
507
508     case REQ_COND_DESTROY:
509       SIMIX_cond_destroy(req->cond_destroy.cond);
510       SIMIX_request_answer(req);
511       break;
512
513     case REQ_COND_SIGNAL:
514       SIMIX_cond_signal(req->cond_signal.cond);
515       SIMIX_request_answer(req);
516       break;
517
518     case REQ_COND_WAIT:
519       SIMIX_pre_cond_wait(req);
520       break;
521
522     case REQ_COND_WAIT_TIMEOUT:
523       SIMIX_pre_cond_wait_timeout(req);
524       break;
525
526     case REQ_COND_BROADCAST:
527       SIMIX_cond_broadcast(req->cond_broadcast.cond);
528       SIMIX_request_answer(req);
529       break;
530
531     case REQ_SEM_INIT:
532       req->sem_init.result = SIMIX_sem_init(req->sem_init.capacity);
533       SIMIX_request_answer(req);
534       break;
535
536     case REQ_SEM_DESTROY:
537       SIMIX_sem_destroy(req->sem_destroy.sem);
538       SIMIX_request_answer(req);
539       break;
540
541     case REQ_SEM_RELEASE:
542       SIMIX_sem_release(req->sem_release.sem);
543       SIMIX_request_answer(req);
544       break;
545
546     case REQ_SEM_WOULD_BLOCK:
547       req->sem_would_block.result =
548         SIMIX_sem_would_block(req->sem_would_block.sem);
549       SIMIX_request_answer(req);
550       break;
551
552     case REQ_SEM_ACQUIRE:
553       SIMIX_pre_sem_acquire(req);
554       break;
555
556     case REQ_SEM_ACQUIRE_TIMEOUT:
557       SIMIX_pre_sem_acquire_timeout(req);
558       break;
559
560     case REQ_SEM_GET_CAPACITY:
561       req->sem_get_capacity.result = 
562         SIMIX_sem_get_capacity(req->sem_get_capacity.sem);
563       SIMIX_request_answer(req);
564       break;
565   }
566 }
567
568 void SIMIX_request_post(smx_action_t action)
569 {
570   switch (action->type) {
571
572     case SIMIX_ACTION_EXECUTE:
573     case SIMIX_ACTION_PARALLEL_EXECUTE:
574       SIMIX_post_host_execute(action);
575       break;
576
577     case SIMIX_ACTION_COMMUNICATE:
578       SIMIX_post_comm(action);
579       break;
580
581     case SIMIX_ACTION_SLEEP:
582       SIMIX_post_process_sleep(action);
583       break;
584
585     case SIMIX_ACTION_SYNCHRO:
586       SIMIX_post_synchro(action);
587       break;
588
589     case SIMIX_ACTION_IO:
590       break;
591   }
592 }