Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Keeping interfaces clean (avoid loading maxmin_private)
[simgrid.git] / src / smpi / src / smpi_base.c
1 #include <stdio.h>
2
3 #include <signal.h>
4 #include <sys/time.h>
5 #include "xbt/xbt_os_time.h"
6 #include "simix/simix.h"
7 #include "simix/private.h"
8 #include "smpi.h"
9
10 // FIXME: move globals into structure...
11
12 xbt_mallocator_t smpi_request_mallocator      = NULL;
13 xbt_mallocator_t smpi_message_mallocator      = NULL;
14
15 xbt_fifo_t *smpi_pending_send_requests        = NULL;
16 smx_mutex_t *smpi_pending_send_requests_mutex = NULL;
17
18 xbt_fifo_t *smpi_pending_recv_requests        = NULL;
19 smx_mutex_t *smpi_pending_recv_requests_mutex = NULL;
20
21 xbt_fifo_t *smpi_received_messages            = NULL;
22 smx_mutex_t *smpi_received_messages_mutex     = NULL;
23
24 smx_process_t *smpi_sender_processes        = NULL;
25 smx_process_t *smpi_receiver_processes      = NULL;
26
27 int smpi_running_hosts = 0;
28
29 smpi_mpi_communicator_t smpi_mpi_comm_world;
30
31 smpi_mpi_status_t smpi_mpi_status_ignore;
32
33 smpi_mpi_datatype_t smpi_mpi_byte;
34 smpi_mpi_datatype_t smpi_mpi_int;
35 smpi_mpi_datatype_t smpi_mpi_double;
36
37 smpi_mpi_op_t smpi_mpi_land;
38 smpi_mpi_op_t smpi_mpi_sum;
39
40 static xbt_os_timer_t smpi_timer;
41 static int smpi_benchmarking;
42 static double smpi_reference_speed;
43
44 // mutexes
45 smx_mutex_t smpi_running_hosts_mutex = NULL;
46 smx_mutex_t smpi_benchmarking_mutex  = NULL;
47 smx_mutex_t init_mutex = NULL;
48 smx_cond_t init_cond  = NULL;
49
50 int smpi_root_ready = 0;
51 int smpi_ready_count = 0;
52
53 XBT_LOG_NEW_DEFAULT_CATEGORY(smpi, "SMPI");
54
55 int inline smpi_mpi_comm_size(smpi_mpi_communicator_t *comm) 
56 {
57         return comm->size;
58 }
59
60 // FIXME: smarter algorithm?
61 int smpi_mpi_comm_rank(smpi_mpi_communicator_t *comm, smx_host_t host)
62 {
63         int i;
64
65         for(i = comm->size - 1; i > 0 && host != comm->hosts[i]; i--);
66
67         return i;
68 }
69
70 int inline smpi_mpi_comm_rank_self(smpi_mpi_communicator_t *comm)
71 {
72         return smpi_mpi_comm_rank(comm, SIMIX_host_self());
73 }
74
75 int inline smpi_mpi_comm_world_rank_self()
76 {
77         return smpi_mpi_comm_rank(&smpi_mpi_comm_world, SIMIX_host_self())
78 }
79
80 int smpi_sender(int argc, char **argv)
81 {
82         smx_process_t self;
83         smx_host_t shost;
84         int rank;
85         xbt_fifo_t request_queue;
86         smx_mutex_t request_queue_mutex;
87         int size;
88         int running_hosts = 0;
89         smpi_mpi_request_t *request;
90         smx_host_t dhost;
91         smx_action_t communicate_action;
92         smpi_received_message_t *scratch;
93         int drank;
94         smx_process_t waitproc;
95
96         self  = SIMIX_process_self();
97         shost = SIMIX_host_self();
98         rank  = smpi_mpi_comm_rank(&smpi_mpi_comm_world, shost);
99
100         // make sure root is done before own initialization
101         SIMIX_mutex_lock(init_mutex);
102         if (!smpi_root_ready) {
103                 SIMIX_cond_wait(init_cond, init_mutex);
104         }
105         SIMIX_mutex_unlock(init_mutex);
106
107         request_queue       = smpi_pending_send_requests[rank];
108         request_queue_mutex = smpi_pending_send_requests_mutex[rank];
109
110         size = smpi_mpi_comm_size(&smpi_mpi_comm_world);
111
112         smpi_sender_processes[rank] = self;
113
114         // wait for all nodes to signal initializatin complete
115         SIMIX_mutex_lock(init_mutex);
116         smpi_ready_count++;
117         if (smpi_ready_count < 3 * size) {
118                 SIMIX_cond_wait(init_cond, init_mutex);
119         } else {
120                 SIMIX_cond_broadcast(init_cond);
121         }
122         SIMIX_mutex_unlock(init_mutex);
123
124         SIMIX_mutex_lock(smpi_running_hosts_mutex);
125         running_hosts = smpi_running_hosts;
126         SIMIX_mutex_unlock(smpi_running_hosts_mutex);
127
128         while (0 < running_hosts) {
129
130                 SIMIX_mutex_lock(request_queue_mutex);
131                 request = xbt_fifo_shift(request_queue);
132                 SIMIX_mutex_unlock(request_queue_mutex);
133
134                 if (NULL == request) {
135                         SIMIX_process_suspend(self);
136                 } else {
137                         SIMIX_mutex_lock(request->mutex);
138
139                         dhost = request->comm->hosts[request->dst];
140
141                         // FIXME: not at all sure I can assume magic just happens here....
142                         communicate_action = SIMIX_action_communicate(shost, dhost,
143                                 "communication", request->datatype->size * request->count * 1.0, -1.0);
144
145                         SIMIX_register_condition_to_action(communicate_action, request->cond);
146                         SIMIX_register_action_to_condition(communicate_action, request->cond);
147
148                         SIMIX_cond_wait(request->cond, request->mutex);
149
150                         // copy request to appropriate received queue
151                         scratch = xbt_mallocator_get(smpi_message_mallocator);
152                         scratch->comm = request->comm;
153                         scratch->src  = request->src;
154                         scratch->dst  = request->dst;
155                         scratch->tag  = request->tag;
156                         scratch->buf  = request->buf;
157                         drank = smpi_mpi_comm_rank(&smpi_mpi_comm_world, dhost);
158                         SIMIX_mutex_lock(smpi_received_messages_mutex[drank]);
159                         xbt_fifo_push(smpi_received_messages[drank], scratch);
160                         SIMIX_mutex_unlock(smpi_received_messages_mutex[drank]);
161
162                         request->completed = 1;
163
164                         // wake up receiver, then any waiting sender
165                         waitproc = smpi_receiver_processes[drank];
166
167                         do {
168                                 if (SIMIX_process_is_suspended(waitproc)) {
169                                         SIMIX_process_resume(waitproc);
170                                 }
171                         } while(waitproc = xbt_fifo_shift(request->waitlist));
172
173                         SIMIX_mutex_unlock(request->mutex);
174                 }
175
176                 SIMIX_mutex_lock(smpi_running_hosts_mutex);
177                 running_hosts = smpi_running_hosts;
178                 SIMIX_mutex_unlock(smpi_running_hosts_mutex);
179         }
180
181         return 0;
182 }
183
184 int smpi_receiver(int argc, char **argv)
185 {
186         smx_process_t self;
187         int rank;
188         xbt_fifo_t request_queue;
189         smx_mutex_t request_queue_mutex;
190         xbt_fifo_t message_queue;
191         smx_mutex_t message_queue_mutex;
192         int size;
193         int running_hosts;
194         xbt_fifo_item_t request_item, message_item;
195         smpi_mpi_request_t *request;
196         smpi_received_message_t *message;
197         smx_process_t waitproc;
198
199         self  = SIMIX_process_self();
200         rank  = smpi_mpi_comm_world_rank_self();
201
202         // make sure root is done before own initialization
203         SIMIX_mutex_lock(init_mutex);
204         if (!smpi_root_ready) {
205                 SIMIX_cond_wait(init_cond, init_mutex);
206         }
207         SIMIX_mutex_unlock(init_mutex);
208
209         request_queue       = smpi_pending_recv_requests[rank];
210         request_queue_mutex = smpi_pending_recv_requests_mutex[rank];
211
212         message_queue       = smpi_received_messages[rank];
213         message_queue_mutex = smpi_received_messages_mutex[rank];
214
215         size = smpi_mpi_comm_size(&smpi_mpi_comm_world);
216         smpi_receiver_processes[rank] = self;
217
218         // wait for all nodes to signal initializatin complete
219         SIMIX_mutex_lock(init_mutex);
220         smpi_ready_count++;
221         if (smpi_ready_count < 3 * size) {
222                 SIMIX_cond_wait(init_cond, init_mutex);
223         } else {
224                 SIMIX_cond_broadcast(init_cond);
225         }
226         SIMIX_mutex_unlock(init_mutex);
227
228         SIMIX_mutex_lock(smpi_running_hosts_mutex);
229         running_hosts = smpi_running_hosts;
230         SIMIX_mutex_unlock(smpi_running_hosts_mutex);
231
232         while (0 < running_hosts) {
233
234                 // FIXME: better algorithm, maybe some kind of balanced tree? or a heap?
235
236                 // FIXME: not the best way to request multiple locks...
237                 SIMIX_mutex_lock(request_queue_mutex);
238                 SIMIX_mutex_lock(message_queue_mutex);
239 search:         for (request_item = xbt_fifo_get_first_item(request_queue);
240                         NULL != request_item;
241                         request_item = xbt_fifo_get_next_item(request_item)) {
242                         request = xbt_fifo_get_item_content(request_item);
243                         for (message_item = xbt_fifo_get_first_item(message_queue);
244                                 NULL != message_item;
245                                 message_item = xbt_fifo_get_next_item(message_item)) {
246                                 message = xbt_fifo_get_item_content(message_item);
247                                 if (request->comm == message->comm &&
248                                                 (MPI_ANY_SOURCE == request->src || request->src == message->src) &&
249                                                 request->tag == message->tag) {
250                                         xbt_fifo_remove_item(request_queue, request_item);
251                                         xbt_fifo_remove_item(message_queue, message_item);
252                                         break search;
253                                 }
254                         }
255                 }
256                 SIMIX_mutex_unlock(message_queue_mutex);
257                 SIMIX_mutex_unlock(request_queue_mutex);
258
259                 if (NULL == request || NULL == message) {
260                         SIMIX_process_suspend(self);
261                 } else {
262                         SIMIX_mutex_lock(request->mutex);
263                         memcpy(request->buf, message->buf, request->count * request->datatype->size);
264                         request->src = message->src;
265                         request->completed = 1;
266
267                         while (waitproc = xbt_fifo_shift(request->waitlist)) {
268                                 if (SIMIX_process_is_suspended(waitproc)) {
269                                         SIMIX_process_resume(waitproc);
270                                 }
271                         }
272                         SIMIX_mutex_unlock(request->mutex);
273
274                         xbt_mallocator_release(smpi_message_mallocator, message);
275                 }
276
277                 SIMIX_mutex_lock(smpi_running_hosts_mutex);
278                 running_hosts = smpi_running_hosts;
279                 SIMIX_mutex_unlock(smpi_running_hosts_mutex);
280         }
281
282         return 0;
283 }
284
285 int smpi_run_simulation(int argc, char **argv)
286 {
287         smx_cond_t   cond           = NULL;
288         smx_action_t action         = NULL;
289
290         xbt_fifo_t   actions_failed = xbt_fifo_new();
291         xbt_fifo_t   actions_done   = xbt_fifo_new();
292
293         srand(SMPI_RAND_SEED);
294
295         SIMIX_global_init(&argc, argv);
296
297         init_mutex = SIMIX_mutex_init();
298         init_cond  = SIMIX_cond_init();
299
300         SIMIX_function_register("smpi_simulated_main", smpi_simulated_main);
301         SIMIX_function_register("smpi_sender", smpi_sender);
302         SIMIX_function_register("smpi_receiver", smpi_receiver);
303         SIMIX_create_environment(argv[1]);
304         SIMIX_launch_application(argv[2]);
305
306         /* Prepare to display some more info when dying on Ctrl-C pressing */
307         //signal(SIGINT, inthandler);
308
309         /* Clean IO before the run */
310         fflush(stdout);
311         fflush(stderr);
312
313         while (SIMIX_solve(actions_done, actions_failed) != -1.0) {
314                 while (action = xbt_fifo_pop(actions_failed)) {
315                         DEBUG1("** %s failed **", action->name);
316                         while (cond = xbt_fifo_pop(action->cond_list)) {
317                                 SIMIX_cond_broadcast(cond);
318                         }
319                         SIMIX_action_destroy(action);
320                 }
321                 while (action = xbt_fifo_pop(actions_done)) {
322                         DEBUG1("** %s done **",action->name);
323                         while (cond = xbt_fifo_pop(action->cond_list)) {
324                                 SIMIX_cond_broadcast(cond);
325                         }
326                         SIMIX_action_destroy(action);
327                 }
328         }
329         xbt_fifo_free(actions_failed);
330         xbt_fifo_free(actions_done);
331         INFO1("simulation time %g", SIMIX_get_clock());
332         SIMIX_clean();
333         return 0;
334 }
335
336 void smpi_mpi_land_func(void *x, void *y, void *z)
337 {
338         *(int *)z = *(int *)x && *(int *)y;
339 }
340
341 void smpi_mpi_sum_func(void *x, void *y, void *z)
342 {
343         *(int *)z = *(int *)x + *(int *)y;
344 }
345
346 smpi_mpi_request_t *smpi_new_request()
347 {
348         return xbt_new(smpi_mpi_request_t, 1);
349 }
350
351 void smpi_mpi_init()
352 {
353         int i;
354         int size;
355         smx_process_t process;
356         smx_host_t *hosts;
357         smx_host_t host;
358         double duration;
359
360         // initialize some local variables
361         host  = SIMIX_host_self();
362         hosts = SIMIX_host_get_table();
363         size  = SIMIX_host_get_number();
364
365         // node 0 sets the globals
366         if (host == hosts[0]) {
367
368                 // processes
369                 smpi_sender_processes             = xbt_new(smx_process_t, size);
370                 smpi_receiver_processes           = xbt_new(smx_process_t, size);
371
372                 // running hosts
373                 smpi_running_hosts_mutex          = SIMIX_mutex_init();
374                 smpi_running_hosts                = size;
375
376                 // global communicator
377                 smpi_mpi_comm_world.size          = size;
378                 smpi_mpi_comm_world.barrier       = 0;
379                 smpi_mpi_comm_world.barrier_mutex = SIMIX_mutex_init();
380                 smpi_mpi_comm_world.barrier_cond  = SIMIX_cond_init();
381                 smpi_mpi_comm_world.hosts         = hosts;
382                 smpi_mpi_comm_world.processes     = xbt_new(smx_process_t, size);
383                 smpi_mpi_comm_world.processes[0]  = SIMIX_process_self();
384
385                 // mpi datatypes
386                 smpi_mpi_byte.size                = (size_t)1;
387                 smpi_mpi_int.size                 = sizeof(int);
388                 smpi_mpi_double.size              = sizeof(double);
389
390                 // mpi operations
391                 smpi_mpi_land.func                = &smpi_mpi_land_func;
392                 smpi_mpi_sum.func                 = &smpi_mpi_sum_func;
393
394                 // smpi globals
395                 smpi_request_mallocator           = xbt_mallocator_new(SMPI_REQUEST_MALLOCATOR_SIZE, smpi_new_request, xbt_free, NULL);
396                 smpi_message_mallocator           = xbt_mallocator_new(SMPI_MESSAGE_MALLOCATOR_SIZE, smpi_new_message, xbt_free, NULL);
397                 smpi_pending_send_requests        = xbt_new(xbt_fifo_t,  size);
398                 smpi_pending_send_requests_mutex  = xbt_new(smx_mutex_t, size);
399                 smpi_pending_recv_requests        = xbt_new(xbt_fifo_t,  size);
400                 smpi_pending_recv_requests_mutex  = xbt_new(smx_mutex_t, size);
401                 smpi_received_messages            = xbt_new(xbt_fifo_t,  size);
402                 smpi_received_messages_mutex      = xbt_new(smx_mutex_t, size);
403
404                 for(i = 0; i < size; i++) {
405                         smpi_pending_send_requests[i]       = xbt_fifo_new();
406                         smpi_pending_send_requests_mutex[i] = SIMIX_mutex_init();
407                         smpi_pending_recv_requests[i]       = xbt_fifo_new();
408                         smpi_pending_recv_requests_mutex[i] = SIMIX_mutex_init();
409                         smpi_received_messages[i]           = xbt_fifo_new();
410                         smpi_received_messages_mutex[i]     = SIMIX_mutex_init();
411                 }
412
413                 smpi_timer                      = xbt_os_timer_new();
414                 smpi_reference_speed            = SMPI_DEFAULT_SPEED;
415                 smpi_benchmarking               = 0;
416                 smpi_benchmarking_mutex         = SIMIX_mutex_init();
417
418                 // signal all nodes to perform initialization
419                 SIMIX_mutex_lock(init_mutex);
420                 smpi_root_ready = 1;
421                 SIMIX_cond_broadcast(init_cond);
422                 SIMIX_mutex_unlock(init_mutex);
423
424         } else {
425
426                 // make sure root is done before own initialization
427                 SIMIX_mutex_lock(init_mutex);
428                 if (!smpi_root_ready) {
429                         SIMIX_cond_wait(init_cond, init_mutex);
430                 }
431                 SIMIX_mutex_unlock(init_mutex);
432
433                 smpi_mpi_comm_world.processes[smpi_mpi_comm_rank_self(&smpi_mpi_comm_world)] = SIMIX_process_self();
434
435         }
436
437         // wait for all nodes to signal initializatin complete
438         SIMIX_mutex_lock(init_mutex);
439         smpi_ready_count++;
440         if (smpi_ready_count < 3 * size) {
441                 SIMIX_cond_wait(init_cond, init_mutex);
442         } else {
443                 SIMIX_cond_broadcast(init_cond);
444         }
445         SIMIX_mutex_unlock(init_mutex);
446
447 }
448
449 void smpi_mpi_finalize()
450 {
451         int i;
452
453         SIMIX_mutex_lock(smpi_running_hosts_mutex);
454         i = --smpi_running_hosts;
455         SIMIX_mutex_unlock(smpi_running_hosts_mutex);
456
457         if (0 >= i) {
458
459                 SIMIX_mutex_destroy(smpi_running_hosts_mutex);
460
461                 for (i = 0 ; i < smpi_mpi_comm_world.size; i++) {
462                         xbt_fifo_free(smpi_pending_send_requests[i]);
463                         SIMIX_mutex_destroy(smpi_pending_send_requests_mutex[i]);
464                         xbt_fifo_free(smpi_pending_recv_requests[i]);
465                         SIMIX_mutex_destroy(smpi_pending_recv_requests_mutex[i]);
466                         xbt_fifo_free(smpi_received_messages[i]);
467                         SIMIX_mutex_destroy(smpi_received_messages_mutex[i]);
468                 }
469
470                 xbt_mallocator_free(smpi_request_mallocator);
471                 xbt_mallocator_free(smpi_message_mallocator);
472                 xbt_free(smpi_pending_send_requests);
473                 xbt_free(smpi_pending_send_requests_mutex);
474                 xbt_free(smpi_pending_recv_requests);
475                 xbt_free(smpi_pending_recv_requests_mutex);
476                 xbt_free(smpi_received_messages);
477                 xbt_free(smpi_received_messages_mutex);
478
479                 SIMIX_mutex_destroy(smpi_mpi_comm_world.barrier_mutex);
480                 SIMIX_cond_destroy(smpi_mpi_comm_world.barrier_cond);
481                 xbt_free(smpi_mpi_comm_world.processes);
482
483                 xbt_os_timer_free(smpi_timer);
484         }
485
486 }
487
488 void smpi_bench_begin()
489 {
490         xbt_assert0(!smpi_benchmarking, "Already benchmarking");
491         smpi_benchmarking = 1;
492         xbt_os_timer_start(smpi_timer);
493         return;
494 }
495
496 void smpi_bench_end()
497 {
498         double duration;
499         smx_host_t host;
500         smx_action_t compute_action;
501         smx_mutex_t mutex;
502         smx_cond_t cond;
503
504         xbt_assert0(smpi_benchmarking, "Not benchmarking yet");
505         smpi_benchmarking = 0;
506         xbt_os_timer_stop(smpi_timer);
507         duration = xbt_os_timer_elapsed(smpi_timer);
508         host           = SIMIX_host_self();
509         compute_action = SIMIX_action_execute(host, "computation", duration * SMPI_DEFAULT_SPEED);
510         mutex          = SIMIX_mutex_init();
511         cond           = SIMIX_cond_init();
512         SIMIX_mutex_lock(mutex);
513         SIMIX_register_condition_to_action(compute_action, cond);
514         SIMIX_register_action_to_condition(compute_action, cond);
515         SIMIX_cond_wait(cond, mutex);
516         SIMIX_mutex_unlock(mutex);
517         SIMIX_mutex_destroy(mutex);
518         SIMIX_cond_destroy(cond);
519         // FIXME: check for success/failure?
520         return;
521 }
522
523 void smpi_barrier(smpi_mpi_communicator_t *comm) {
524         int i;
525         SIMIX_mutex_lock(comm->barrier_mutex);
526         comm->barrier++;
527         if(i < comm->size) {
528                 SIMIX_cond_wait(comm->barrier_cond, comm->barrier_mutex);
529         } else {
530                 comm->barrier = 0;
531                 SIMIX_cond_broadcast(comm->barrier_cond);
532         }
533         SIMIX_mutex_unlock(comm->barrier_mutex);
534 }
535
536 int smpi_comm_rank(smpi_mpi_communicator_t *comm, smx_host_t host)
537 {
538         int i;
539         for(i = 0; i < comm->size && host != comm->hosts[i]; i++);
540         if (i >= comm->size) i = -1;
541         return i;
542 }
543
544 int smpi_create_request(void *buf, int count, smpi_mpi_datatype_t *datatype,
545         int src, int dst, int tag, smpi_mpi_communicator_t *comm, smpi_mpi_request_t **request)
546 {
547         int retval = MPI_SUCCESS;
548
549         *request = NULL;
550
551         if (0 > count) {
552                 retval = MPI_ERR_COUNT;
553         } else if (NULL == buf) {
554                 retval = MPI_ERR_INTERN;
555         } else if (NULL == datatype) {
556                 retval = MPI_ERR_TYPE;
557         } else if (NULL == comm) {
558                 retval = MPI_ERR_COMM;
559         } else if (MPI_ANY_SOURCE != src && (0 > src || comm->size <= src)) {
560                 retval = MPI_ERR_RANK;
561         } else if (0 > dst || comm->size <= dst) {
562                 retval = MPI_ERR_RANK;
563         } else if (0 > tag) {
564                 retval = MPI_ERR_TAG;
565         } else {
566                 *request = xbt_mallocator_get(smpi_request_mallocator);
567                 (*request)->comm       = comm;
568                 (*request)->src        = src;
569                 (*request)->dst        = dst;
570                 (*request)->tag        = tag;
571                 (*request)->buf        = buf;
572                 (*request)->count      = count;
573                 (*request)->datatype   = datatype;
574                 (*request)->completed  = 0;
575                 (*request)->mutex      = SIMIX_mutex_init();
576                 (*request)->cond       = SIMIX_cond_init();
577                 (*request)->waitlist   = NULL;
578         }
579         return retval;
580 }
581
582 int smpi_isend(smpi_mpi_request_t *request)
583 {
584         int rank = smpi_mpi_comm_rank_self(&smpi_mpi_comm_world);
585
586         SIMIX_mutex_lock(smpi_pending_send_requests_mutex[rank]);
587         xbt_fifo_push(smpi_pending_send_requests[rank], request);
588         SIMIX_mutex_unlock(smpi_pending_send_requests_mutex[rank]);
589
590         if (MSG_process_is_suspended(smpi_sender_processes[rank])) {
591                 MSG_process_resume(smpi_sender_processes[rank]);
592         }
593 }
594
595 int smpi_irecv(smpi_mpi_request_t *request)
596 {
597         int rank = smpi_mpi_comm_rank_self(&smpi_mpi_comm_world);
598
599         SIMIX_mutex_lock(smpi_pending_recv_requests_mutex[rank]);
600         xbt_fifo_push(smpi_pending_recv_requests[rank], request);
601         SIMIX_mutex_unlock(smpi_pending_recv_requests_mutex[rank]);
602
603         if (MSG_process_is_suspended(smpi_receiver_processes[rank])) {
604                 MSG_process_resume(smpi_receiver_processes[rank]);
605         }
606 }
607
608 void smpi_wait(smpi_mpi_request_t *request, smpi_mpi_status_t *status)
609 {
610         smx_process_t self;
611         int suspend = 0;
612         self = SIMIX_process_self();
613
614         if (NULL != request) {
615                 SIMIX_mutex_lock(request->mutex);
616                 if (!request->completed) {
617                         xbt_fifo_push(request->waitlist, self);
618                         suspend = 1;
619                 }
620                 SIMIX_mutex_unlock(request->mutex);
621                 if (suspend) {
622                         SIMIX_suspend(self);
623                 }
624                 if (NULL != status && MPI_STATUS_IGNORE != status) {
625                         SIMIX_mutex_lock(request->mutex);
626                         status->MPI_SOURCE = request->src;
627                         SIMIX_mutex_unlock(request->mutex);
628                 }
629         }
630 }
631
632 // FIXME: move into own file
633 int smpi_gettimeofday(struct timeval *tv, struct timezone *tz)
634 {
635         double now;
636         int retval = 0;
637         smpi_bench_end();
638         if (NULL == tv) {
639                 retval = -1;
640         } else {
641                 now = SIMIX_get_clock();
642                 tv->tv_sec  = now;
643                 tv->tv_usec = ((now - (double)tv->tv_sec) * 1000000.0);
644         }
645         smpi_bench_begin();
646         return retval;
647 }
648
649 unsigned int smpi_sleep(unsigned int seconds)
650 {
651         smx_mutex_t mutex;
652         smx_cond_t cond;
653         smx_host_t host;
654         smx_action_t sleep_action;
655
656         smpi_bench_end();
657         host         = SIMIX_host_self();
658         sleep_action = SIMIX_action_sleep(host, seconds);
659         mutex        = SIMIX_mutex_init();
660         cond         = SIMIX_cond_init();
661         SIMIX_mutex_lock(mutex);
662         SIMIX_register_condition_to_action(sleep_action, cond);
663         SIMIX_register_action_to_condition(sleep_action, cond);
664         SIMIX_cond_wait(cond, mutex);
665         SIMIX_mutex_unlock(mutex);
666         SIMIX_mutex_destroy(mutex);
667         SIMIX_cond_destroy(cond);
668         // FIXME: check for success/failure?
669         smpi_bench_begin();
670         return 0;
671 }
672
673 void smpi_exit(int status)
674 {
675         smpi_bench_end();
676         SIMIX_mutex_lock(smpi_running_hosts_mutex);
677         smpi_running_hosts--;
678         SIMIX_mutex_unlock(smpi_running_hosts_mutex);
679         SIMIX_process_kill(SIMIX_process_self());
680         return;
681 }