Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
64a4f8d09a4126db979804f2a860392e908ff199
[simgrid.git] / src / bindings / lua / lua_state_cloner.c
1 /* Copyright (c) 2010-2014. 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 state management                                             */
8
9 #include "lua_state_cloner.h"
10 #include "lua_utils.h"
11 #include "xbt.h"
12 #include "xbt/log.h"
13 #include <lauxlib.h>
14 #include <lualib.h>
15
16 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(lua_state_cloner, bindings, "Lua state management");
17
18 static void sglua_add_maestro_table(lua_State* L, int index, void* maestro_table_ptr);
19 static void sglua_remove_maestro_table(lua_State* L, int index, void* maestro_table_ptr);
20 static void* sglua_get_maestro_table_ptr(lua_State* L, int index);
21 static void sglua_get_table_by_ptr(lua_State* L, void* table_ptr);
22 static int l_get_from_maestro(lua_State* L);
23
24 static void sglua_copy_nil(lua_State* src, lua_State* dst);
25 static void sglua_copy_number(lua_State* src, lua_State* dst);
26 static void sglua_copy_boolean(lua_State* src, lua_State* dst);
27 static void sglua_copy_string(lua_State* src, lua_State* dst);
28 static void sglua_copy_table(lua_State* src, lua_State* dst);
29 static void sglua_copy_function(lua_State* src, lua_State* dst);
30 static void sglua_copy_lightuserdata(lua_State* src, lua_State* dst);
31 static void sglua_copy_userdata(lua_State* src, lua_State* dst);
32 static void sglua_copy_thread(lua_State* src, lua_State* dst);
33
34 /**
35  * @brief Adds a reference to a maestro table to the list of known maestro
36  * tables of a state.
37  *
38  * TODO identify maestro's tables with my own IDs instead of pointers
39  * to Lua internals
40  *
41  * @param L a state (can be maestro itself)
42  * @param index index of the copy of the maestro table in the stack of L
43  * @param maestro_table_ptr pointer to the original table in maestro's world
44  */
45 static void sglua_add_maestro_table(lua_State* L, int index, void* maestro_table_ptr) {
46
47   /* we will set both [ptr] -> table and [table] -> ptr */
48
49                                   /* ... */
50   lua_pushvalue(L, index);
51                                   /* ... table */
52   lua_pushstring(L, "simgrid.maestro_tables");
53                                   /* ... table "simgrid.maestro_tables" */
54   lua_rawget(L, LUA_REGISTRYINDEX);
55                                   /* ... table maestrotbs */
56   lua_pushvalue(L, -2);
57                                   /* ... table maestrotbs table */
58   lua_pushlightuserdata(L, maestro_table_ptr);
59                                   /* ... table maestrotbs table tableptr */
60   lua_pushvalue(L, -1);
61                                   /* ... table maestrotbs table tableptr tableptr */
62   lua_pushvalue(L, -3);
63                                   /* ... table maestrotbs table tableptr tableptr table */
64   lua_settable(L, -5);
65                                   /* ... table maestrotbs table tableptr */
66   lua_settable(L, -3);
67                                   /* ... table maestrotbs */
68   lua_pop(L, 2);
69                                   /* ... */
70 }
71
72 /**
73  * @brief Removes a reference to a maestro table to the list of known maestro
74  * tables of a state.
75  *
76  * @param L a state (can be maestro itself)
77  * @param index index of the copy of the maestro table in the stack of L
78  * @param maestro_table_ptr pointer to the original table in maestro's world
79  */
80 static void sglua_remove_maestro_table(lua_State* L, int index, void* maestro_table_ptr) {
81
82   /* we will unset both [ptr] -> table and [table] -> ptr */
83
84                                   /* ... */
85   lua_pushvalue(L, index);
86                                   /* ... table */
87   lua_pushstring(L, "simgrid.maestro_tables");
88                                   /* ... table "simgrid.maestro_tables" */
89   lua_rawget(L, LUA_REGISTRYINDEX);
90                                   /* ... table maestrotbs */
91   lua_pushvalue(L, -2);
92                                   /* ... table maestrotbs table */
93   lua_pushnil(L);
94                                   /* ... table maestrotbs table nil */
95   lua_pushlightuserdata(L, maestro_table_ptr);
96                                   /* ... table maestrotbs table nil tableptr */
97   lua_pushnil(L);
98                                   /* ... table maestrotbs table nil tableptr nil*/
99   lua_settable(L, -5);
100                                   /* ... table maestrotbs table nil */
101   lua_settable(L, -3);
102                                   /* ... table maestrotbs */
103   lua_pop(L, 2);
104                                   /* ... */
105 }
106
107 /**
108  * @brief For a table in the stack of L, returns a pointer that identifies the
109  * same table in in maestro's world.
110  * @param L a Lua state
111  * @param index index of a table in the stack of L
112  * @return a pointer to maestro's copy of this table, or NULL if this table
113  * did not come from maestro
114  */
115 static void* sglua_get_maestro_table_ptr(lua_State* L, int index) {
116
117   void* maestro_table_ptr = NULL;
118                                   /* ... */
119   lua_pushvalue(L, index);
120                                   /* ... table */
121   lua_pushstring(L, "simgrid.maestro_tables");
122                                   /* ... table "simgrid.maestro_tables" */
123   lua_rawget(L, LUA_REGISTRYINDEX);
124                                   /* ... table maestrotbs */
125   lua_pushvalue(L, -2);
126                                   /* ... table maestrotbs table */
127   lua_gettable(L, -2);
128                                   /* ... table maestrotbs tableptr/nil */
129   if (!lua_isnil(L, -1)) {
130                                   /* ... table maestrotbs tableptr */
131     maestro_table_ptr = (void*) lua_topointer(L, -1);
132   }
133
134   lua_pop(L, 3);
135                                   /* ... */
136   return maestro_table_ptr;
137 }
138
139 /**
140  * @brief Pushes a table knowing a pointer to maestro's copy of this table.
141  *
142  * Pushes nil if L does not know this table in maestro.
143  *
144  * @param L a Lua state
145  * @param maestro_table_ptr pointer that identifies a table in maestro's world
146  */
147 static void sglua_get_table_by_ptr(lua_State* L, void* maestro_table_ptr) {
148
149                                   /* ... */
150   lua_pushstring(L, "simgrid.maestro_tables");
151                                   /* ... "simgrid.maestro_tables" */
152   lua_rawget(L, LUA_REGISTRYINDEX);
153                                   /* ... maestrotbs */
154   lua_pushlightuserdata(L, maestro_table_ptr);
155                                   /* ... maestrotbs tableptr */
156   lua_gettable(L, -2);
157                                   /* ... maestrotbs table/nil */
158   lua_remove(L, -2);
159                                   /* ... table/nil */
160 }
161
162 /**
163  * @brief Pops a value from the stack of a source state and pushes it on the
164  * stack of another state.
165  * If the value is a table, its content is copied recursively.
166  *
167  * This function is similar to lua_xmove() but it allows to move a value
168  * between two different global states.
169  *
170  * @param src the source state (not necessarily maestro)
171  * @param dst the destination state
172  */
173 void sglua_move_value(lua_State* src, lua_State* dst) {
174
175   sglua_copy_value(src, dst);
176   lua_pop(src, 1);
177 }
178
179 /**
180  * @brief Pushes onto the stack a copy of the value on top another stack.
181  * If the value is a table, its content is copied recursively.
182  *
183  * This function allows to move a value between two different global states.
184  *
185  * @param src the source state (not necessarily maestro)
186  * @param dst the destination state
187  */
188 void sglua_copy_value(lua_State* src, lua_State* dst) {
189
190   luaL_checkany(src, -1);                  /* check the value to copy */
191
192   int indent = (lua_gettop(dst) - 1) * 6;
193   XBT_DEBUG("%sCopying data %s", sglua_get_spaces(indent), sglua_tostring(src, -1));
194
195   sglua_stack_dump("src before copying a value (should be ... value): ", src);
196   sglua_stack_dump("dst before copying a value (should be ...): ", dst);
197
198   switch (lua_type(src, -1)) {
199
200     case LUA_TNIL:
201       sglua_copy_nil(src, dst);
202       break;
203
204     case LUA_TNUMBER:
205       sglua_copy_number(src, dst);
206       break;
207
208     case LUA_TBOOLEAN:
209       sglua_copy_boolean(src, dst);
210       break;
211
212     case LUA_TSTRING:
213       sglua_copy_string(src, dst);
214       break;
215
216     case LUA_TFUNCTION:
217       sglua_copy_function(src, dst);
218       break;
219
220     case LUA_TTABLE:
221       sglua_copy_table(src, dst);
222       break;
223
224     case LUA_TLIGHTUSERDATA:
225       sglua_copy_lightuserdata(src, dst);
226       break;
227
228     case LUA_TUSERDATA:
229       sglua_copy_userdata(src, dst);
230       break;
231
232     case LUA_TTHREAD:
233       sglua_copy_thread(src, dst);
234       break;
235
236     case LUA_TNONE:
237         XBT_ERROR("This index is acceptable but non-valid");
238       break;
239   }
240
241   XBT_DEBUG("%sData copied", sglua_get_spaces(indent));
242
243   sglua_stack_dump("src after copying a value (should be ... value): ", src);
244   sglua_stack_dump("dst after copying a value (should be ... value): ", dst);
245 }
246
247 /**
248  * @brief Copies the nil value on the top of src to the top of dst.
249  * @param src source state
250  * @param dst destination state
251  */
252 static void sglua_copy_nil(lua_State* src, lua_State* dst) {
253   lua_pushnil(dst);
254 }
255
256 /**
257  * @brief Copies the number value on the top of src to the top of dst.
258  * @param src source state
259  * @param dst destination state
260  */
261 static void sglua_copy_number(lua_State* src, lua_State* dst) {
262   lua_pushnumber(dst, lua_tonumber(src, -1));
263 }
264
265 /**
266  * @brief Copies the boolean value on the top of src to the top of dst.
267  * @param src source state
268  * @param dst destination state
269  */
270 static void sglua_copy_boolean(lua_State* src, lua_State* dst) {
271   lua_pushboolean(dst, lua_toboolean(src, -1));
272 }
273
274 /**
275  * @brief Copies the string value on the top of src to the top of dst.
276  * @param src source state
277  * @param dst destination state
278  */
279 static void sglua_copy_string(lua_State* src, lua_State* dst) {
280
281   /* no worries about memory: lua_pushstring makes a copy */
282   lua_pushstring(dst, lua_tostring(src, -1));
283 }
284
285 /**
286  * @brief Copies the table value on top of src to the top of dst.
287  *
288  * A deep copy of the table is made. If the table has a metatable, the
289  * metatable is also copied.
290  * If the table comes from maestro and is already known by the destination
291  * state, it is not copied again.
292  *
293  * @param src source state
294  * @param dst destination state
295  */
296 static void sglua_copy_table(lua_State* src, lua_State* dst) {
297
298                                   /* src: ... table
299                                      dst: ... */
300   int indent = lua_gettop(dst) * 6  + 2;
301
302   /* get from maestro the pointer that identifies this table */
303   void* table_ptr = sglua_get_maestro_table_ptr(src, -1);
304   int known_by_maestro = (table_ptr != NULL);
305
306   if (!known_by_maestro) {
307     /* the table didn't come from maestro: nevermind, use the pointer of src */
308     table_ptr = (void*) lua_topointer(src, -1);
309     XBT_DEBUG("%sMaestro does not know this table",
310         sglua_get_spaces(indent));
311   }
312
313   if (sglua_is_maestro(src)) {
314     /* register the table in maestro itself */
315     XBT_DEBUG("%sKeeping track of this table in maestro itself",
316         sglua_get_spaces(indent));
317     sglua_add_maestro_table(src, -1, table_ptr);
318     known_by_maestro = 1;
319     xbt_assert(sglua_get_maestro_table_ptr(src, -1) == table_ptr);
320   }
321
322   /* to avoid infinite recursion, see if this table is already known by dst */
323   sglua_get_table_by_ptr(dst, table_ptr);
324                                   /* dst: ... table/nil */
325   if (!lua_isnil(dst, -1)) {
326     XBT_DEBUG("%sNothing to do: table already known (%p)",
327         sglua_get_spaces(indent), table_ptr);
328                                   /* dst: ... table */
329   }
330   else {
331     XBT_DEBUG("%sFirst visit of this table (%p)", sglua_get_spaces(indent),
332         table_ptr);
333                                   /* dst: ... nil */
334     lua_pop(dst, 1);
335                                   /* dst: ... */
336
337     /* first visit: create the new table in dst */
338     lua_newtable(dst);
339                                   /* dst: ... table */
340
341     /* mark the table as known right now to avoid infinite recursion */
342     sglua_add_maestro_table(dst, -1, table_ptr);
343     /* we may have added a table with a non-maestro pointer, but if it was the
344      * case, we will remove it later */
345     XBT_DEBUG("%sTable marked as known", sglua_get_spaces(indent));
346     xbt_assert(sglua_get_maestro_table_ptr(dst, -1) == table_ptr);
347
348     sglua_stack_dump("dst after marking the table as known (should be ... table): ", dst);
349
350     /* copy the metatable if any */
351     int has_meta_table = lua_getmetatable(src, -1);
352                                   /* src: ... table mt? */
353     if (has_meta_table) {
354       XBT_DEBUG("%sCopying the metatable", sglua_get_spaces(indent));
355                                   /* src: ... table mt */
356       sglua_copy_table(src, dst);
357                                   /* dst: ... table mt */
358       lua_pop(src, 1);
359                                   /* src: ... table */
360       lua_setmetatable(dst, -2);
361                                   /* dst: ... table */
362     }
363     else {
364                                   /* src: ... table */
365       XBT_DEBUG("%sNo metatable", sglua_get_spaces(indent));
366     }
367
368     sglua_stack_dump("src before traversing the table (should be ... table): ", src);
369     sglua_stack_dump("dst before traversing the table (should be ... table): ", dst);
370
371     /* traverse the table of src and copy each element */
372     lua_pushnil(src);
373                                   /* src: ... table nil */
374     while (lua_next(src, -2) != 0) {
375                                   /* src: ... table key value */
376
377       XBT_DEBUG("%sCopying table element %s", sglua_get_spaces(indent),
378           sglua_keyvalue_tostring(src, -2, -1));
379
380       sglua_stack_dump("src before copying table element (should be ... table key value): ", src);
381       sglua_stack_dump("dst before copying table element (should be ... table): ", dst);
382
383       /* copy the key */
384       lua_pushvalue(src, -2);
385                                   /* src: ... table key value key */
386       indent += 2;
387       XBT_DEBUG("%sCopying the key part of the table element",
388           sglua_get_spaces(indent));
389       sglua_move_value(src, dst);
390                                   /* src: ... table key value
391                                      dst: ... table key */
392       XBT_DEBUG("%sCopied the key part of the table element",
393           sglua_get_spaces(indent));
394
395       /* copy the value */
396       XBT_DEBUG("%sCopying the value part of the table element",
397           sglua_get_spaces(indent));
398       sglua_move_value(src, dst);
399                                   /* src: ... table key
400                                      dst: ... table key value */
401       XBT_DEBUG("%sCopied the value part of the table element",
402           sglua_get_spaces(indent));
403       indent -= 2;
404
405       /* set the table element */
406       lua_settable(dst, -3);
407                                   /* dst: ... table */
408
409       /* the key stays on top of src for next iteration */
410       sglua_stack_dump("src before next iteration (should be ... table key): ", src);
411       sglua_stack_dump("dst before next iteration (should be ... table): ", dst);
412
413       XBT_DEBUG("%sTable element copied", sglua_get_spaces(indent));
414     }
415     XBT_DEBUG("%sFinished traversing the table", sglua_get_spaces(indent));
416   }
417
418   if (!known_by_maestro) {
419     /* actually,it was not a maestro table: forget the pointer */
420     sglua_remove_maestro_table(dst, -1, table_ptr);
421   }
422 }
423
424 /**
425  * @brief Copies the function on the top of src to the top of dst.
426  *
427  * It can be a Lua function or a C function.
428  *
429  * @param src source state
430  * @param dst destination state
431  */
432 static void sglua_copy_function(lua_State* src, lua_State* dst) {
433
434   if (lua_iscfunction(src, -1)) {
435     /* it's a C function */
436
437     XBT_DEBUG("It's a C function");
438     sglua_stack_dump("src before copying upvalues: ", src);
439
440     /* get the function pointer */
441     int function_index = lua_gettop(src);
442     lua_CFunction f = lua_tocfunction(src, function_index);
443
444     /* copy the upvalues */
445     int i = 0;
446     const char* upvalue_name = NULL;
447     do {
448       i++;
449       upvalue_name = lua_getupvalue(src, function_index, i);
450
451       if (upvalue_name != NULL) {
452         XBT_DEBUG("Upvalue %s", upvalue_name);
453         sglua_move_value(src, dst);
454       }
455     } while (upvalue_name != NULL);
456
457     sglua_stack_dump("src before copying pointer: ", src);
458
459     /* set the function */
460     lua_pushcclosure(dst, f, i - 1);
461     XBT_DEBUG("Function pointer copied");
462   }
463   else {
464     /* it's a Lua function: dump it from src */
465
466     s_sglua_buffer_t buffer;
467     buffer.capacity = 128; /* an empty function uses 77 bytes */
468     buffer.size = 0;
469     buffer.data = xbt_new(char, buffer.capacity);
470
471     /* copy the binary chunk from src into a buffer
472      * c.heinrich: Added parameter TRUE for Lua 5.3 - this strips all debug
473      * information from the function.
474      */
475     // Was before merge: XBT_GNUC_UNUSED and was replaced with XBT_ATTRIB_UNUSED
476     XBT_ATTRIB_UNUSED int error = lua_dump(src, sglua_memory_writer, &buffer, TRUE);
477     xbt_assert(!error, "Failed to dump the function from the source state: error %d",
478         error);
479     XBT_DEBUG("Fonction dumped: %zu bytes", buffer.size);
480
481     /*
482     fwrite(buffer.data, buffer.size, buffer.size, stderr);
483     fprintf(stderr, "\n");
484     */
485
486     /* load the chunk into dst */
487     error = luaL_loadbuffer(dst, buffer.data, buffer.size, "(dumped function)");
488     xbt_assert(!error, "Failed to load the function into the destination state: %s",
489         lua_tostring(dst, -1));
490   }
491 }
492
493 /**
494  * @brief Copies the light userdata on the top of src to the top of dst.
495  * @param src source state
496  * @param dst destination state
497  */
498 static void sglua_copy_lightuserdata(lua_State* src, lua_State* dst) {
499   lua_pushlightuserdata(dst, lua_touserdata(src, -1));
500 }
501
502 /**
503  * @brief Copies the full userdata on the top of src to the top of dst.
504  *
505  * If the userdata has a metatable, the metatable is also copied.
506  *
507  * @param src source state
508  * @param dst destination state
509  */
510 static void sglua_copy_userdata(lua_State* src, lua_State* dst) {
511
512   int indent = lua_gettop(dst) * 6  + 2;
513
514   /* copy the data */
515                                   /* src: ... udata
516                                      dst: ... */
517   size_t size = lua_rawlen(src, -1);
518   void* src_block = lua_touserdata(src, -1);
519   void* dst_block = lua_newuserdata(dst, size);
520                                   /* dst: ... udata */
521   memcpy(dst_block, src_block, size);
522
523   /* copy the metatable if any */
524   int has_meta_table = lua_getmetatable(src, -1);
525                                   /* src: ... udata mt? */
526   if (has_meta_table) {
527     XBT_DEBUG("%sCopying metatable of userdata (%p)",
528         sglua_get_spaces(indent), lua_topointer(src, -1));
529                                   /* src: ... udata mt */
530     sglua_copy_table(src, dst);
531                                   /* src: ... udata mt
532                                      dst: ... udata mt */
533     lua_pop(src, 1);
534                                   /* src: ... udata */
535     lua_setmetatable(dst, -2);
536                                   /* dst: ... udata */
537
538     XBT_DEBUG("%sMetatable of userdata copied", sglua_get_spaces(indent));
539   }
540   else {
541     XBT_DEBUG("%sNo metatable for this userdata",
542         sglua_get_spaces(indent));
543                                   /* src: ... udata */
544   }
545 }
546
547 /**
548  * @brief This operation is not supported (yet?) so it just pushes nil.
549  *
550  * @param src source state
551  * @param dst destination state
552  */
553 static void sglua_copy_thread(lua_State* src, lua_State* dst) {
554
555   XBT_WARN("Copying a thread from another state is not implemented (yet?).");
556   lua_pushnil(dst);
557 }
558
559 /**
560  * @brief Copies a global value or a registry value from the maestro state.
561  *
562  * The state L must have been created by sglua_clone_maestro_state().
563  * This function is meant to be an __index metamethod.
564  * Consequently, it assumes that the stack has two elements:
565  * a table (either the environment or the registry of L) and the string key of
566  * a value that does not exist yet in this table. It copies the corresponding
567  * value from maestro and pushes it on the stack of L.
568  * If the value does not exist in maestro state either, nil is pushed.
569  *
570  * TODO: make this function thread safe. If the simulation runs in parallel,
571  * several simulated processes may trigger this __index metamethod at the same
572  * time and get globals from maestro.
573  *
574  * @param L the current state
575  * @return number of return values pushed (always 1)
576  */
577 static int l_get_from_maestro(lua_State *L) {
578
579   /* check the arguments */
580   luaL_checktype(L, 1, LUA_TTABLE);
581   const char* key = luaL_checkstring(L, 2);
582                                   /* L:      table key */
583   XBT_DEBUG("__index of '%s' begins", key);
584
585   /* want a global or a registry value? */
586   int pseudo_index;
587   if (lua_compare(L, 1, LUA_REGISTRYINDEX, LUA_OPEQ)) {
588     /* registry */
589     pseudo_index = LUA_REGISTRYINDEX;
590     XBT_DEBUG("Will get the value from the registry of maestro");
591   }
592   else {
593     /* global */
594     pseudo_index = lua_getfield(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS);
595     XBT_DEBUG("Will get the value from the globals of maestro");
596   }
597
598   /* get the father */
599   lua_State* maestro = sglua_get_maestro();
600
601                                   /* L:      table key */
602
603   /* get the value from maestro */
604   lua_getfield(maestro, pseudo_index, key);
605                                   /* maestro: ... value */
606
607   /* push the value onto the stack of L */
608   sglua_move_value(maestro, L);
609                                   /* maestro: ...
610                                      L:      table key value */
611
612   /* prepare the return value of __index */
613   lua_pushvalue(L, -1);
614                                   /* L:      table key value value */
615   lua_insert(L, 1);
616                                   /* L:      value table key value */
617
618   /* save the copied value in the table for subsequent accesses */
619   lua_settable(L, -3);
620                                   /* L:      value table */
621   lua_settop(L, 1);
622                                   /* L:      value */
623
624   XBT_DEBUG("__index of '%s' returns %s", key, sglua_tostring(L, -1));
625
626   return 1;
627 }
628
629 /**
630  * @brief Creates a new Lua state and get its environment from the maestro
631  * state.
632  *
633  * The state created is independent from maestro and has its own copies of
634  * global and registry values.
635  * However, the global and registry values are not copied right now from
636  * the original state; they are copied only the first time they are accessed.
637  * This behavior saves time and memory, and is okay for Simgrid's needs.
638  *
639  * TODO: if the simulation runs in parallel, copy everything right now?
640  *
641  * @return the state created
642  */
643 lua_State* sglua_clone_maestro(void) {
644
645   /* create the new state */
646   lua_State *L = luaL_newstate();
647
648   /* set its environment and its registry:
649    * - create a table newenv
650    * - create a metatable mt
651    * - set mt.__index = a function that copies the global from the father state
652    * - set mt as the metatable of the registry
653    * - set mt as the metatable of newenv
654    * - set newenv as the environment of the new state
655    */
656   lua_pushthread(L);                        /* thread */
657   lua_newtable(L);                          /* thread newenv */
658   lua_newtable(L);                          /* thread newenv mt */
659   lua_pushvalue(L, LUA_REGISTRYINDEX);      /* thread newenv mt reg */
660   lua_pushcfunction(L, l_get_from_maestro); /* thread newenv mt reg f */
661   lua_setfield(L, -3, "__index");           /* thread newenv mt reg */
662   lua_pushvalue(L, -2);                     /* thread newenv mt reg mt */
663   lua_setmetatable(L, -2);                  /* thread newenv mt reg */
664   lua_pop(L, 1);                            /* thread newenv mt */
665   lua_setmetatable(L, -2);                  /* thread newenv */
666   // TODO c.heinrich This needs to be re-implemented
667   /*lua_setfenv(L, -2);                       [> thread <]*/
668   lua_pop(L, 1);                            /* -- */
669
670   /* create the table of known tables from maestro */
671   lua_pushstring(L, "simgrid.maestro_tables");
672                                             /* "simgrid.maestro_tables" */
673   lua_newtable(L);                          /* "simgrid.maestro_tables" maestrotbs */
674   lua_rawset(L, LUA_REGISTRYINDEX);
675                                             /* -- */
676
677   /* opening the standard libs is not necessary as they are
678    * inherited like any global values */
679   /* luaL_openlibs(L); */
680
681   XBT_DEBUG("New state created");
682
683   return L;
684 }