Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
61b606c635c737dea02f4834de47106e0de8dcb4
[simgrid.git] / src / simix / smx_smurf_private.h
1 /* Copyright (c) 2007, 2008, 2009, 2010. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #ifndef _SIMIX_SMURF_PRIVATE_H
8 #define _SIMIX_SMURF_PRIVATE_H
9
10 /********************************* Simcalls *********************************/
11
12 /* we want to build the e_smx_simcall_t enumeration, the table of the
13  * corresponding simcalls string names, and the simcall handlers table
14  * automatically, using macros.
15  * To add a new simcall follow the following syntax:
16  *
17  * SIMCALL_ENUM_ELEMENT(<simcall_enumeration_id>, <simcall_handler_function>)
18  *
19  * */
20
21 #define SIMCALL_LIST1 \
22 SIMCALL_ENUM_ELEMENT(SIMCALL_NONE),\
23 SIMCALL_ENUM_ELEMENT(SIMCALL_HOST_GET_BY_NAME),\
24 SIMCALL_ENUM_ELEMENT(SIMCALL_HOST_GET_NAME),\
25 SIMCALL_ENUM_ELEMENT(SIMCALL_HOST_GET_PROPERTIES),\
26 SIMCALL_ENUM_ELEMENT(SIMCALL_HOST_GET_SPEED),\
27 SIMCALL_ENUM_ELEMENT(SIMCALL_HOST_GET_AVAILABLE_SPEED),\
28 SIMCALL_ENUM_ELEMENT(SIMCALL_HOST_GET_STATE),\
29 SIMCALL_ENUM_ELEMENT(SIMCALL_HOST_GET_DATA),\
30 SIMCALL_ENUM_ELEMENT(SIMCALL_HOST_SET_DATA),\
31 SIMCALL_ENUM_ELEMENT(SIMCALL_HOST_EXECUTE),\
32 SIMCALL_ENUM_ELEMENT(SIMCALL_HOST_PARALLEL_EXECUTE),\
33 SIMCALL_ENUM_ELEMENT(SIMCALL_HOST_EXECUTION_DESTROY),\
34 SIMCALL_ENUM_ELEMENT(SIMCALL_HOST_EXECUTION_CANCEL),\
35 SIMCALL_ENUM_ELEMENT(SIMCALL_HOST_EXECUTION_GET_REMAINS),\
36 SIMCALL_ENUM_ELEMENT(SIMCALL_HOST_EXECUTION_GET_STATE),\
37 SIMCALL_ENUM_ELEMENT(SIMCALL_HOST_EXECUTION_SET_PRIORITY),\
38 SIMCALL_ENUM_ELEMENT(SIMCALL_HOST_EXECUTION_WAIT),\
39 SIMCALL_ENUM_ELEMENT(SIMCALL_PROCESS_CREATE),\
40 SIMCALL_ENUM_ELEMENT(SIMCALL_PROCESS_KILL),\
41 SIMCALL_ENUM_ELEMENT(SIMCALL_PROCESS_KILLALL),\
42 SIMCALL_ENUM_ELEMENT(SIMCALL_PROCESS_CLEANUP),\
43 SIMCALL_ENUM_ELEMENT(SIMCALL_PROCESS_CHANGE_HOST),\
44 SIMCALL_ENUM_ELEMENT(SIMCALL_PROCESS_SUSPEND),\
45 SIMCALL_ENUM_ELEMENT(SIMCALL_PROCESS_RESUME),\
46 SIMCALL_ENUM_ELEMENT(SIMCALL_PROCESS_COUNT),\
47 SIMCALL_ENUM_ELEMENT(SIMCALL_PROCESS_GET_DATA),\
48 SIMCALL_ENUM_ELEMENT(SIMCALL_PROCESS_SET_DATA),\
49 SIMCALL_ENUM_ELEMENT(SIMCALL_PROCESS_GET_HOST),\
50 SIMCALL_ENUM_ELEMENT(SIMCALL_PROCESS_GET_NAME),\
51 SIMCALL_ENUM_ELEMENT(SIMCALL_PROCESS_IS_SUSPENDED),\
52 SIMCALL_ENUM_ELEMENT(SIMCALL_PROCESS_GET_PROPERTIES),\
53 SIMCALL_ENUM_ELEMENT(SIMCALL_PROCESS_SLEEP),\
54 SIMCALL_ENUM_ELEMENT(SIMCALL_PROCESS_ON_EXIT),\
55 SIMCALL_ENUM_ELEMENT(SIMCALL_PROCESS_AUTO_RESTART_SET),\
56 SIMCALL_ENUM_ELEMENT(SIMCALL_PROCESS_RESTART),\
57 SIMCALL_ENUM_ELEMENT(SIMCALL_RDV_CREATE),\
58 SIMCALL_ENUM_ELEMENT(SIMCALL_RDV_DESTROY),\
59 SIMCALL_ENUM_ELEMENT(SIMCALL_RDV_GEY_BY_NAME),\
60 SIMCALL_ENUM_ELEMENT(SIMCALL_RDV_COMM_COUNT_BY_HOST),\
61 SIMCALL_ENUM_ELEMENT(SIMCALL_RDV_GET_HEAD),\
62 SIMCALL_ENUM_ELEMENT(SIMCALL_RDV_SET_RECV),\
63 SIMCALL_ENUM_ELEMENT(SIMCALL_RDV_GET_RECV),\
64 SIMCALL_ENUM_ELEMENT(SIMCALL_COMM_SEND),\
65 SIMCALL_ENUM_ELEMENT(SIMCALL_COMM_ISEND),\
66 SIMCALL_ENUM_ELEMENT(SIMCALL_COMM_RECV),\
67 SIMCALL_ENUM_ELEMENT(SIMCALL_COMM_IRECV),\
68 SIMCALL_ENUM_ELEMENT(SIMCALL_COMM_DESTROY),\
69 SIMCALL_ENUM_ELEMENT(SIMCALL_COMM_CANCEL),\
70 SIMCALL_ENUM_ELEMENT(SIMCALL_COMM_WAITANY),\
71 SIMCALL_ENUM_ELEMENT(SIMCALL_COMM_WAIT),\
72 SIMCALL_ENUM_ELEMENT(SIMCALL_COMM_TEST),\
73 SIMCALL_ENUM_ELEMENT(SIMCALL_COMM_TESTANY),\
74 SIMCALL_ENUM_ELEMENT(SIMCALL_COMM_IPROBE),\
75 SIMCALL_ENUM_ELEMENT(SIMCALL_COMM_GET_REMAINS),\
76 SIMCALL_ENUM_ELEMENT(SIMCALL_COMM_GET_STATE),\
77 SIMCALL_ENUM_ELEMENT(SIMCALL_COMM_GET_SRC_DATA),\
78 SIMCALL_ENUM_ELEMENT(SIMCALL_COMM_GET_DST_DATA),\
79 SIMCALL_ENUM_ELEMENT(SIMCALL_COMM_GET_SRC_PROC),\
80 SIMCALL_ENUM_ELEMENT(SIMCALL_COMM_GET_DST_PROC),\
81 SIMCALL_ENUM_ELEMENT(SIMCALL_MUTEX_INIT),\
82 SIMCALL_ENUM_ELEMENT(SIMCALL_MUTEX_DESTROY),\
83 SIMCALL_ENUM_ELEMENT(SIMCALL_MUTEX_LOCK),\
84 SIMCALL_ENUM_ELEMENT(SIMCALL_MUTEX_TRYLOCK),\
85 SIMCALL_ENUM_ELEMENT(SIMCALL_MUTEX_UNLOCK),\
86 SIMCALL_ENUM_ELEMENT(SIMCALL_COND_INIT),\
87 SIMCALL_ENUM_ELEMENT(SIMCALL_COND_DESTROY),\
88 SIMCALL_ENUM_ELEMENT(SIMCALL_COND_SIGNAL),\
89 SIMCALL_ENUM_ELEMENT(SIMCALL_COND_WAIT),\
90 SIMCALL_ENUM_ELEMENT(SIMCALL_COND_WAIT_TIMEOUT),\
91 SIMCALL_ENUM_ELEMENT(SIMCALL_COND_BROADCAST),\
92 SIMCALL_ENUM_ELEMENT(SIMCALL_SEM_INIT),\
93 SIMCALL_ENUM_ELEMENT(SIMCALL_SEM_DESTROY),\
94 SIMCALL_ENUM_ELEMENT(SIMCALL_SEM_RELEASE),\
95 SIMCALL_ENUM_ELEMENT(SIMCALL_SEM_WOULD_BLOCK),\
96 SIMCALL_ENUM_ELEMENT(SIMCALL_SEM_ACQUIRE),\
97 SIMCALL_ENUM_ELEMENT(SIMCALL_SEM_ACQUIRE_TIMEOUT),\
98 SIMCALL_ENUM_ELEMENT(SIMCALL_SEM_GET_CAPACITY),\
99 SIMCALL_ENUM_ELEMENT(SIMCALL_FILE_READ),\
100 SIMCALL_ENUM_ELEMENT(SIMCALL_FILE_WRITE),\
101 SIMCALL_ENUM_ELEMENT(SIMCALL_FILE_OPEN),\
102 SIMCALL_ENUM_ELEMENT(SIMCALL_FILE_CLOSE),\
103 SIMCALL_ENUM_ELEMENT(SIMCALL_FILE_STAT), \
104 SIMCALL_ENUM_ELEMENT(SIMCALL_FILE_UNLINK),\
105 SIMCALL_ENUM_ELEMENT(SIMCALL_FILE_LS),\
106 SIMCALL_ENUM_ELEMENT(SIMCALL_ASR_GET_PROPERTIES), \
107 /* ****************************************************************************************** */ \
108 /* TUTORIAL: New API                                                                        */ \
109 /* ****************************************************************************************** */ \
110 SIMCALL_ENUM_ELEMENT(SIMCALL_NEW_API_INIT)
111
112 /* SIMCALL_COMM_IS_LATENCY_BOUNDED and SIMCALL_SET_CATEGORY make things complicated
113  * because they are not always present */
114 #ifdef HAVE_LATENCY_BOUND_TRACKING
115 #define SIMCALL_LIST2 \
116 ,SIMCALL_ENUM_ELEMENT(SIMCALL_COMM_IS_LATENCY_BOUNDED, SIMIX_comm_is_latency_bounded)
117 #else
118 #define SIMCALL_LIST2
119 #endif
120
121 #ifdef HAVE_TRACING
122 #define SIMCALL_LIST3 \
123 ,SIMCALL_ENUM_ELEMENT(SIMCALL_SET_CATEGORY, SIMIX_set_category)
124 #else
125 #define SIMCALL_LIST3
126 #endif
127
128 #ifdef HAVE_MC
129 #define SIMCALL_LIST4                                        \
130   ,SIMCALL_ENUM_ELEMENT(SIMCALL_MC_SNAPSHOT)                 \
131   ,SIMCALL_ENUM_ELEMENT(SIMCALL_MC_COMPARE_SNAPSHOTS)
132 #else
133 #define SIMCALL_LIST4
134 #endif
135
136 /* SIMCALL_LIST is the final macro to use */
137 #define SIMCALL_LIST SIMCALL_LIST1 SIMCALL_LIST2 SIMCALL_LIST3 SIMCALL_LIST4
138
139 /* you can redefine the following macro differently to generate something else
140  * with the list of enumeration values (e.g. a table of strings or a table of function pointers) */
141 #define SIMCALL_ENUM_ELEMENT(x, y) x
142
143 /**
144  * \brief All possible simcalls.
145  */
146 typedef enum {
147 SIMCALL_LIST
148 } e_smx_simcall_t;
149
150 /**
151  * \brief Represents a simcall to the kernel.
152  */
153 typedef struct s_smx_simcall {
154   e_smx_simcall_t call;
155   smx_process_t issuer;
156   union u_smx_scalar *args;
157   //FIXME: union u_smx_scalar retval;
158
159   union {
160
161     struct {
162       const char *name;
163       smx_host_t result;
164     } host_get_by_name;
165
166     struct {
167       smx_host_t host;
168       const char* result;
169     } host_get_name;
170
171     struct {
172       smx_host_t host;
173       xbt_dict_t result;
174     } host_get_properties;
175
176     struct {
177       smx_host_t host;
178       double result;
179     } host_get_speed;
180
181     struct {
182       smx_host_t host;
183       double result;
184     } host_get_available_speed;
185
186     struct {
187       smx_host_t host;
188       int result;
189     } host_get_state;
190
191     struct {
192       smx_host_t host;
193       void* result;
194     } host_get_data;
195
196     struct {
197       smx_host_t host;
198       void* data;
199     } host_set_data;
200
201     struct {
202       const char* name;
203       smx_host_t host;
204       double computation_amount;
205       double priority;
206       smx_action_t result;
207     } host_execute;
208
209     struct {
210       const char *name;
211       int host_nb;
212       smx_host_t *host_list;
213       double *computation_amount;
214       double *communication_amount;
215       double amount;
216       double rate;
217       smx_action_t result;
218     } host_parallel_execute;
219
220     struct {
221       smx_action_t execution;
222     } host_execution_destroy;
223
224     struct {
225       smx_action_t execution;
226     } host_execution_cancel;
227
228     struct {
229       smx_action_t execution;
230       double result;
231     } host_execution_get_remains;
232
233     struct {
234       smx_action_t execution;
235       e_smx_state_t result;
236     } host_execution_get_state;
237
238     struct {
239       smx_action_t execution;
240       double priority;
241     } host_execution_set_priority;
242
243     struct {
244       smx_action_t execution;
245       struct s_smx_simcall *simcall;
246       e_smx_state_t result;
247
248     } host_execution_wait;
249
250     struct {
251       smx_process_t *process;
252       const char *name;
253       xbt_main_func_t code;
254       void *data;
255       const char *hostname;
256       double kill_time;
257       int argc;
258       char **argv;
259       xbt_dict_t properties;
260       int auto_restart;
261     } process_create;
262
263     struct {
264       smx_process_t process;
265     } process_kill;
266
267     struct {
268       smx_process_t process;
269     } process_cleanup;
270
271     struct {
272       smx_process_t process;
273       smx_host_t dest;
274     } process_change_host;
275
276     struct {
277       smx_process_t process;
278     } process_suspend;
279
280     struct {
281       smx_process_t process;
282     } process_resume;
283
284     struct {
285       int result;
286     } process_count;
287
288     struct {
289       smx_process_t process;
290       void* result;
291     } process_get_data;
292
293     struct {
294       smx_process_t process;
295       void* data;
296     } process_set_data;
297
298     struct {
299       smx_process_t process;
300       smx_host_t result;
301     } process_get_host;
302
303     struct {
304       smx_process_t process;
305       const char *result;
306     } process_get_name;
307
308     struct {
309       smx_process_t process;
310       int result;
311     } process_is_suspended;
312
313     struct {
314       smx_process_t process;
315       xbt_dict_t result;
316     } process_get_properties;
317
318     struct {
319       double duration;
320       e_smx_state_t result;
321     } process_sleep;
322
323     struct {
324       smx_process_t process;
325       int_f_pvoid_t fun;
326       void *data;
327     } process_on_exit;
328
329     struct {
330       smx_process_t process;
331       int auto_restart;
332     } process_auto_restart;
333
334     struct {
335       smx_process_t process;
336       smx_process_t result;
337     } process_restart;
338
339     struct {
340       const char *name;
341       smx_rdv_t result;
342     } rdv_create;
343
344     struct {
345       smx_rdv_t rdv;
346     } rdv_destroy;
347
348     struct {
349       const char* name;
350       smx_rdv_t result;
351     } rdv_get_by_name;
352
353     struct {
354       smx_rdv_t rdv;
355       smx_host_t host;
356       unsigned int result; 
357     } rdv_comm_count_by_host;
358
359     struct {
360       smx_rdv_t rdv;
361       smx_action_t result;
362     } rdv_get_head;
363
364     struct {
365       smx_rdv_t rdv;
366       smx_process_t receiver;
367     } rdv_set_rcv_proc;
368
369     struct {
370       smx_rdv_t rdv;
371       smx_process_t result;
372     } rdv_get_rcv_proc;
373
374     struct {
375       smx_rdv_t rdv;
376       double task_size;
377       double rate;
378       void *src_buff;
379       size_t src_buff_size;
380       int (*match_fun)(void *, void *, smx_action_t);
381       void *data;
382       double timeout;
383     } comm_send;
384
385     struct {
386       smx_rdv_t rdv;
387       double task_size;
388       double rate;
389       void *src_buff;
390       size_t src_buff_size;
391       int (*match_fun)(void *, void *, smx_action_t);
392       void (*clean_fun)(void *);
393       void *data;
394       int detached;
395       smx_action_t result;
396     } comm_isend;
397
398     struct {
399       smx_rdv_t rdv;
400       void *dst_buff;
401       size_t *dst_buff_size;
402       int (*match_fun)(void *, void *, smx_action_t);
403       void *data;
404       double timeout;
405     } comm_recv;
406
407     struct {
408       smx_rdv_t rdv;
409       void *dst_buff;
410       size_t *dst_buff_size;
411       int (*match_fun)(void *, void *, smx_action_t);
412       void *data;
413       smx_action_t result;
414     } comm_irecv;
415
416     struct {
417       smx_rdv_t rdv;
418       int src;
419       int tag;
420       int (*match_fun)(void *, void *, smx_action_t);
421       void *data;
422       smx_action_t result;
423     } comm_iprobe;
424
425     struct {
426       smx_action_t comm;
427     } comm_destroy;
428
429     struct {
430       smx_action_t comm;
431     } comm_cancel;
432
433     struct {
434       xbt_dynar_t comms;
435       unsigned int result;
436     } comm_waitany;
437
438     struct {
439       smx_action_t comm;
440       double timeout;
441     } comm_wait;
442
443     struct {
444       smx_action_t comm;
445       int result;
446     } comm_test;
447
448     struct {
449       xbt_dynar_t comms;
450       int result;
451     } comm_testany;
452
453     struct {
454       smx_action_t comm;
455       double result;
456     } comm_get_remains;
457
458     struct {
459       smx_action_t comm;
460       e_smx_state_t result;
461     } comm_get_state;
462
463     struct {
464       smx_action_t comm;
465       void *result;
466     } comm_get_src_data;
467
468     struct {
469       smx_action_t comm;
470       void *result;
471     } comm_get_dst_data;
472
473     struct {
474       smx_action_t comm;
475       smx_process_t result;
476     } comm_get_src_proc;
477
478     struct {
479       smx_action_t comm;
480       smx_process_t result;
481     } comm_get_dst_proc;
482
483 #ifdef HAVE_LATENCY_BOUND_TRACKING
484     struct {
485       smx_action_t comm;
486       int result;
487     } comm_is_latency_bounded;
488 #endif
489
490 #ifdef HAVE_TRACING
491     struct {
492       smx_action_t action;
493       const char *category;
494     } set_category;
495 #endif
496
497     struct {
498       smx_mutex_t result;
499     } mutex_init;
500
501     struct {
502       smx_mutex_t mutex;
503     } mutex_lock;
504
505     struct {
506       smx_mutex_t mutex;
507       int result;
508     } mutex_trylock;
509
510     struct {
511       smx_mutex_t mutex;
512     } mutex_unlock;
513
514     struct {
515       smx_mutex_t mutex;
516     } mutex_destroy;
517
518     struct {
519       smx_cond_t result;
520     } cond_init;
521
522     struct {
523       smx_cond_t cond;
524     } cond_destroy;
525
526     struct {
527       smx_cond_t cond;
528     } cond_signal;
529
530     struct {
531       smx_cond_t cond;
532       smx_mutex_t mutex;
533     } cond_wait;
534
535     struct {
536       smx_cond_t cond;
537       smx_mutex_t mutex;
538       double timeout;
539     } cond_wait_timeout;
540
541     struct {
542       smx_cond_t cond;
543     } cond_broadcast;
544
545     struct {
546       int capacity;
547       smx_sem_t result;
548     } sem_init;
549
550     struct {
551       smx_sem_t sem;
552     } sem_destroy;
553
554     struct {
555       smx_sem_t sem;
556     } sem_release;
557
558     struct {
559       smx_sem_t sem;
560       int result;
561     } sem_would_block;
562
563     struct {
564       smx_sem_t sem;
565     } sem_acquire;
566
567     struct {
568       smx_sem_t sem;
569       double timeout;
570     } sem_acquire_timeout;
571
572     struct {
573       smx_sem_t sem;
574       int result;
575     } sem_get_capacity;
576
577     struct {
578       void *ptr;
579       size_t size;
580       size_t nmemb;
581       smx_file_t stream;
582       double result;
583     } file_read;
584
585     struct {
586       const void *ptr;
587       size_t size;
588       size_t nmemb;
589       smx_file_t stream;
590       size_t result;
591     } file_write;
592
593     struct {
594       const char* mount;
595       const char* path;
596       const char* mode;
597       smx_file_t result;
598     } file_open;
599
600     struct {
601       smx_file_t fp;
602       int result;
603     } file_close;
604
605     struct {
606       smx_file_t fd;
607       s_file_stat_t buf;
608       int result;
609     } file_stat;
610
611     struct {
612       smx_file_t fd;
613       int result;
614     } file_unlink;
615
616     struct {
617       const char *mount;
618       const char *path;
619       xbt_dict_t result;
620     } file_ls;
621
622     struct {
623       const char* name;
624       xbt_dict_t result;
625     } asr_get_properties;
626
627     struct{
628       void *s;
629     } mc_snapshot;
630
631     struct{
632       void *snapshot1;
633       void *snapshot2;
634       int result;
635     } mc_compare_snapshots;
636
637     /* ****************************************************************************************** */
638     /* TUTORIAL: New API                                                                        */
639     /* ****************************************************************************************** */
640     struct {
641       const char* param1;
642       double param2;
643       int result;
644     } new_api;
645
646   };
647 } s_smx_simcall_t, *smx_simcall_t;
648
649 /******************************** General *************************************/
650
651 void SIMIX_simcall_push(smx_process_t self);
652 void SIMIX_simcall_answer(smx_simcall_t);
653 void SIMIX_simcall_pre(smx_simcall_t, int);
654 void SIMIX_simcall_post(smx_action_t);
655 smx_simcall_t SIMIX_simcall_mine(void);
656 const char *SIMIX_simcall_name(e_smx_simcall_t kind);
657
658 /*************************** New simcall interface ****************************/
659
660 /* Pack all possible scalar types in an union */
661 union u_smx_scalar {
662   char            c;
663   const char*     cc;
664   short           s;
665   int             i;
666   long            l;
667   unsigned char   uc;
668   unsigned short  us;
669   unsigned int    ui;
670   unsigned long   ul;
671   float           f;
672   double          d;
673   void*           p;
674 };
675
676 #define SIMIX_pack_args(...) (u_smx_scalar_t[]){MAP(INIT_FIELD, __VA_ARGS__)}
677
678
679 /*
680  * Define scalar type wrappers to ease the use of simcalls.
681  * These are used to wrap the arguments in SIMIX_simcall macro.
682  */
683 #define CHAR(x) (c,x)
684 #define STRING(x) (cc,x)
685 #define SHORT(x) (s,x)
686 #define INT(x) (i,x)
687 #define LONG(x) (l,x)
688 #define UCHAR(x) (uc,x)
689 #define USHORT(x) (us,x)
690 #define UINT(x) (ui,x)
691 #define ULONG(x) (ul,x)
692 #define FLOAT(x) (f,x)
693 #define DOUBLE(x) (d,x)
694 #define PTR(x)  (p,x)
695
696 /*
697  * Some macro machinery to get a MAP over the arguments of a variadic macro.
698  * It uses a FOLD to apply a macro to every argument, and because there is
699  * no recursion in the C preprocessor we must create a new macro for every
700  * depth of FOLD's recursion.
701  */
702
703 /* FOLD macro */
704 #define FE_1(WHAT, X) WHAT(X)
705 #define FE_2(WHAT, X, ...) WHAT(X), FE_1(WHAT, __VA_ARGS__)
706 #define FE_3(WHAT, X, ...) WHAT(X), FE_2(WHAT, __VA_ARGS__)
707 #define FE_4(WHAT, X, ...) WHAT(X), FE_3(WHAT, __VA_ARGS__)
708 #define FE_5(WHAT, X, ...) WHAT(X), FE_4(WHAT, __VA_ARGS__)
709 /* NOTE: add as many FE_n as needed (maximum number of simcall arguments )*/
710
711 /* Make a MAP macro usgin FOLD (will apply 'action' to the arguments.
712  * GET_MACRO is a smart hack that counts the number of arguments passed to
713  * the variadic macro, and it is used to invoke the right FOLD depth.
714  */
715 #define GET_MACRO(_1,_2,_3,_4,_5,NAME,...) NAME
716 #define MAP(action,...) \
717   GET_MACRO(__VA_ARGS__,FE_5,FE_4,FE_3,FE_2,FE_1) (action, __VA_ARGS__)
718
719
720 /* Generate code to initialize the field 'x' with value 'y' of an structure or union */
721 #define INIT_FIELD_(x,y) {.x = y}
722 #define INIT_FIELD(t) INIT_FIELD_ t
723
724 /* Project the second element of a tuple */
725 #define SECOND_(x, y) y
726 #define SECOND(t) SECOND_ t
727
728 /*
729  * \brief Simcall invocation macro
730  * It calls a dummy function that uses the format attribute to ensure typesafety (see
731  * gcc format attribute), then it invokes the real simcall function packing the
732  * user provided arguments in an array.
733  * \param id a simcall id (from the simcall enumeration ids)
734  *
735  */
736 #define SIMIX_simcall(id, ...) \
737   SIMIX_simcall_typecheck(simcall_types[id], MAP(SECOND, __VA_ARGS__)); \
738   __SIMIX_simcall(id, (u_smx_scalar_t[]){MAP(INIT_FIELD, __VA_ARGS__)})
739
740 void __SIMIX_simcall(e_smx_simcall_t simcall_id, u_smx_scalar_t *args);
741
742 /*
743  * \biref Dummy variadic function used to typecheck the arguments of a simcall
744  * \param fmt A format string following printf style
745  */
746 void SIMIX_simcall_typecheck(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
747
748 typedef smx_action_t (*simcall_handler_t)(u_smx_scalar_t *);
749
750 extern const char *simcall_types[];
751 extern simcall_handler_t simcall_table[];
752
753 #endif
754