Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Lua: don't garbage collect a task after sending it (the receiver will)
[simgrid.git] / src / bindings / lua / simgrid_lua.c
1 /* Copyright (c) 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 /* SimGrid Lua bindings                                                     */
8
9 #include "simgrid_lua.h"
10 #include "lua_state_cloner.h"
11 #include "lua_utils.h"
12
13 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(lua, bindings, "Lua Bindings");
14
15 #define TASK_MODULE_NAME "simgrid.Task"
16 #define HOST_MODULE_NAME "simgrid.Host"
17 // Surf (bypass XML)
18 #define LINK_MODULE_NAME "simgrid.Link"
19 #define ROUTE_MODULE_NAME "simgrid.Route"
20 #define AS_MODULE_NAME "simgrid.AS"
21 #define TRACE_MODULE_NAME "simgrid.Trace"
22
23 /**
24  * @brief Userdata type for tasks.
25  */
26 typedef struct s_sglua_task {
27   m_task_t msg_task;    /**< the task, or NULL if I sent it to someone else */
28 } s_sglua_task_t, *sglua_task_t;
29
30 static lua_State* sglua_maestro_state;
31
32 static void register_c_functions(lua_State *L);
33
34 /**
35  * \brief Like luaL_checkudata, with additional debug logs.
36  * \param L a lua state
37  * \param ud index of the userdata to check in the stack
38  * \param tname key of the metatable of this userdata in the registry
39  */
40 static void* my_checkudata(lua_State* L, int ud, const char* tname) {
41
42   XBT_DEBUG("Checking the userdata: ud = %d", ud);
43   sglua_stack_dump("my_checkudata: ", L);
44   void* p = lua_touserdata(L, ud);
45   lua_getfield(L, LUA_REGISTRYINDEX, tname);
46   const void* correct_mt = lua_topointer(L, -1);
47
48   int has_mt = lua_getmetatable(L, ud);
49   XBT_DEBUG("Checking the userdata: has metatable ? %d", has_mt);
50   const void* actual_mt = NULL;
51   if (has_mt) {
52     actual_mt = lua_topointer(L, -1);
53     lua_pop(L, 1);
54   }
55   XBT_DEBUG("Checking the task's metatable: expected %p, found %p", correct_mt, actual_mt);
56   sglua_stack_dump("my_checkudata: ", L);
57
58   if (p == NULL || !lua_getmetatable(L, ud) || !lua_rawequal(L, -1, -2))
59     luaL_typerror(L, ud, tname);
60   lua_pop(L, 2);
61   return p;
62 }
63
64 /**
65  * @brief Ensures that a value is a valid task and returns it.
66  * @param L a Lua state
67  * @param index an index in the Lua stack
68  * @return the task at this index
69  */
70 static m_task_t checkTask(lua_State* L, int index)
71 {
72   sglua_stack_dump("checkTask: ", L);
73   luaL_checktype(L, index, LUA_TTABLE);
74                                   /* ... task ... */
75   lua_getfield(L, index, "__simgrid_task");
76                                   /* ... task ... ctask */
77   m_task_t task = *((m_task_t*) luaL_checkudata(L, -1, TASK_MODULE_NAME));
78   lua_pop(L, 1);
79                                   /* ... task ... */
80
81   if (task == NULL) {
82     luaL_error(L, "This task was sent to someone else, you cannot access it anymore");
83   }
84
85   return task;
86 }
87
88 /* ********************************************************************************* */
89 /*                           wrapper functions                                       */
90 /* ********************************************************************************* */
91
92 /**
93  * \brief Creates a new task and leaves it onto the stack.
94  *
95  * Lua arguments:
96  * - task name (string)
97  * - computation size (integer)
98  * - communication size (integer)
99  */
100 static int Task_new(lua_State* L)
101 {
102   XBT_DEBUG("Task new");
103   const char* name = luaL_checkstring(L, 1);
104   int comp_size = luaL_checkint(L, 2);
105   int msg_size = luaL_checkint(L, 3);
106                                   /* name comp comm */
107   lua_settop(L, 0);
108                                   /* -- */
109   m_task_t msg_task = MSG_task_create(name, comp_size, msg_size, NULL);
110
111   lua_newtable(L);
112                                   /* task */
113   m_task_t* lua_task = (m_task_t*) lua_newuserdata(L, sizeof(m_task_t));
114                                   /* task ctask */
115   *lua_task = msg_task;
116   luaL_getmetatable(L, TASK_MODULE_NAME);
117                                   /* task ctask mt */
118   lua_setmetatable(L, -2);
119                                   /* task ctask */
120   lua_setfield(L, -2, "__simgrid_task");
121                                   /* task */
122   return 1;
123 }
124
125 static int Task_get_name(lua_State* L)
126 {
127   m_task_t task = checkTask(L, 1);
128   lua_pushstring(L, MSG_task_get_name(task));
129   return 1;
130 }
131
132 static int Task_computation_duration(lua_State* L)
133 {
134   m_task_t task = checkTask(L, 1);
135   lua_pushnumber(L, MSG_task_get_compute_duration(task));
136   return 1;
137 }
138
139 static int Task_execute(lua_State* L)
140 {
141   m_task_t task = checkTask(L, 1);
142   int res = MSG_task_execute(task);
143   lua_pushnumber(L, res);
144   return 1;
145 }
146
147 static int Task_send(lua_State* L)
148 {
149   m_task_t task = checkTask(L, 1);
150   const char* mailbox = luaL_checkstring(L, 2);
151                                   /* task mailbox */
152   lua_settop(L, 1);
153                                   /* task */
154   /* copy my stack into the task, so that the receiver can copy the lua task */
155   MSG_task_set_data(task, L);
156   MSG_error_t res = MSG_task_send(task, mailbox);
157   while (MSG_task_get_data(task) != NULL) {
158     /* don't mess up with my stack: the receiver didn't copy the data yet */
159     MSG_process_sleep(0);
160   }
161
162   if (res == MSG_OK) {
163     /* the receiver is the owner of the task and may destroy it:
164      * remove the C task on my side so that I don't garbage collect it */
165     lua_getfield(L, 1, "__simgrid_task");
166                                   /* task ctask */
167     m_task_t* udata = (m_task_t*) luaL_checkudata(L, -1, TASK_MODULE_NAME);
168     *udata = NULL;
169     lua_pop(L, 1);
170                                   /* task */
171   }
172   else {
173     switch (res) {
174     case MSG_TIMEOUT:
175       XBT_DEBUG("MSG_task_send failed : Timeout");
176       break;
177     case MSG_TRANSFER_FAILURE:
178       XBT_DEBUG("MSG_task_send failed : Transfer Failure");
179       break;
180     case MSG_HOST_FAILURE:
181       XBT_DEBUG("MSG_task_send failed : Host Failure ");
182       break;
183     default:
184       XBT_ERROR
185           ("MSG_task_send failed : Unexpected error , please report this bug");
186       break;
187     }
188   }
189   return 0;
190 }
191
192 static int Task_recv_with_timeout(lua_State *L)
193 {
194   m_task_t task = NULL;
195   const char* mailbox = luaL_checkstring(L, 1);
196   int timeout = luaL_checknumber(L, 2);
197                                   /* mailbox timeout */
198   lua_settop(L, 0);
199                                   /* -- */
200   MSG_error_t res = MSG_task_receive_with_timeout(&task, mailbox, timeout);
201
202   if (res == MSG_OK) {
203     /* copy the data directly from sender's stack */
204     lua_State* sender_stack = MSG_task_get_data(task);
205     sglua_copy_value(sender_stack, L);
206                                   /* task */
207     MSG_task_set_data(task, NULL);
208   }
209   else {
210     switch (res) {
211     case MSG_TIMEOUT:
212       XBT_DEBUG("MSG_task_receive failed : Timeout");
213       break;
214     case MSG_TRANSFER_FAILURE:
215       XBT_DEBUG("MSG_task_receive failed : Transfer Failure");
216       break;
217     case MSG_HOST_FAILURE:
218       XBT_DEBUG("MSG_task_receive failed : Host Failure ");
219       break;
220     default:
221       XBT_ERROR("MSG_task_receive failed : Unexpected error , please report this bug");
222       break;
223     }
224     lua_pushnil(L);
225                                   /* nil */
226   }
227                                   /* task/nil */
228   return 1;
229 }
230
231 static int Task_recv(lua_State * L)
232 {
233   lua_pushnumber(L, -1.0);
234   return Task_recv_with_timeout(L);
235 }
236
237 static const luaL_reg Task_methods[] = {
238   {"new", Task_new},
239   {"name", Task_get_name},
240   {"computation_duration", Task_computation_duration},
241   {"execute", Task_execute},
242   {"send", Task_send},
243   {"recv", Task_recv},
244   {"recv_timeout", Task_recv_with_timeout},
245   {NULL, NULL}
246 };
247
248 static int Task_gc(lua_State* L)
249 {
250                                   /* ctask */
251   m_task_t task = *((m_task_t*) luaL_checkudata(L, 1, TASK_MODULE_NAME));
252   /* the task is NULL if I sent it to someone else */
253   if (task != NULL) {
254     MSG_task_destroy(task);
255   }
256   return 0;
257 }
258
259 static int Task_tostring(lua_State* L)
260 {
261   m_task_t task = checkTask(L, 1);
262   lua_pushfstring(L, "Task: %p", task);
263   return 1;
264 }
265
266 static const luaL_reg Task_meta[] = {
267   {"__gc", Task_gc},
268   {"__tostring", Task_tostring},
269   {NULL, NULL}
270 };
271
272 /**
273  * Host
274  */
275 static m_host_t checkHost(lua_State * L, int index)
276 {
277   m_host_t *pi, ht;
278   luaL_checktype(L, index, LUA_TTABLE);
279   lua_getfield(L, index, "__simgrid_host");
280   pi = (m_host_t *) luaL_checkudata(L, lua_gettop(L), HOST_MODULE_NAME);
281   if (pi == NULL)
282     luaL_typerror(L, index, HOST_MODULE_NAME);
283   ht = *pi;
284   if (!ht)
285     luaL_error(L, "null Host");
286   lua_pop(L, 1);
287   return ht;
288 }
289
290 static int Host_get_by_name(lua_State * L)
291 {
292   const char *name = luaL_checkstring(L, 1);
293   XBT_DEBUG("Getting Host from name...");
294   m_host_t msg_host = MSG_get_host_by_name(name);
295   if (!msg_host) {
296     luaL_error(L, "null Host : MSG_get_host_by_name failed");
297   }
298   lua_newtable(L);              /* create a table, put the userdata on top of it */
299   m_host_t *lua_host = (m_host_t *) lua_newuserdata(L, sizeof(m_host_t));
300   *lua_host = msg_host;
301   luaL_getmetatable(L, HOST_MODULE_NAME);
302   lua_setmetatable(L, -2);
303   lua_setfield(L, -2, "__simgrid_host");        /* put the userdata as field of the table */
304   /* remove the args from the stack */
305   lua_remove(L, 1);
306   return 1;
307 }
308
309 static int Host_get_name(lua_State * L)
310 {
311   m_host_t ht = checkHost(L, -1);
312   lua_pushstring(L, MSG_host_get_name(ht));
313   return 1;
314 }
315
316 static int Host_number(lua_State * L)
317 {
318   lua_pushnumber(L, MSG_get_host_number());
319   return 1;
320 }
321
322 static int Host_at(lua_State * L)
323 {
324   int index = luaL_checkinteger(L, 1);
325   m_host_t host = MSG_get_host_table()[index - 1];      // lua indexing start by 1 (lua[1] <=> C[0])
326   lua_newtable(L);              /* create a table, put the userdata on top of it */
327   m_host_t *lua_host = (m_host_t *) lua_newuserdata(L, sizeof(m_host_t));
328   *lua_host = host;
329   luaL_getmetatable(L, HOST_MODULE_NAME);
330   lua_setmetatable(L, -2);
331   lua_setfield(L, -2, "__simgrid_host");        /* put the userdata as field of the table */
332   return 1;
333
334 }
335
336 static int Host_self(lua_State * L)
337 {
338                                   /* -- */
339   m_host_t host = MSG_host_self();
340   lua_newtable(L);
341                                   /* table */
342   m_host_t* lua_host = (m_host_t*) lua_newuserdata(L, sizeof(m_host_t));
343                                   /* table ud */
344   *lua_host = host;
345   luaL_getmetatable(L, HOST_MODULE_NAME);
346                                   /* table ud mt */
347   lua_setmetatable(L, -2);
348                                   /* table ud */
349   lua_setfield(L, -2, "__simgrid_host");
350                                   /* table */
351   return 1;
352 }
353
354 static int Host_get_property_value(lua_State * L)
355 {
356   m_host_t ht = checkHost(L, -2);
357   const char *prop = luaL_checkstring(L, -1);
358   lua_pushstring(L,MSG_host_get_property_value(ht,prop));
359   return 1;
360 }
361
362 static int Host_sleep(lua_State *L)
363 {
364   int time = luaL_checknumber(L, -1);
365   MSG_process_sleep(time);
366   return 1;
367 }
368
369 static int Host_destroy(lua_State *L)
370 {
371   m_host_t ht = checkHost(L, -1);
372   __MSG_host_destroy(ht);
373   return 1;
374 }
375
376 /* ********************************************************************************* */
377 /*                           lua_stub_generator functions                            */
378 /* ********************************************************************************* */
379
380 xbt_dict_t process_function_set;
381 xbt_dynar_t process_list;
382 xbt_dict_t machine_set;
383 static s_process_t process;
384
385 void s_process_free(void *process)
386 {
387   s_process_t *p = (s_process_t *) process;
388   int i;
389   for (i = 0; i < p->argc; i++)
390     free(p->argv[i]);
391   free(p->argv);
392   free(p->host);
393 }
394
395 static int gras_add_process_function(lua_State * L)
396 {
397   const char *arg;
398   const char *process_host = luaL_checkstring(L, 1);
399   const char *process_function = luaL_checkstring(L, 2);
400
401   if (xbt_dict_is_empty(machine_set)
402       || xbt_dict_is_empty(process_function_set)
403       || xbt_dynar_is_empty(process_list)) {
404     process_function_set = xbt_dict_new();
405     process_list = xbt_dynar_new(sizeof(s_process_t), s_process_free);
406     machine_set = xbt_dict_new();
407   }
408
409   xbt_dict_set(machine_set, process_host, NULL, NULL);
410   xbt_dict_set(process_function_set, process_function, NULL, NULL);
411
412   process.argc = 1;
413   process.argv = xbt_new(char *, 1);
414   process.argv[0] = xbt_strdup(process_function);
415   process.host = strdup(process_host);
416
417   lua_pushnil(L);
418   while (lua_next(L, 3) != 0) {
419     arg = lua_tostring(L, -1);
420     process.argc++;
421     process.argv =
422         xbt_realloc(process.argv, (process.argc) * sizeof(char *));
423     process.argv[(process.argc) - 1] = xbt_strdup(arg);
424
425     XBT_DEBUG("index = %f , arg = %s \n", lua_tonumber(L, -2),
426            lua_tostring(L, -1));
427     lua_pop(L, 1);
428   }
429   lua_pop(L, 1);
430   //add to the process list
431   xbt_dynar_push(process_list, &process);
432   return 0;
433 }
434
435
436 static int gras_generate(lua_State * L)
437 {
438   const char *project_name = luaL_checkstring(L, 1);
439   generate_sim(project_name);
440   generate_rl(project_name);
441   generate_makefile_local(project_name);
442   return 0;
443 }
444
445 /***********************************
446  *      Tracing
447  **********************************/
448 static int trace_start(lua_State *L)
449 {
450 #ifdef HAVE_TRACING
451   TRACE_start();
452 #endif
453   return 1;
454 }
455
456 static int trace_category(lua_State * L)
457 {
458 #ifdef HAVE_TRACING
459   TRACE_category(luaL_checkstring(L, 1));
460 #endif
461   return 1;
462 }
463
464 static int trace_set_task_category(lua_State *L)
465 {
466 #ifdef HAVE_TRACING
467   TRACE_msg_set_task_category(checkTask(L, -2), luaL_checkstring(L, -1));
468 #endif
469   return 1;
470 }
471
472 static int trace_end(lua_State *L)
473 {
474 #ifdef HAVE_TRACING
475   TRACE_end();
476 #endif
477   return 1;
478 }
479
480 // *********** Register Methods ******************************************* //
481
482 /*
483  * Host Methods
484  */
485 static const luaL_reg Host_methods[] = {
486   {"getByName", Host_get_by_name},
487   {"name", Host_get_name},
488   {"number", Host_number},
489   {"at", Host_at},
490   {"self", Host_self},
491   {"getPropValue", Host_get_property_value},
492   {"sleep", Host_sleep},
493   {"destroy", Host_destroy},
494   // Bypass XML Methods
495   {"setFunction", console_set_function},
496   {"setProperty", console_host_set_property},
497   {NULL, NULL}
498 };
499
500 static int Host_gc(lua_State * L)
501 {
502   m_host_t ht = checkHost(L, -1);
503   if (ht)
504     ht = NULL;
505   return 0;
506 }
507
508 static int Host_tostring(lua_State * L)
509 {
510   lua_pushfstring(L, "Host :%p", lua_touserdata(L, 1));
511   return 1;
512 }
513
514 static const luaL_reg Host_meta[] = {
515   {"__gc", Host_gc},
516   {"__tostring", Host_tostring},
517   {0, 0}
518 };
519
520 /*
521  * AS Methods
522  */
523 static const luaL_reg AS_methods[] = {
524   {"new", console_add_AS},
525   {"addHost", console_add_host},
526   {"addLink", console_add_link},
527   {"addRoute", console_add_route},
528   {NULL, NULL}
529 };
530
531 /**
532  * Tracing Functions
533  */
534 static const luaL_reg Trace_methods[] = {
535   {"start", trace_start},
536   {"category", trace_category},
537   {"setTaskCategory", trace_set_task_category},
538   {"finish", trace_end},
539   {NULL, NULL}
540 };
541
542 /*
543  * Environment related
544  */
545
546 /**
547  * @brief Runs a Lua function as a new simulated process.
548  * @param argc number of arguments of the function
549  * @param argv name of the Lua function and array of its arguments
550  * @return result of the function
551  */
552 static int run_lua_code(int argc, char **argv)
553 {
554   XBT_DEBUG("Run lua code %s", argv[0]);
555
556   lua_State *L = sglua_clone_maestro();
557   int res = 1;
558
559   /* start the function */
560   lua_getglobal(L, argv[0]);
561   xbt_assert(lua_isfunction(L, -1),
562               "The lua function %s does not seem to exist", argv[0]);
563
564   /* push arguments onto the stack */
565   int i;
566   for (i = 1; i < argc; i++)
567     lua_pushstring(L, argv[i]);
568
569   /* call the function */
570   _XBT_GNUC_UNUSED int err;
571   err = lua_pcall(L, argc - 1, 1, 0);
572   xbt_assert(err == 0, "error running function `%s': %s", argv[0],
573               lua_tostring(L, -1));
574
575   /* retrieve result */
576   if (lua_isnumber(L, -1)) {
577     res = lua_tonumber(L, -1);
578     lua_pop(L, 1);              /* pop returned value */
579   }
580
581   XBT_DEBUG("Execution of Lua code %s is over", (argv ? argv[0] : "(null)"));
582
583   return res;
584 }
585
586 static int launch_application(lua_State * L)
587 {
588   const char *file = luaL_checkstring(L, 1);
589   MSG_function_register_default(run_lua_code);
590   MSG_launch_application(file);
591   return 0;
592 }
593
594 static int create_environment(lua_State * L)
595 {
596   const char *file = luaL_checkstring(L, 1);
597   XBT_DEBUG("Loading environment file %s", file);
598   MSG_create_environment(file);
599   return 0;
600 }
601
602 static int debug(lua_State * L)
603 {
604   const char *str = luaL_checkstring(L, 1);
605   XBT_DEBUG("%s", str);
606   return 0;
607 }
608
609 static int info(lua_State * L)
610 {
611   const char *str = luaL_checkstring(L, 1);
612   XBT_INFO("%s", str);
613   return 0;
614 }
615
616 static int run(lua_State * L)
617 {
618   MSG_main();
619   return 0;
620 }
621
622 static int clean(lua_State * L)
623 {
624   MSG_clean();
625   return 0;
626 }
627
628 /*
629  * Bypass XML Parser (lua console)
630  */
631
632 /*
633  * Register platform for MSG
634  */
635 static int msg_register_platform(lua_State * L)
636 {
637   /* Tell Simgrid we dont wanna use its parser */
638   surf_parse = console_parse_platform;
639   surf_parse_reset_callbacks();
640   MSG_create_environment(NULL);
641   return 0;
642 }
643
644 /*
645  * Register platform for Simdag
646  */
647
648 static int sd_register_platform(lua_State * L)
649 {
650   surf_parse = console_parse_platform_wsL07;
651   surf_parse_reset_callbacks();
652   SD_create_environment(NULL);
653   return 0;
654 }
655
656 /*
657  * Register platform for gras
658  */
659 static int gras_register_platform(lua_State * L)
660 {
661   /* Tell Simgrid we dont wanna use surf parser */
662   surf_parse = console_parse_platform;
663   surf_parse_reset_callbacks();
664   gras_create_environment(NULL);
665   return 0;
666 }
667
668 /**
669  * Register applicaiton for MSG
670  */
671 static int msg_register_application(lua_State * L)
672 {
673   MSG_function_register_default(run_lua_code);
674   surf_parse = console_parse_application;
675   MSG_launch_application(NULL);
676   return 0;
677 }
678
679 /*
680  * Register application for gras
681  */
682 static int gras_register_application(lua_State * L)
683 {
684   gras_function_register_default(run_lua_code);
685   surf_parse = console_parse_application;
686   gras_launch_application(NULL);
687   return 0;
688 }
689
690 static const luaL_Reg simgrid_funcs[] = {
691   {"create_environment", create_environment},
692   {"launch_application", launch_application},
693   {"debug", debug},
694   {"info", info},
695   {"run", run},
696   {"clean", clean},
697   /* short names */
698   {"platform", create_environment},
699   {"application", launch_application},
700   /* methods to bypass XML parser */
701   {"msg_register_platform", msg_register_platform},
702   {"sd_register_platform", sd_register_platform},
703   {"msg_register_application", msg_register_application},
704   {"gras_register_platform", gras_register_platform},
705   {"gras_register_application", gras_register_application},
706   /* gras sub generator method */
707   {"gras_set_process_function", gras_add_process_function},
708   {"gras_generate", gras_generate},
709   {NULL, NULL}
710 };
711
712 /* ********************************************************************************* */
713 /*                       module management functions                                 */
714 /* ********************************************************************************* */
715
716 #define LUA_MAX_ARGS_COUNT 10   /* maximum amount of arguments we can get from lua on command line */
717
718 int luaopen_simgrid(lua_State *L);     // Fuck gcc: we don't need that prototype
719
720 /**
721  * This function is called automatically by the Lua interpreter when some Lua code requires
722  * the "simgrid" module.
723  * @param L the Lua state
724  */
725 int luaopen_simgrid(lua_State *L)
726 {
727   XBT_DEBUG("luaopen_simgrid *****");
728
729   /* Get the command line arguments from the lua interpreter */
730   char **argv = malloc(sizeof(char *) * LUA_MAX_ARGS_COUNT);
731   int argc = 1;
732   argv[0] = (char *) "/usr/bin/lua";    /* Lie on the argv[0] so that the stack dumping facilities find the right binary. FIXME: what if lua is not in that location? */
733
734   lua_getglobal(L, "arg");
735   /* if arg is a null value, it means we use lua only as a script to init platform
736    * else it should be a table and then take arg in consideration
737    */
738   if (lua_istable(L, -1)) {
739     int done = 0;
740     while (!done) {
741       argc++;
742       lua_pushinteger(L, argc - 2);
743       lua_gettable(L, -2);
744       if (lua_isnil(L, -1)) {
745         done = 1;
746       } else {
747         xbt_assert(lua_isstring(L, -1),
748                     "argv[%d] got from lua is no string", argc - 1);
749         xbt_assert(argc < LUA_MAX_ARGS_COUNT,
750                     "Too many arguments, please increase LUA_MAX_ARGS_COUNT in %s before recompiling SimGrid if you insist on having more than %d args on command line",
751                     __FILE__, LUA_MAX_ARGS_COUNT - 1);
752         argv[argc - 1] = (char *) luaL_checkstring(L, -1);
753         lua_pop(L, 1);
754         XBT_DEBUG("Got command line argument %s from lua", argv[argc - 1]);
755       }
756     }
757     argv[argc--] = NULL;
758
759     /* Initialize the MSG core */
760     MSG_global_init(&argc, argv);
761     XBT_DEBUG("Still %d arguments on command line", argc); // FIXME: update the lua's arg table to reflect the changes from SimGrid
762   }
763
764   /* Keep the context mechanism informed of our lua world today */
765   sglua_maestro_state = L;
766
767   /* initialize access to my tables by children Lua states */
768   lua_newtable(L);
769   lua_setfield(L, LUA_REGISTRYINDEX, "simgrid.maestro_tables");
770
771   register_c_functions(L);
772
773   return 1;
774 }
775
776 /**
777  * @brief Returns whether a Lua state is the maestro state.
778  * @param L a Lua state
779  * @return true if this is maestro
780  */
781 int sglua_is_maestro(lua_State* L) {
782   return L == sglua_maestro_state;
783 }
784
785 /**
786  * @brief Returns the maestro state.
787  * @return true the maestro Lua state
788  */
789 lua_State* sglua_get_maestro(void) {
790   return sglua_maestro_state;
791 }
792
793 /**
794  * Makes the appropriate Simgrid functions available to the Lua world.
795  * @param L a Lua world
796  */
797 void register_c_functions(lua_State *L) {
798
799   /* register the core C functions to lua */
800   luaL_register(L, "simgrid", simgrid_funcs);
801
802   /* register the task methods to lua */
803   luaL_openlib(L, TASK_MODULE_NAME, Task_methods, 0);   // create methods table, add it to the globals
804   luaL_newmetatable(L, TASK_MODULE_NAME);       // create metatable for Task, add it to the Lua registry
805   luaL_openlib(L, 0, Task_meta, 0);     // fill metatable
806   lua_pushliteral(L, "__index");
807   lua_pushvalue(L, -3);         // dup methods table
808   lua_rawset(L, -3);            // matatable.__index = methods
809   lua_pushliteral(L, "__metatable");
810   lua_pushvalue(L, -3);         // dup methods table
811   lua_rawset(L, -3);            // hide metatable:metatable.__metatable = methods
812   lua_pop(L, 1);                // drop metatable
813
814   /* register the hosts methods to lua */
815   luaL_openlib(L, HOST_MODULE_NAME, Host_methods, 0);
816   luaL_newmetatable(L, HOST_MODULE_NAME);
817   luaL_openlib(L, 0, Host_meta, 0);
818   lua_pushliteral(L, "__index");
819   lua_pushvalue(L, -3);
820   lua_rawset(L, -3);
821   lua_pushliteral(L, "__metatable");
822   lua_pushvalue(L, -3);
823   lua_rawset(L, -3);
824   lua_pop(L, 1);
825
826   /* register the links methods to lua */
827   luaL_openlib(L, AS_MODULE_NAME, AS_methods, 0);
828   luaL_newmetatable(L, AS_MODULE_NAME);
829   lua_pop(L, 1);
830
831   /* register the Tracing functions to lua */
832   luaL_openlib(L, TRACE_MODULE_NAME, Trace_methods, 0);
833   luaL_newmetatable(L, TRACE_MODULE_NAME);
834   lua_pop(L, 1);
835 }