Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Change simcall functions
[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 /****************************
22  * SIMCALL GENERATING MACRO *
23  ****************************
24  *
25  * action(ENUM_NAME, func_name, result_type, params…) 
26  *
27  **/
28
29 /*
30  * Some macro machinery to get a MAP over the arguments of a variadic macro.
31  * It uses a FOLD to apply a macro to every argument, and because there is
32  * no recursion in the C preprocessor we must create a new macro for every
33  * depth of FOLD's recursion.
34  */
35
36 /* FOLD macro */
37 #define FE_0(WHAT, X, ...)
38 #define FE_1(I, WHAT, X) WHAT(I, X)
39 #define FE_2(I, WHAT, X, ...) WHAT(I, X), FE_1(I+1, WHAT, __VA_ARGS__)
40 #define FE_3(I, WHAT, X, ...) WHAT(I, X), FE_2(I+1, WHAT, __VA_ARGS__)
41 #define FE_4(I, WHAT, X, ...) WHAT(I, X), FE_3(I+1, WHAT, __VA_ARGS__)
42 #define FE_5(I, WHAT, X, ...) WHAT(I, X), FE_4(I+1, WHAT, __VA_ARGS__)
43 #define FE_6(I, WHAT, X, ...) WHAT(I, X), FE_5(I+1, WHAT, __VA_ARGS__)
44 #define FE_7(I, WHAT, X, ...) WHAT(I, X), FE_6(I+1, WHAT, __VA_ARGS__)
45 #define FE_8(I, WHAT, X, ...) WHAT(I, X), FE_7(I+1, WHAT, __VA_ARGS__)
46 #define FE_9(I, WHAT, X, ...) WHAT(I, X), FE_8(I+1, WHAT, __VA_ARGS__)
47 #define FE_10(I, WHAT, X, ...) WHAT(I, X), FE_9(I+1, WHAT, __VA_ARGS__)
48
49
50 /* NOTE: add as many FE_n as needed (maximum number of simcall arguments )*/
51
52 /* Make a MAP macro usgin FOLD (will apply 'action' to the arguments.
53  * GET_MACRO is a smart hack that counts the number of arguments passed to
54  * the variadic macro, and it is used to invoke the right FOLD depth.
55  */
56 #define GET_MACRO(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,NAME,...) NAME
57 #define MAP(action, ...) \
58   GET_MACRO(, ##__VA_ARGS__, FE_10,FE_9,FE_8,FE_7,FE_6,FE_5,FE_4,FE_3,FE_2,FE_1, FE_0) (0, action, __VA_ARGS__)
59
60 /*
61  * Define scalar type wrappers to ease the use of simcalls.
62  * These are used to wrap the arguments in SIMIX_simcall macro.
63  */
64 #define TCHAR(n) (n, char, c)
65 #define TSTRING(n) (n, const char*, cc)
66 #define TSHORT(n) (n, short, s)
67 #define TINT(n) (n, int, i)
68 #define TLONG(n) (n, long, l)
69 #define TUCHAR(n) (n, unsigned char, uc)
70 #define TUSHORT(n) (n, unsigned short, us)
71 #define TUINT(n) (n, unsigned int, ui)
72 #define TULONG(n) (n, unsigned long, ul)
73 #define TFLOAT(n) (n, float, f)
74 #define TDOUBLE(n) (n, double, d)
75 #define TPTR(n) (n, void*, p)
76 #define TCPTR(n) (n, const void*, cp)
77 #define TSIZE(n) (n, size_t, si)
78 #define TSTAT(n) (n, s_file_stat_t, fs)
79 #define TVOID(n) (n, void)
80 #define TSPEC(n,t) (n, t, p)
81
82 /* use comma or nothing to separate elements*/
83 #define SIMCALL_SEP_COMMA ,
84 #define SIMCALL_SEP_NOTHING
85
86 /* get the name of the parameter */
87 #define SIMCALL_NAME_(name, type, field) name
88 #define SIMCALL_NAME(i, v) SIMCALL_NAME_ v
89
90 /* get the %s format code of the parameter */
91 #define SIMCALL_FORMAT_(name, type, field) %field
92 #define SIMCALL_FORMAT(i, v) SIMCALL_FORMAT_ v
93
94 /* get the parameter declaration */
95 #define SIMCALL_ARG_(name, type, field) type name
96 #define SIMCALL_ARG(i, v) SIMCALL_ARG_ v
97
98 /* get the parameter initialisation field */
99 #define SIMCALL_INIT_FIELD_(name, type, field) {.field = name}
100 #define SIMCALL_INIT_FIELD(i, v) SIMCALL_INIT_FIELD_ v
101
102 /* get the case of the parameter */
103 #define SIMCALL_CASE_PARAM_(name, type, field) field
104 #define SIMCALL_CASE_PARAM(i, v) simcall->args[i].SIMCALL_CASE_PARAM_ v
105
106 /* generate some code for SIMCALL_CASE if the simcall has an answer */
107 #define MAYBE2(_0, _1, func, ...) func
108
109 #define SIMCALL_WITH_RESULT_BEGIN(name, type, field) simcall->result.field =
110 #define SIMCALL_WITHOUT_RESULT_BEGIN(name, type, field)
111 #define SIMCALL_RESULT_BEGIN_(name, type, ...)\
112         MAYBE2(,##__VA_ARGS__, SIMCALL_WITH_RESULT_BEGIN, SIMCALL_WITHOUT_RESULT_BEGIN)\
113         (name, type, __VA_ARGS__)
114 #define SIMCALL_RESULT_BEGIN(answer, res) answer(SIMCALL_RESULT_BEGIN_ res)
115
116 #define SIMCALL_RESULT_END_(name, type, ...)\
117         SIMIX_simcall_answer(simcall);
118 #define SIMCALL_RESULT_END(answer, res) answer(SIMCALL_RESULT_END_ res)
119
120 /* generate some code for BODY function */
121 #define SIMCALL_FUNC_RETURN_TYPE_(name, type, ...) type
122 #define SIMCALL_FUNC_RETURN_TYPE(res) SIMCALL_FUNC_RETURN_TYPE_ res
123
124 #define SIMCALL_WITH_FUNC_SIMCALL(name, type, field) smx_simcall_t simcall = 
125 #define SIMCALL_WITHOUT_FUNC_SIMCALL(name, type, field)
126 #define SIMCALL_FUNC_SIMCALL_(name, type, ...)\
127         MAYBE2(,##__VA_ARGS__, SIMCALL_WITH_FUNC_SIMCALL, SIMCALL_WITHOUT_FUNC_SIMCALL)\
128         (name, type, __VA_ARGS__)
129 #define SIMCALL_FUNC_SIMCALL(res) SIMCALL_FUNC_SIMCALL_ res
130
131 #define SIMCALL_WITH_FUNC_RETURN(name, type, field) return simcall->result.field;
132 #define SIMCALL_WITHOUT_FUNC_RETURN(name, type, field)
133 #define SIMCALL_FUNC_RETURN_(name, type, ...)\
134         MAYBE2(,##__VA_ARGS__, SIMCALL_WITH_FUNC_RETURN, SIMCALL_WITHOUT_FUNC_RETURN)\
135         (name, type, __VA_ARGS__)
136 #define SIMCALL_FUNC_RETURN(res) SIMCALL_FUNC_RETURN_ res
137
138
139 /* generate the simcall enumeration */
140 #define SIMCALL_ENUM(type, ...)\
141         type
142
143 /* generate strings from the enumeration values */
144 #define SIMCALL_TYPE(type, name, answer, res, ...)\
145         [type] = STRINGIFY(MAP(SIMCALL_FORMAT, __VA_ARGS__))
146
147 /* generate the simcalls functions */
148 #define SIMCALL_FUNC(type, name, answer, res, ...)\
149         SIMCALL_FUNC_RETURN_TYPE(res) simcall_BODY_##name(MAP(SIMCALL_ARG, ##__VA_ARGS__)) { \
150       SIMCALL_FUNC_SIMCALL(res) __SIMIX_simcall(type, (u_smx_scalar_t[]){MAP(SIMCALL_INIT_FIELD, ##__VA_ARGS__)}); \
151       SIMCALL_FUNC_RETURN(res)\
152     }
153
154 /* generate the simcalls prototypes functions */
155 #define VOID_IF_EMPTY(...) GET_CLEAN(,##__VA_ARGS__,,,,,,,,,,,void)
156 #define SIMCALL_FUNC_PROTO(type, name, answer, res, ...)\
157         SIMCALL_FUNC_RETURN_TYPE(res) simcall_BODY_##name(VOID_IF_EMPTY(__VA_ARGS__) MAP(SIMCALL_ARG, ##__VA_ARGS__));
158
159
160 /* generate a comma if there is an argument*/
161 #define WITHOUT_COMMA 
162 #define WITH_COMMA ,
163 #define GET_CLEAN(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10, NAME,...) NAME
164 #define MAYBE_COMMA(...) GET_CLEAN(,##__VA_ARGS__,WITH_COMMA,WITH_COMMA,WITH_COMMA,WITH_COMMA,WITH_COMMA,WITH_COMMA,WITH_COMMA,WITH_COMMA,WITH_COMMA,WITH_COMMA,WITHOUT_COMMA)
165
166 /* generate the simcalls cases for the SIMIX_simcall_pre function */
167 #define WITH_ANSWER(...) __VA_ARGS__
168 #define WITHOUT_ANSWER(...) 
169 #define SIMCALL_CASE(type, name, answer, res, ...)\
170     case type:;\
171       SIMCALL_RESULT_BEGIN(answer, res) SIMIX_pre_ ## name(simcall MAYBE_COMMA(__VA_ARGS__) MAP(SIMCALL_CASE_PARAM, ##__VA_ARGS__));\
172       SIMCALL_RESULT_END(answer, res)\
173       break;
174
175 /* stringify arguments */
176 #define STRINGIFY_(...) #__VA_ARGS__
177 #define STRINGIFY(...) STRINGIFY_(__VA_ARGS__)
178
179 /* the list of simcalls definitions */
180 #define SIMCALL_LIST1(action, sep) \
181 action(SIMCALL_HOST_GET_BY_NAME, host_get_by_name, WITH_ANSWER, TSPEC(result, smx_host_t), TSTRING(NAME)) sep \
182 action(SIMCALL_HOST_GET_NAME, host_get_name, WITH_ANSWER, TSTRING(result), TSPEC(host, smx_host_t)) sep \
183 action(SIMCALL_HOST_GET_PROPERTIES, host_get_properties, WITH_ANSWER, TSPEC(result, xbt_dict_t), TSPEC(host, smx_host_t)) sep \
184 action(SIMCALL_HOST_GET_SPEED, host_get_speed, WITH_ANSWER, TDOUBLE(result), TSPEC(host, smx_host_t)) sep \
185 action(SIMCALL_HOST_GET_AVAILABLE_SPEED, host_get_available_speed, WITH_ANSWER, TDOUBLE(result), TSPEC(result, smx_host_t)) sep \
186 action(SIMCALL_HOST_GET_STATE, host_get_state, WITH_ANSWER, TINT(result), TSPEC(host, smx_host_t)) sep \
187 action(SIMCALL_HOST_GET_DATA, host_get_data, WITH_ANSWER, TPTR(result), TSPEC(host, smx_host_t)) sep \
188 action(SIMCALL_HOST_SET_DATA, host_set_data, WITH_ANSWER, TVOID(result), TSPEC(host, smx_host_t), TPTR(data)) sep \
189 action(SIMCALL_HOST_EXECUTE, host_execute, WITH_ANSWER, TSPEC(result, smx_action_t), TSTRING(name), TSPEC(host, smx_host_t), TDOUBLE(computation_amount), TDOUBLE(priority)) sep \
190 action(SIMCALL_HOST_PARALLEL_EXECUTE, host_parallel_execute, WITH_ANSWER, TSPEC(result, smx_action_t), TSTRING(name), TINT(host_nb), TSPEC(host_list, smx_host_t*), TSPEC(computation_amount, double*), TSPEC(communication_amount, double*), TDOUBLE(amount), TDOUBLE(rate)) sep \
191 action(SIMCALL_HOST_EXECUTION_DESTROY, host_execution_destroy, WITH_ANSWER, TVOID(result), TSPEC(execution, smx_action_t)) sep \
192 action(SIMCALL_HOST_EXECUTION_CANCEL, host_execution_cancel, WITH_ANSWER, TVOID(result), TSPEC(execution, smx_action_t)) sep \
193 action(SIMCALL_HOST_EXECUTION_GET_REMAINS, host_execution_get_remains, WITH_ANSWER, TDOUBLE(result), TSPEC(execution, smx_action_t)) sep \
194 action(SIMCALL_HOST_EXECUTION_GET_STATE, host_execution_get_state, WITH_ANSWER, TINT(result), TSPEC(execution, smx_action_t)) sep \
195 action(SIMCALL_HOST_EXECUTION_SET_PRIORITY, host_execution_set_priority, WITH_ANSWER, TVOID(result), TSPEC(execution, smx_action_t), TDOUBLE(priority)) sep \
196 action(SIMCALL_HOST_EXECUTION_WAIT, host_execution_wait, WITHOUT_ANSWER, TINT(result), TSPEC(execution, smx_action_t)) sep \
197 action(SIMCALL_PROCESS_CREATE, process_create, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t*), TSTRING(name), TSPEC(code, xbt_main_func_t), TPTR(data), TSTRING(hostname), TDOUBLE(kill_time), TINT(argc), TSPEC(argv, char**), TSPEC(properties, xbt_dict_t), TINT(auto_restart)) sep \
198 action(SIMCALL_PROCESS_KILL, process_kill, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t)) sep \
199 action(SIMCALL_PROCESS_KILLALL, process_killall, WITH_ANSWER, TVOID(result)) sep \
200 action(SIMCALL_PROCESS_CLEANUP, process_cleanup, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t)) sep \
201 action(SIMCALL_PROCESS_CHANGE_HOST, process_change_host, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t), TSPEC(dest, smx_host_t)) sep \
202 action(SIMCALL_PROCESS_SUSPEND, process_suspend, WITHOUT_ANSWER, TVOID(result), TSPEC(process, smx_process_t)) sep \
203 action(SIMCALL_PROCESS_RESUME, process_resume, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t)) sep \
204 action(SIMCALL_PROCESS_COUNT, process_count, WITH_ANSWER, TINT(result)) sep \
205 action(SIMCALL_PROCESS_GET_DATA, process_get_data, WITH_ANSWER, TPTR(result), TSPEC(process, smx_process_t)) sep \
206 action(SIMCALL_PROCESS_SET_DATA, process_set_data, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t), TPTR(data)) sep \
207 action(SIMCALL_PROCESS_GET_HOST, process_get_host, WITH_ANSWER, TSPEC(result, smx_host_t), TSPEC(process, smx_process_t)) sep \
208 action(SIMCALL_PROCESS_GET_NAME, process_get_name, WITH_ANSWER, TSTRING(result), TSPEC(process, smx_process_t)) sep \
209 action(SIMCALL_PROCESS_IS_SUSPENDED, process_is_suspended, WITH_ANSWER, TINT(result), TSPEC(process, smx_process_t)) sep \
210 action(SIMCALL_PROCESS_GET_PROPERTIES, process_get_properties, WITH_ANSWER, TSPEC(result, xbt_dict_t), TSPEC(process, smx_process_t)) sep \
211 action(SIMCALL_PROCESS_SLEEP, process_sleep, WITHOUT_ANSWER, TINT(result), TDOUBLE(duration)) sep \
212 action(SIMCALL_PROCESS_ON_EXIT, process_on_exit, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t), TSPEC(fun, int_f_pvoid_t), TPTR(data)) sep \
213 action(SIMCALL_PROCESS_AUTO_RESTART_SET, process_auto_restart_set, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t), TINT(auto_restart)) sep \
214 action(SIMCALL_PROCESS_RESTART, process_restart, WITH_ANSWER, TSPEC(result, smx_process_t), TSPEC(process, smx_process_t)) sep \
215 action(SIMCALL_RDV_CREATE, rdv_create, WITH_ANSWER, TSPEC(result, smx_rdv_t), TSTRING(name)) sep \
216 action(SIMCALL_RDV_DESTROY, rdv_destroy, WITH_ANSWER, TVOID(result), TSPEC(rdv, smx_rdv_t)) sep \
217 action(SIMCALL_RDV_GET_BY_NAME, rdv_get_by_name, WITH_ANSWER, TSPEC(result, smx_host_t), TSTRING(name)) sep \
218 action(SIMCALL_RDV_COMM_COUNT_BY_HOST, rdv_comm_count_by_host, WITH_ANSWER, TUINT(result), TSPEC(rdv, smx_rdv_t), TSPEC(host, smx_host_t)) sep \
219 action(SIMCALL_RDV_GET_HEAD, rdv_get_head, WITH_ANSWER, TSPEC(result, smx_action_t), TSPEC(rdv, smx_rdv_t)) sep \
220 action(SIMCALL_RDV_SET_RECV, rdv_set_receiver, WITH_ANSWER, TVOID(result), TSPEC(rdv, smx_rdv_t), TSPEC(receiver, smx_process_t)) sep \
221 action(SIMCALL_RDV_GET_RECV, rdv_get_receiver, WITH_ANSWER, TSPEC(result, smx_process_t), TSPEC(rdv, smx_rdv_t)) sep \
222 action(SIMCALL_COMM_IPROBE, comm_iprobe, WITH_ANSWER, TSPEC(result, smx_action_t), TSPEC(rdv, smx_rdv_t), TINT(src), TINT(tag), TSPEC(match_fun, simix_match_func_t), TPTR(data)) sep \
223 action(SIMCALL_COMM_SEND, comm_send, WITHOUT_ANSWER, TVOID(result), TSPEC(rdv, smx_rdv_t), TDOUBLE(task_size), TDOUBLE(rate), TPTR(src_buff), TSIZE(src_buff_size), TSPEC(match_fun, simix_match_func_t), TPTR(data), TDOUBLE(timeout)) sep \
224 action(SIMCALL_COMM_ISEND, comm_isend, WITH_ANSWER, TSPEC(result, smx_action_t), TSPEC(rdv, smx_rdv_t), TDOUBLE(task_size), TDOUBLE(rate), TPTR(src_buff), TSIZE(src_buff_size), TSPEC(match_fun, simix_match_func_t), TSPEC(clean_fun, simix_clean_func_t), TPTR(data), TINT(detached)) sep \
225 action(SIMCALL_COMM_RECV, comm_recv, WITHOUT_ANSWER, TVOID(result), TSPEC(rdv, smx_rdv_t), TPTR(dst_buff), TSPEC(dst_buff_size, size_t*), TSPEC(match_fun, simix_match_func_t), TPTR(data), TDOUBLE(timeout)) sep \
226 action(SIMCALL_COMM_IRECV, comm_irecv, WITH_ANSWER, TSPEC(result, smx_action_t), TSPEC(rdv, smx_rdv_t), TPTR(dst_buff), TSPEC(dst_buff_size, size_t*), TSPEC(match_fun, simix_match_func_t), TPTR(data)) sep \
227 action(SIMCALL_COMM_DESTROY, comm_destroy, WITH_ANSWER, TVOID(result), TSPEC(comm, smx_action_t)) sep \
228 action(SIMCALL_COMM_CANCEL, comm_cancel, WITH_ANSWER, TVOID(result), TSPEC(comm, smx_action_t)) sep \
229 action(SIMCALL_COMM_WAITANY, comm_waitany, WITHOUT_ANSWER, TINT(result), TSPEC(comms, xbt_dynar_t)) sep \
230 action(SIMCALL_COMM_WAIT, comm_wait, WITHOUT_ANSWER, TVOID(result), TSPEC(comm, smx_action_t), TDOUBLE(timeout)) sep \
231 action(SIMCALL_COMM_TEST, comm_test, WITHOUT_ANSWER, TINT(result), TSPEC(comm, smx_action_t)) sep \
232 action(SIMCALL_COMM_TESTANY, comm_testany, WITHOUT_ANSWER, TINT(result), TSPEC(comms, xbt_dynar_t)) sep \
233 action(SIMCALL_COMM_GET_REMAINS, comm_get_remains, WITH_ANSWER, TDOUBLE(result), TSPEC(comm, smx_action_t)) sep \
234 action(SIMCALL_COMM_GET_STATE, comm_get_state, WITH_ANSWER, TINT(result), TSPEC(comm, smx_action_t)) sep \
235 action(SIMCALL_COMM_GET_SRC_DATA, comm_get_src_data, WITH_ANSWER, TPTR(result), TSPEC(comm, smx_action_t)) sep \
236 action(SIMCALL_COMM_GET_DST_DATA, comm_get_dst_data, WITH_ANSWER, TPTR(result), TSPEC(comm, smx_action_t)) sep \
237 action(SIMCALL_COMM_GET_SRC_PROC, comm_get_src_proc, WITH_ANSWER, TSPEC(result, smx_process_t), TSPEC(comm, smx_action_t)) sep \
238 action(SIMCALL_COMM_GET_DST_PROC, comm_get_dst_proc, WITH_ANSWER, TSPEC(result, smx_process_t), TSPEC(comm, smx_action_t)) sep \
239 action(SIMCALL_MUTEX_INIT, mutex_init, WITH_ANSWER, TSPEC(result, smx_mutex_t)) sep \
240 action(SIMCALL_MUTEX_DESTROY, mutex_destroy, WITH_ANSWER, TVOID(result), TSPEC(mutex, smx_mutex_t)) sep \
241 action(SIMCALL_MUTEX_LOCK, mutex_lock, WITHOUT_ANSWER, TVOID(result), TSPEC(mutex, smx_mutex_t)) sep \
242 action(SIMCALL_MUTEX_TRYLOCK, mutex_trylock, WITH_ANSWER, TINT(result), TSPEC(mutex, smx_mutex_t)) sep \
243 action(SIMCALL_MUTEX_UNLOCK, mutex_unlock, WITH_ANSWER, TVOID(result), TSPEC(mutex, smx_mutex_t)) sep \
244 action(SIMCALL_COND_INIT, cond_init, WITH_ANSWER, TSPEC(result, smx_cond_t)) sep \
245 action(SIMCALL_COND_DESTROY, cond_destroy, WITH_ANSWER, TVOID(result), TSPEC(cond, smx_cond_t)) sep \
246 action(SIMCALL_COND_SIGNAL, cond_signal, WITH_ANSWER, TVOID(result), TSPEC(cond, smx_cond_t)) sep \
247 action(SIMCALL_COND_WAIT, cond_wait, WITHOUT_ANSWER, TVOID(result), TSPEC(cond, smx_cond_t), TSPEC(mutex, smx_mutex_t)) sep \
248 action(SIMCALL_COND_WAIT_TIMEOUT, cond_wait_timeout, WITHOUT_ANSWER, TVOID(result), TSPEC(cond, smx_cond_t), TSPEC(mutex, smx_mutex_t), TDOUBLE(timeout)) sep \
249 action(SIMCALL_COND_BROADCAST, cond_broadcast, WITH_ANSWER, TVOID(result), TSPEC(cond, smx_cond_t)) sep \
250 action(SIMCALL_SEM_INIT, sem_init, WITH_ANSWER, TSPEC(result, smx_sem_t), TINT(capacity)) sep \
251 action(SIMCALL_SEM_DESTROY, sem_destroy, WITH_ANSWER, TVOID(result), TSPEC(sem, smx_sem_t)) sep \
252 action(SIMCALL_SEM_RELEASE, sem_release, WITH_ANSWER, TVOID(result), TSPEC(sem, smx_sem_t)) sep \
253 action(SIMCALL_SEM_WOULD_BLOCK, sem_would_block, WITH_ANSWER, TINT(result), TSPEC(sem, smx_sem_t)) sep \
254 action(SIMCALL_SEM_ACQUIRE, sem_acquire, WITHOUT_ANSWER, TVOID(result), TSPEC(sem, smx_sem_t)) sep \
255 action(SIMCALL_SEM_ACQUIRE_TIMEOUT, sem_acquire_timeout, WITHOUT_ANSWER, TVOID(result), TSPEC(sem, smx_sem_t), TDOUBLE(timeout)) sep \
256 action(SIMCALL_SEM_GET_CAPACITY, sem_get_capacity, WITH_ANSWER, TINT(result), TSPEC(sem, smx_sem_t)) sep \
257 action(SIMCALL_FILE_READ, file_read, WITHOUT_ANSWER, TDOUBLE(result), TPTR(ptr), TSIZE(size), TSIZE(nmemb), TSPEC(stream, smx_file_t)) sep \
258 action(SIMCALL_FILE_WRITE, file_write, WITHOUT_ANSWER, TSIZE(result), TCPTR(ptr), TSIZE(size), TSIZE(nmemb), TSPEC(stream, smx_file_t)) sep \
259 action(SIMCALL_FILE_OPEN, file_open, WITHOUT_ANSWER, TSPEC(result, smx_file_t), TSTRING(mount), TSTRING(path), TSTRING(mode)) sep \
260 action(SIMCALL_FILE_CLOSE, file_close, WITHOUT_ANSWER, TINT(result), TSPEC(fp, smx_file_t)) sep \
261 action(SIMCALL_FILE_STAT, file_stat, WITHOUT_ANSWER, TINT(result), TSPEC(fd, smx_file_t), TSTAT(buf)) sep \
262 action(SIMCALL_FILE_UNLINK, file_unlink, WITHOUT_ANSWER, TINT(result), TSPEC(fd, smx_file_t)) sep \
263 action(SIMCALL_FILE_LS, file_ls, WITHOUT_ANSWER, TSPEC(result, xbt_dict_t), TSTRING(mount), TSTRING(path)) sep \
264 action(SIMCALL_ASR_GET_PROPERTIES, asr_get_properties, WITH_ANSWER, TSPEC(result, xbt_dict_t), TSTRING(name)) sep 
265
266 /* SIMCALL_COMM_IS_LATENCY_BOUNDED and SIMCALL_SET_CATEGORY make things complicated
267  * because they are not always present */
268 #ifdef HAVE_LATENCY_BOUND_TRACKING
269 #define SIMCALL_LIST2(action, sep) \
270 action(SIMCALL_COMM_IS_LATENCY_BOUNDED, comm_is_latency_bounded, WITH_ANSWER, TINT(result), TSPEC(comm, smx_action_t)) sep
271 #else
272 #define SIMCALL_LIST2(action, sep)
273 #endif
274
275 #ifdef HAVE_TRACING
276 #define SIMCALL_LIST3(action, sep) \
277 action(SIMCALL_SET_CATEGORY, set_category, WITH_ANSWER, TVOID(result), TSPEC(action, smx_action_t), TSTRING(category)) sep
278 #else
279 #define SIMCALL_LIST3(action, sep)
280 #endif
281
282 #ifdef HAVE_MC
283 #define SIMCALL_LIST4(action, sep) \
284 action(SIMCALL_MC_SNAPSHOT, mc_snapshot, WITH_ANSWER, TPTR(result)) sep \
285 action(SIMCALL_MC_COMPARE_SNAPSHOTS, mc_compare_snapshots, WITH_ANSWER, TINT(result), TPTR(s1), TPTR(s2)) sep 
286 #else
287 #define SIMCALL_LIST4(action, sep)
288 #endif
289
290 /* SIMCALL_LIST is the final macro to use */
291 #define SIMCALL_LIST(action, ...) \
292   SIMCALL_LIST1(action, ##__VA_ARGS__)\
293   SIMCALL_LIST2(action, ##__VA_ARGS__)\
294   SIMCALL_LIST3(action, ##__VA_ARGS__)\
295   SIMCALL_LIST4(action, ##__VA_ARGS__)
296
297
298 /* you can redefine the following macro differently to generate something else
299  * with the list of enumeration values (e.g. a table of strings or a table of function pointers) */
300 #define SIMCALL_ENUM_ELEMENT(x, y) x
301
302 /**
303  * \brief All possible simcalls.
304  */
305 typedef enum {
306 SIMCALL_NONE,
307 SIMCALL_LIST(SIMCALL_ENUM, SIMCALL_SEP_COMMA)
308 SIMCALL_NEW_API_INIT,
309 NUM_SIMCALLS
310 } e_smx_simcall_t;
311
312 typedef int (*simix_match_func_t)(void *, void *, smx_action_t);
313 typedef void (*simix_clean_func_t)(void *);
314
315 /**
316  * \brief Prototypes of SIMIX
317  */
318 SIMCALL_LIST(SIMCALL_FUNC_PROTO, SIMCALL_SEP_NOTHING)
319
320
321 /* Pack all possible scalar types in an union */
322 union u_smx_scalar {
323   char            c;
324   const char*     cc;
325   short           s;
326   int             i;
327   long            l;
328   unsigned char   uc;
329   unsigned short  us;
330   unsigned int    ui;
331   unsigned long   ul;
332   float           f;
333   double          d;
334   size_t          si;
335   s_file_stat_t   fs;
336   void*           p;
337   const void*     cp;
338 };
339
340 /**
341  * \brief Represents a simcall to the kernel.
342  */
343 typedef struct s_smx_simcall {
344   e_smx_simcall_t call;
345   smx_process_t issuer;
346   int mc_value;
347   union u_smx_scalar *args;
348   union u_smx_scalar result;
349   //FIXME: union u_smx_scalar retval;
350
351   union {
352
353     struct {
354       const char *name;
355       smx_host_t result;
356     } host_get_by_name;
357
358     struct {
359       smx_host_t host;
360       const char* result;
361     } host_get_name;
362
363     struct {
364       smx_host_t host;
365       xbt_dict_t result;
366     } host_get_properties;
367
368     struct {
369       smx_host_t host;
370       double result;
371     } host_get_speed;
372
373     struct {
374       smx_host_t host;
375       double result;
376     } host_get_available_speed;
377
378     struct {
379       smx_host_t host;
380       int result;
381     } host_get_state;
382
383     struct {
384       smx_host_t host;
385       void* result;
386     } host_get_data;
387
388     struct {
389       smx_host_t host;
390       void* data;
391     } host_set_data;
392
393     struct {
394       const char* name;
395       smx_host_t host;
396       double computation_amount;
397       double priority;
398       smx_action_t result;
399     } host_execute;
400
401     struct {
402       const char *name;
403       int host_nb;
404       smx_host_t *host_list;
405       double *computation_amount;
406       double *communication_amount;
407       double amount;
408       double rate;
409       smx_action_t result;
410     } host_parallel_execute;
411
412     struct {
413       smx_action_t execution;
414     } host_execution_destroy;
415
416     struct {
417       smx_action_t execution;
418     } host_execution_cancel;
419
420     struct {
421       smx_action_t execution;
422       double result;
423     } host_execution_get_remains;
424
425     struct {
426       smx_action_t execution;
427       e_smx_state_t result;
428     } host_execution_get_state;
429
430     struct {
431       smx_action_t execution;
432       double priority;
433     } host_execution_set_priority;
434
435     struct {
436       smx_action_t execution;
437       struct s_smx_simcall *simcall;
438       e_smx_state_t result;
439
440     } host_execution_wait;
441
442     struct {
443       smx_process_t *process;
444       const char *name;
445       xbt_main_func_t code;
446       void *data;
447       const char *hostname;
448       double kill_time;
449       int argc;
450       char **argv;
451       xbt_dict_t properties;
452       int auto_restart;
453     } process_create;
454
455     struct {
456       smx_process_t process;
457     } process_kill;
458
459     struct {
460       smx_process_t process;
461     } process_cleanup;
462
463     struct {
464       smx_process_t process;
465       smx_host_t dest;
466     } process_change_host;
467
468     struct {
469       smx_process_t process;
470     } process_suspend;
471
472     struct {
473       smx_process_t process;
474     } process_resume;
475
476     struct {
477       int result;
478     } process_count;
479
480     struct {
481       smx_process_t process;
482       void* result;
483     } process_get_data;
484
485     struct {
486       smx_process_t process;
487       void* data;
488     } process_set_data;
489
490     struct {
491       smx_process_t process;
492       smx_host_t result;
493     } process_get_host;
494
495     struct {
496       smx_process_t process;
497       const char *result;
498     } process_get_name;
499
500     struct {
501       smx_process_t process;
502       int result;
503     } process_is_suspended;
504
505     struct {
506       smx_process_t process;
507       xbt_dict_t result;
508     } process_get_properties;
509
510     struct {
511       double duration;
512       e_smx_state_t result;
513     } process_sleep;
514
515     struct {
516       smx_process_t process;
517       int_f_pvoid_t fun;
518       void *data;
519     } process_on_exit;
520
521     struct {
522       smx_process_t process;
523       int auto_restart;
524     } process_auto_restart;
525
526     struct {
527       smx_process_t process;
528       smx_process_t result;
529     } process_restart;
530
531     struct {
532       const char *name;
533       smx_rdv_t result;
534     } rdv_create;
535
536     struct {
537       smx_rdv_t rdv;
538     } rdv_destroy;
539
540     struct {
541       const char* name;
542       smx_rdv_t result;
543     } rdv_get_by_name;
544
545     struct {
546       smx_rdv_t rdv;
547       smx_host_t host;
548       unsigned int result; 
549     } rdv_comm_count_by_host;
550
551     struct {
552       smx_rdv_t rdv;
553       smx_action_t result;
554     } rdv_get_head;
555
556     struct {
557       smx_rdv_t rdv;
558       smx_process_t receiver;
559     } rdv_set_rcv_proc;
560
561     struct {
562       smx_rdv_t rdv;
563       smx_process_t result;
564     } rdv_get_rcv_proc;
565
566     struct {
567       smx_rdv_t rdv;
568       double task_size;
569       double rate;
570       void *src_buff;
571       size_t src_buff_size;
572       int (*match_fun)(void *, void *, smx_action_t);
573       void *data;
574       double timeout;
575     } comm_send;
576
577     struct {
578       smx_rdv_t rdv;
579       double task_size;
580       double rate;
581       void *src_buff;
582       size_t src_buff_size;
583       int (*match_fun)(void *, void *, smx_action_t);
584       void (*clean_fun)(void *);
585       void *data;
586       int detached;
587       smx_action_t result;
588     } comm_isend;
589
590     struct {
591       smx_rdv_t rdv;
592       void *dst_buff;
593       size_t *dst_buff_size;
594       int (*match_fun)(void *, void *, smx_action_t);
595       void *data;
596       double timeout;
597     } comm_recv;
598
599     struct {
600       smx_rdv_t rdv;
601       void *dst_buff;
602       size_t *dst_buff_size;
603       int (*match_fun)(void *, void *, smx_action_t);
604       void *data;
605       smx_action_t result;
606     } comm_irecv;
607
608     struct {
609       smx_rdv_t rdv;
610       int src;
611       int tag;
612       int (*match_fun)(void *, void *, smx_action_t);
613       void *data;
614       smx_action_t result;
615     } comm_iprobe;
616
617     struct {
618       smx_action_t comm;
619     } comm_destroy;
620
621     struct {
622       smx_action_t comm;
623     } comm_cancel;
624
625     struct {
626       xbt_dynar_t comms;
627       unsigned int result;
628     } comm_waitany;
629
630     struct {
631       smx_action_t comm;
632       double timeout;
633     } comm_wait;
634
635     struct {
636       smx_action_t comm;
637       int result;
638     } comm_test;
639
640     struct {
641       xbt_dynar_t comms;
642       int result;
643     } comm_testany;
644
645     struct {
646       smx_action_t comm;
647       double result;
648     } comm_get_remains;
649
650     struct {
651       smx_action_t comm;
652       e_smx_state_t result;
653     } comm_get_state;
654
655     struct {
656       smx_action_t comm;
657       void *result;
658     } comm_get_src_data;
659
660     struct {
661       smx_action_t comm;
662       void *result;
663     } comm_get_dst_data;
664
665     struct {
666       smx_action_t comm;
667       smx_process_t result;
668     } comm_get_src_proc;
669
670     struct {
671       smx_action_t comm;
672       smx_process_t result;
673     } comm_get_dst_proc;
674
675 #ifdef HAVE_LATENCY_BOUND_TRACKING
676     struct {
677       smx_action_t comm;
678       int result;
679     } comm_is_latency_bounded;
680 #endif
681
682 #ifdef HAVE_TRACING
683     struct {
684       smx_action_t action;
685       const char *category;
686     } set_category;
687 #endif
688
689     struct {
690       smx_mutex_t result;
691     } mutex_init;
692
693     struct {
694       smx_mutex_t mutex;
695     } mutex_lock;
696
697     struct {
698       smx_mutex_t mutex;
699       int result;
700     } mutex_trylock;
701
702     struct {
703       smx_mutex_t mutex;
704     } mutex_unlock;
705
706     struct {
707       smx_mutex_t mutex;
708     } mutex_destroy;
709
710     struct {
711       smx_cond_t result;
712     } cond_init;
713
714     struct {
715       smx_cond_t cond;
716     } cond_destroy;
717
718     struct {
719       smx_cond_t cond;
720     } cond_signal;
721
722     struct {
723       smx_cond_t cond;
724       smx_mutex_t mutex;
725     } cond_wait;
726
727     struct {
728       smx_cond_t cond;
729       smx_mutex_t mutex;
730       double timeout;
731     } cond_wait_timeout;
732
733     struct {
734       smx_cond_t cond;
735     } cond_broadcast;
736
737     struct {
738       int capacity;
739       smx_sem_t result;
740     } sem_init;
741
742     struct {
743       smx_sem_t sem;
744     } sem_destroy;
745
746     struct {
747       smx_sem_t sem;
748     } sem_release;
749
750     struct {
751       smx_sem_t sem;
752       int result;
753     } sem_would_block;
754
755     struct {
756       smx_sem_t sem;
757     } sem_acquire;
758
759     struct {
760       smx_sem_t sem;
761       double timeout;
762     } sem_acquire_timeout;
763
764     struct {
765       smx_sem_t sem;
766       int result;
767     } sem_get_capacity;
768
769     struct {
770       void *ptr;
771       size_t size;
772       size_t nmemb;
773       smx_file_t stream;
774       double result;
775     } file_read;
776
777     struct {
778       const void *ptr;
779       size_t size;
780       size_t nmemb;
781       smx_file_t stream;
782       size_t result;
783     } file_write;
784
785     struct {
786       const char* mount;
787       const char* path;
788       const char* mode;
789       smx_file_t result;
790     } file_open;
791
792     struct {
793       smx_file_t fp;
794       int result;
795     } file_close;
796
797     struct {
798       smx_file_t fd;
799       s_file_stat_t buf;
800       int result;
801     } file_stat;
802
803     struct {
804       smx_file_t fd;
805       int result;
806     } file_unlink;
807
808     struct {
809       const char *mount;
810       const char *path;
811       xbt_dict_t result;
812     } file_ls;
813
814     struct {
815       const char* name;
816       xbt_dict_t result;
817     } asr_get_properties;
818
819     struct{
820       void *s;
821     } mc_snapshot;
822
823     struct{
824       void *snapshot1;
825       void *snapshot2;
826       int result;
827     } mc_compare_snapshots;
828
829     /* ****************************************************************************************** */
830     /* TUTORIAL: New API                                                                        */
831     /* ****************************************************************************************** */
832     struct {
833       const char* param1;
834       double param2;
835       int result;
836     } new_api;
837
838   };
839 } s_smx_simcall_t, *smx_simcall_t;
840
841
842
843 /******************************** General *************************************/
844
845 void SIMIX_simcall_push(smx_process_t self);
846 void SIMIX_simcall_answer(smx_simcall_t);
847 void SIMIX_simcall_pre(smx_simcall_t, int);
848 void SIMIX_simcall_post(smx_action_t);
849 smx_simcall_t SIMIX_simcall_mine(void);
850 const char *SIMIX_simcall_name(e_smx_simcall_t kind);
851 //TOFIX put it in a better place
852 xbt_dict_t SIMIX_pre_asr_get_properties(smx_simcall_t simcall, const char *name);
853
854 /*************************** New simcall interface ****************************/
855
856 #define SIMIX_pack_args(...) (u_smx_scalar_t[]){MAP(INIT_FIELD, __VA_ARGS__)}
857
858
859 /*
860  * Define scalar type wrappers to ease the use of simcalls.
861  * These are used to wrap the arguments in SIMIX_simcall macro.
862  */
863 #define CHAR(x) (c,x)
864 #define STRING(x) (cc,x)
865 #define SHORT(x) (s,x)
866 #define INT(x) (i,x)
867 #define LONG(x) (l,x)
868 #define UCHAR(x) (uc,x)
869 #define USHORT(x) (us,x)
870 #define UINT(x) (ui,x)
871 #define ULONG(x) (ul,x)
872 #define FLOAT(x) (f,x)
873 #define DOUBLE(x) (d,x)
874 #define PTR(x)  (p,x)
875
876 /*
877  * Some macro machinery to get a MAP over the arguments of a variadic macro.
878  * It uses a FOLD to apply a macro to every argument, and because there is
879  * no recursion in the C preprocessor we must create a new macro for every
880  * depth of FOLD's recursion.
881  */
882
883 /* FOLD macro */
884 #define FE_0(WHAT, X, ...)
885 #define FE_1(I, WHAT, X) WHAT(I, X)
886 #define FE_2(I, WHAT, X, ...) WHAT(I, X), FE_1(I+1, WHAT, __VA_ARGS__)
887 #define FE_3(I, WHAT, X, ...) WHAT(I, X), FE_2(I+1, WHAT, __VA_ARGS__)
888 #define FE_4(I, WHAT, X, ...) WHAT(I, X), FE_3(I+1, WHAT, __VA_ARGS__)
889 #define FE_5(I, WHAT, X, ...) WHAT(I, X), FE_4(I+1, WHAT, __VA_ARGS__)
890 #define FE_6(I, WHAT, X, ...) WHAT(I, X), FE_5(I+1, WHAT, __VA_ARGS__)
891 #define FE_7(I, WHAT, X, ...) WHAT(I, X), FE_6(I+1, WHAT, __VA_ARGS__)
892 #define FE_8(I, WHAT, X, ...) WHAT(I, X), FE_7(I+1, WHAT, __VA_ARGS__)
893 #define FE_9(I, WHAT, X, ...) WHAT(I, X), FE_8(I+1, WHAT, __VA_ARGS__)
894 #define FE_10(I, WHAT, X, ...) WHAT(I, X), FE_9(I+1, WHAT, __VA_ARGS__)
895
896
897 /* NOTE: add as many FE_n as needed (maximum number of simcall arguments )*/
898
899 /* Make a MAP macro usgin FOLD (will apply 'action' to the arguments.
900  * GET_MACRO is a smart hack that counts the number of arguments passed to
901  * the variadic macro, and it is used to invoke the right FOLD depth.
902  */
903 #define GET_MACRO(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,NAME,...) NAME
904 #define MAP(action, ...) \
905   GET_MACRO(, ##__VA_ARGS__, FE_10,FE_9,FE_8,FE_7,FE_6,FE_5,FE_4,FE_3,FE_2,FE_1, FE_0) (0, action, __VA_ARGS__)
906
907 /* Generate code to initialize the field 'x' with value 'y' of an structure or union */
908 #define INIT_FIELD_(x,y) {.x = y}
909 #define INIT_FIELD(t) INIT_FIELD_ t
910
911 /* Project the second element of a tuple */
912 #define SECOND_(x, y) y
913 #define SECOND(t) SECOND_ t
914
915 /*
916  * \brief Simcall invocation macro
917  * It calls a dummy function that uses the format attribute to ensure typesafety (see
918  * gcc format attribute), then it invokes the real simcall function packing the
919  * user provided arguments in an array.
920  * \param id a simcall id (from the simcall enumeration ids)
921  *
922  */
923 #define SIMIX_simcall(id, ...) \
924   SIMIX_simcall_typecheck(simcall_types[id], MAP(SECOND, __VA_ARGS__)); \
925   __SIMIX_simcall(id, (u_smx_scalar_t[]){MAP(INIT_FIELD, __VA_ARGS__)})
926
927 smx_simcall_t __SIMIX_simcall(e_smx_simcall_t simcall_id, u_smx_scalar_t *args);
928
929 /*
930  * \biref Dummy variadic function used to typecheck the arguments of a simcall
931  * \param fmt A format string following printf style
932  */
933 void SIMIX_simcall_typecheck(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
934
935 typedef smx_action_t (*simcall_handler_t)(u_smx_scalar_t *);
936
937 extern const char *simcall_types[];
938 extern simcall_handler_t simcall_table[];
939
940 #endif
941