Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
WIP on simcalls: fd8c267 Stop making direct calls to SIMIX for host handling, use...
[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       e_smx_state_t result;
246     } host_execution_wait;
247
248     struct {
249       smx_process_t *process;
250       const char *name;
251       xbt_main_func_t code;
252       void *data;
253       const char *hostname;
254       double kill_time;
255       int argc;
256       char **argv;
257       xbt_dict_t properties;
258       int auto_restart;
259     } process_create;
260
261     struct {
262       smx_process_t process;
263     } process_kill;
264
265     struct {
266       smx_process_t process;
267     } process_cleanup;
268
269     struct {
270       smx_process_t process;
271       smx_host_t dest;
272     } process_change_host;
273
274     struct {
275       smx_process_t process;
276     } process_suspend;
277
278     struct {
279       smx_process_t process;
280     } process_resume;
281
282     struct {
283       int result;
284     } process_count;
285
286     struct {
287       smx_process_t process;
288       void* result;
289     } process_get_data;
290
291     struct {
292       smx_process_t process;
293       void* data;
294     } process_set_data;
295
296     struct {
297       smx_process_t process;
298       smx_host_t result;
299     } process_get_host;
300
301     struct {
302       smx_process_t process;
303       const char *result;
304     } process_get_name;
305
306     struct {
307       smx_process_t process;
308       int result;
309     } process_is_suspended;
310
311     struct {
312       smx_process_t process;
313       xbt_dict_t result;
314     } process_get_properties;
315
316     struct {
317       double duration;
318       e_smx_state_t result;
319     } process_sleep;
320
321     struct {
322       smx_process_t process;
323       int_f_pvoid_t fun;
324       void *data;
325     } process_on_exit;
326
327     struct {
328       smx_process_t process;
329       int auto_restart;
330     } process_auto_restart;
331
332     struct {
333       smx_process_t process;
334       smx_process_t result;
335     } process_restart;
336
337     struct {
338       const char *name;
339       smx_rdv_t result;
340     } rdv_create;
341
342     struct {
343       smx_rdv_t rdv;
344     } rdv_destroy;
345
346     struct {
347       const char* name;
348       smx_rdv_t result;
349     } rdv_get_by_name;
350
351     struct {
352       smx_rdv_t rdv;
353       smx_host_t host;
354       unsigned int result; 
355     } rdv_comm_count_by_host;
356
357     struct {
358       smx_rdv_t rdv;
359       smx_action_t result;
360     } rdv_get_head;
361
362     struct {
363       smx_rdv_t rdv;
364       smx_process_t receiver;
365     } rdv_set_rcv_proc;
366
367     struct {
368       smx_rdv_t rdv;
369       smx_process_t result;
370     } rdv_get_rcv_proc;
371
372     struct {
373       smx_rdv_t rdv;
374       double task_size;
375       double rate;
376       void *src_buff;
377       size_t src_buff_size;
378       int (*match_fun)(void *, void *, smx_action_t);
379       void *data;
380       double timeout;
381     } comm_send;
382
383     struct {
384       smx_rdv_t rdv;
385       double task_size;
386       double rate;
387       void *src_buff;
388       size_t src_buff_size;
389       int (*match_fun)(void *, void *, smx_action_t);
390       void (*clean_fun)(void *);
391       void *data;
392       int detached;
393       smx_action_t result;
394     } comm_isend;
395
396     struct {
397       smx_rdv_t rdv;
398       void *dst_buff;
399       size_t *dst_buff_size;
400       int (*match_fun)(void *, void *, smx_action_t);
401       void *data;
402       double timeout;
403     } comm_recv;
404
405     struct {
406       smx_rdv_t rdv;
407       void *dst_buff;
408       size_t *dst_buff_size;
409       int (*match_fun)(void *, void *, smx_action_t);
410       void *data;
411       smx_action_t result;
412     } comm_irecv;
413
414     struct {
415       smx_rdv_t rdv;
416       int src;
417       int tag;
418       int (*match_fun)(void *, void *, smx_action_t);
419       void *data;
420       smx_action_t result;
421     } comm_iprobe;
422
423     struct {
424       smx_action_t comm;
425     } comm_destroy;
426
427     struct {
428       smx_action_t comm;
429     } comm_cancel;
430
431     struct {
432       xbt_dynar_t comms;
433       unsigned int result;
434     } comm_waitany;
435
436     struct {
437       smx_action_t comm;
438       double timeout;
439     } comm_wait;
440
441     struct {
442       smx_action_t comm;
443       int result;
444     } comm_test;
445
446     struct {
447       xbt_dynar_t comms;
448       int result;
449     } comm_testany;
450
451     struct {
452       smx_action_t comm;
453       double result;
454     } comm_get_remains;
455
456     struct {
457       smx_action_t comm;
458       e_smx_state_t result;
459     } comm_get_state;
460
461     struct {
462       smx_action_t comm;
463       void *result;
464     } comm_get_src_data;
465
466     struct {
467       smx_action_t comm;
468       void *result;
469     } comm_get_dst_data;
470
471     struct {
472       smx_action_t comm;
473       smx_process_t result;
474     } comm_get_src_proc;
475
476     struct {
477       smx_action_t comm;
478       smx_process_t result;
479     } comm_get_dst_proc;
480
481 #ifdef HAVE_LATENCY_BOUND_TRACKING
482     struct {
483       smx_action_t comm;
484       int result;
485     } comm_is_latency_bounded;
486 #endif
487
488 #ifdef HAVE_TRACING
489     struct {
490       smx_action_t action;
491       const char *category;
492     } set_category;
493 #endif
494
495     struct {
496       smx_mutex_t result;
497     } mutex_init;
498
499     struct {
500       smx_mutex_t mutex;
501     } mutex_lock;
502
503     struct {
504       smx_mutex_t mutex;
505       int result;
506     } mutex_trylock;
507
508     struct {
509       smx_mutex_t mutex;
510     } mutex_unlock;
511
512     struct {
513       smx_mutex_t mutex;
514     } mutex_destroy;
515
516     struct {
517       smx_cond_t result;
518     } cond_init;
519
520     struct {
521       smx_cond_t cond;
522     } cond_destroy;
523
524     struct {
525       smx_cond_t cond;
526     } cond_signal;
527
528     struct {
529       smx_cond_t cond;
530       smx_mutex_t mutex;
531     } cond_wait;
532
533     struct {
534       smx_cond_t cond;
535       smx_mutex_t mutex;
536       double timeout;
537     } cond_wait_timeout;
538
539     struct {
540       smx_cond_t cond;
541     } cond_broadcast;
542
543     struct {
544       int capacity;
545       smx_sem_t result;
546     } sem_init;
547
548     struct {
549       smx_sem_t sem;
550     } sem_destroy;
551
552     struct {
553       smx_sem_t sem;
554     } sem_release;
555
556     struct {
557       smx_sem_t sem;
558       int result;
559     } sem_would_block;
560
561     struct {
562       smx_sem_t sem;
563     } sem_acquire;
564
565     struct {
566       smx_sem_t sem;
567       double timeout;
568     } sem_acquire_timeout;
569
570     struct {
571       smx_sem_t sem;
572       int result;
573     } sem_get_capacity;
574
575     struct {
576       void *ptr;
577       size_t size;
578       size_t nmemb;
579       smx_file_t stream;
580       double result;
581     } file_read;
582
583     struct {
584       const void *ptr;
585       size_t size;
586       size_t nmemb;
587       smx_file_t stream;
588       size_t result;
589     } file_write;
590
591     struct {
592       const char* mount;
593       const char* path;
594       const char* mode;
595       smx_file_t result;
596     } file_open;
597
598     struct {
599       smx_file_t fp;
600       int result;
601     } file_close;
602
603     struct {
604       smx_file_t fd;
605       s_file_stat_t buf;
606       int result;
607     } file_stat;
608
609     struct {
610       smx_file_t fd;
611       int result;
612     } file_unlink;
613
614     struct {
615       const char *mount;
616       const char *path;
617       xbt_dict_t result;
618     } file_ls;
619
620     struct {
621       const char* name;
622       xbt_dict_t result;
623     } asr_get_properties;
624
625     struct{
626       void *s;
627     } mc_snapshot;
628
629     struct{
630       void *snapshot1;
631       void *snapshot2;
632       int result;
633     } mc_compare_snapshots;
634
635     /* ****************************************************************************************** */
636     /* TUTORIAL: New API                                                                        */
637     /* ****************************************************************************************** */
638     struct {
639       const char* param1;
640       double param2;
641       int result;
642     } new_api;
643
644   };
645 } s_smx_simcall_t, *smx_simcall_t;
646
647 /******************************** General *************************************/
648
649 void SIMIX_simcall_push(smx_process_t self);
650 void SIMIX_simcall_answer(smx_simcall_t);
651 void SIMIX_simcall_pre(smx_simcall_t, int);
652 void SIMIX_simcall_post(smx_action_t);
653 smx_simcall_t SIMIX_simcall_mine(void);
654 const char *SIMIX_simcall_name(e_smx_simcall_t kind);
655
656 /*************************** New simcall interface ****************************/
657
658 /* Pack all possible scalar types in an union */
659 union u_smx_scalar {
660   char            c;
661   const char*     cc;
662   short           s;
663   int             i;
664   long            l;
665   unsigned char   uc;
666   unsigned short  us;
667   unsigned int    ui;
668   unsigned long   ul;
669   float           f;
670   double          d;
671   void*           p;
672 };
673
674 #define SIMIX_pack_args(...) (u_smx_scalar_t[]){MAP(INIT_FIELD, __VA_ARGS__)}
675
676
677 /*
678  * Define scalar type wrappers to ease the use of simcalls.
679  * These are used to wrap the arguments in SIMIX_simcall macro.
680  */
681 #define CHAR(x) (c,x)
682 #define STRING(x) (cc,x)
683 #define SHORT(x) (s,x)
684 #define INT(x) (i,x)
685 #define LONG(x) (l,x)
686 #define UCHAR(x) (uc,x)
687 #define USHORT(x) (us,x)
688 #define UINT(x) (ui,x)
689 #define ULONG(x) (ul,x)
690 #define FLOAT(x) (f,x)
691 #define DOUBLE(x) (d,x)
692 #define PTR(x)  (p,x)
693
694 /*
695  * Some macro machinery to get a MAP over the arguments of a variadic macro.
696  * It uses a FOLD to apply a macro to every argument, and because there is
697  * no recursion in the C preprocessor we must create a new macro for every
698  * depth of FOLD's recursion.
699  */
700
701 /* FOLD macro */
702 #define FE_1(WHAT, X) WHAT(X)
703 #define FE_2(WHAT, X, ...) WHAT(X), FE_1(WHAT, __VA_ARGS__)
704 #define FE_3(WHAT, X, ...) WHAT(X), FE_2(WHAT, __VA_ARGS__)
705 #define FE_4(WHAT, X, ...) WHAT(X), FE_3(WHAT, __VA_ARGS__)
706 #define FE_5(WHAT, X, ...) WHAT(X), FE_4(WHAT, __VA_ARGS__)
707 /* NOTE: add as many FE_n as needed (maximum number of simcall arguments )*/
708
709 /* Make a MAP macro usgin FOLD (will apply 'action' to the arguments.
710  * GET_MACRO is a smart hack that counts the number of arguments passed to
711  * the variadic macro, and it is used to invoke the right FOLD depth.
712  */
713 #define GET_MACRO(_1,_2,_3,_4,_5,NAME,...) NAME
714 #define MAP(action,...) \
715   GET_MACRO(__VA_ARGS__,FE_5,FE_4,FE_3,FE_2,FE_1) (action, __VA_ARGS__)
716
717
718 /* Generate code to initialize the field 'x' with value 'y' of an structure or union */
719 #define INIT_FIELD_(x,y) {.x = y}
720 #define INIT_FIELD(t) INIT_FIELD_ t
721
722 /* Project the second element of a tuple */
723 #define SECOND_(x, y) y
724 #define SECOND(t) SECOND_ t
725
726 /*
727  * \brief Simcall invocation macro
728  * It calls a dummy function that uses the format attribute to ensure typesafety (see
729  * gcc format attribute), then it invokes the real simcall function packing the
730  * user provided arguments in an array.
731  * \param id a simcall id (from the simcall enumeration ids)
732  *
733  */
734 #define SIMIX_simcall(id, ...) \
735   SIMIX_simcall_typecheck(simcall_types[id], MAP(SECOND, __VA_ARGS__)); \
736   __SIMIX_simcall(id, (u_smx_scalar_t[]){MAP(INIT_FIELD, __VA_ARGS__)})
737
738 void __SIMIX_simcall(e_smx_simcall_t simcall_id, u_smx_scalar_t *args);
739
740 /*
741  * \biref Dummy variadic function used to typecheck the arguments of a simcall
742  * \param fmt A format string following printf style
743  */
744 void SIMIX_simcall_typecheck(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
745
746 typedef smx_action_t (*simcall_handler_t)(u_smx_scalar_t *);
747
748 extern const char *simcall_types[];
749 extern simcall_handler_t simcall_table[];
750
751 #endif
752