Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
dfee7ed34968f2b8218575bb2fdb4ade151183e0
[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_Number n = lua_tonumber(src, -1);
263   if ( ((lua_Integer) n) == n) {
264     lua_pushinteger(dst, lua_tointeger(src, -1));
265   }
266   else
267     lua_pushnumber(dst, lua_tonumber(src, -1));
268 }
269
270 /**
271  * @brief Copies the boolean value on the top of src to the top of dst.
272  * @param src source state
273  * @param dst destination state
274  */
275 static void sglua_copy_boolean(lua_State* src, lua_State* dst) {
276   lua_pushboolean(dst, lua_toboolean(src, -1));
277 }
278
279 /**
280  * @brief Copies the string value on the top of src to the top of dst.
281  * @param src source state
282  * @param dst destination state
283  */
284 static void sglua_copy_string(lua_State* src, lua_State* dst) {
285
286   /* no worries about memory: lua_pushstring makes a copy */
287   lua_pushstring(dst, lua_tostring(src, -1));
288 }
289
290 /**
291  * @brief Copies the table value on top of src to the top of dst.
292  *
293  * A deep copy of the table is made. If the table has a metatable, the
294  * metatable is also copied.
295  * If the table comes from maestro and is already known by the destination
296  * state, it is not copied again.
297  *
298  * @param src source state
299  * @param dst destination state
300  */
301 static void sglua_copy_table(lua_State* src, lua_State* dst) {
302
303                                   /* src: ... table
304                                      dst: ... */
305   int indent = lua_gettop(dst) * 6  + 2;
306
307   /* get from maestro the pointer that identifies this table */
308   void* table_ptr = sglua_get_maestro_table_ptr(src, -1);
309   int known_by_maestro = (table_ptr != NULL);
310
311   if (!known_by_maestro) {
312     /* the table didn't come from maestro: nevermind, use the pointer of src */
313     table_ptr = (void*) lua_topointer(src, -1);
314     XBT_DEBUG("%sMaestro does not know this table",
315         sglua_get_spaces(indent));
316   }
317
318   if (sglua_is_maestro(src)) {
319     /* register the table in maestro itself */
320     XBT_DEBUG("%sKeeping track of this table in maestro itself",
321         sglua_get_spaces(indent));
322     sglua_add_maestro_table(src, -1, table_ptr);
323     known_by_maestro = 1;
324     xbt_assert(sglua_get_maestro_table_ptr(src, -1) == table_ptr);
325   }
326
327   /* to avoid infinite recursion, see if this table is already known by dst */
328   sglua_get_table_by_ptr(dst, table_ptr);
329                                   /* dst: ... table/nil */
330   if (!lua_isnil(dst, -1)) {
331     XBT_DEBUG("%sNothing to do: table already known (%p)",
332         sglua_get_spaces(indent), table_ptr);
333                                   /* dst: ... table */
334   }
335   else {
336     XBT_DEBUG("%sFirst visit of this table (%p)", sglua_get_spaces(indent),
337         table_ptr);
338                                   /* dst: ... nil */
339     lua_pop(dst, 1);
340                                   /* dst: ... */
341
342     /* first visit: create the new table in dst */
343     lua_newtable(dst);
344                                   /* dst: ... table */
345
346     /* mark the table as known right now to avoid infinite recursion */
347     sglua_add_maestro_table(dst, -1, table_ptr);
348     /* we may have added a table with a non-maestro pointer, but if it was the
349      * case, we will remove it later */
350     XBT_DEBUG("%sTable marked as known", sglua_get_spaces(indent));
351     xbt_assert(sglua_get_maestro_table_ptr(dst, -1) == table_ptr);
352
353     sglua_stack_dump("dst after marking the table as known (should be ... table): ", dst);
354
355     /* copy the metatable if any */
356     int has_meta_table = lua_getmetatable(src, -1);
357                                   /* src: ... table mt? */
358     if (has_meta_table) {
359       XBT_DEBUG("%sCopying the metatable", sglua_get_spaces(indent));
360                                   /* src: ... table mt */
361       sglua_copy_table(src, dst);
362                                   /* dst: ... table mt */
363       lua_pop(src, 1);
364                                   /* src: ... table */
365       lua_setmetatable(dst, -2);
366                                   /* dst: ... table */
367     }
368     else {
369                                   /* src: ... table */
370       XBT_DEBUG("%sNo metatable", sglua_get_spaces(indent));
371     }
372
373     sglua_stack_dump("src before traversing the table (should be ... table): ", src);
374     sglua_stack_dump("dst before traversing the table (should be ... table): ", dst);
375
376     /* traverse the table of src and copy each element */
377     lua_pushnil(src);
378                                   /* src: ... table nil */
379     while (lua_next(src, -2) != 0) {
380                                   /* src: ... table key value */
381
382       XBT_DEBUG("%sCopying table element %s", sglua_get_spaces(indent),
383           sglua_keyvalue_tostring(src, -2, -1));
384
385       sglua_stack_dump("src before copying table element (should be ... table key value): ", src);
386       sglua_stack_dump("dst before copying table element (should be ... table): ", dst);
387
388       /* copy the key */
389       lua_pushvalue(src, -2);
390                                   /* src: ... table key value key */
391       indent += 2;
392       XBT_DEBUG("%sCopying the key part of the table element",
393           sglua_get_spaces(indent));
394       sglua_move_value(src, dst);
395                                   /* src: ... table key value
396                                      dst: ... table key */
397       XBT_DEBUG("%sCopied the key part of the table element",
398           sglua_get_spaces(indent));
399
400       /* copy the value */
401       XBT_DEBUG("%sCopying the value part of the table element",
402           sglua_get_spaces(indent));
403       sglua_move_value(src, dst);
404                                   /* src: ... table key
405                                      dst: ... table key value */
406       XBT_DEBUG("%sCopied the value part of the table element",
407           sglua_get_spaces(indent));
408       indent -= 2;
409
410       /* set the table element */
411       lua_settable(dst, -3);
412                                   /* dst: ... table */
413
414       /* the key stays on top of src for next iteration */
415       sglua_stack_dump("src before next iteration (should be ... table key): ", src);
416       sglua_stack_dump("dst before next iteration (should be ... table): ", dst);
417
418       XBT_DEBUG("%sTable element copied", sglua_get_spaces(indent));
419     }
420     XBT_DEBUG("%sFinished traversing the table", sglua_get_spaces(indent));
421   }
422
423   if (!known_by_maestro) {
424     /* actually,it was not a maestro table: forget the pointer */
425     sglua_remove_maestro_table(dst, -1, table_ptr);
426   }
427 }
428
429 /**
430  * @brief Copies the function on the top of src to the top of dst.
431  *
432  * It can be a Lua function or a C function.
433  *
434  * @param src source state
435  * @param dst destination state
436  */
437 static void sglua_copy_function(lua_State* src, lua_State* dst) {
438
439   if (lua_iscfunction(src, -1)) {
440     /* it's a C function */
441
442     XBT_DEBUG("It's a C function");
443     sglua_stack_dump("src before copying upvalues: ", src);
444
445     /* get the function pointer */
446     int function_index = lua_gettop(src);
447     lua_CFunction f = lua_tocfunction(src, function_index);
448
449     /* copy the upvalues */
450     int i = 0;
451     const char* upvalue_name = NULL;
452     do {
453       i++;
454       upvalue_name = lua_getupvalue(src, function_index, i);
455
456       if (upvalue_name != NULL) {
457         XBT_DEBUG("Upvalue %s", upvalue_name);
458         sglua_move_value(src, dst);
459       }
460     } while (upvalue_name != NULL);
461
462     sglua_stack_dump("src before copying pointer: ", src);
463
464     /* set the function */
465     lua_pushcclosure(dst, f, i - 1);
466     XBT_DEBUG("Function pointer copied");
467   }
468   else {
469     /* it's a Lua function: dump it from src */
470
471     s_sglua_buffer_t buffer;
472     buffer.capacity = 128; /* an empty function uses 77 bytes */
473     buffer.size = 0;
474     buffer.data = xbt_new(char, buffer.capacity);
475
476     /* copy the binary chunk from src into a buffer
477      * c.heinrich: Added parameter TRUE for Lua 5.3 - this strips all debug
478      * information from the function.
479      */
480     // Was before merge: XBT_GNUC_UNUSED and was replaced with XBT_ATTRIB_UNUSED
481     XBT_ATTRIB_UNUSED int error = lua_dump(src, sglua_memory_writer, &buffer, TRUE);
482     xbt_assert(!error, "Failed to dump the function from the source state: error %d",
483         error);
484     XBT_DEBUG("Fonction dumped: %zu bytes", buffer.size);
485
486     /*
487     fwrite(buffer.data, buffer.size, buffer.size, stderr);
488     fprintf(stderr, "\n");
489     */
490
491     /* load the chunk into dst */
492     error = luaL_loadbuffer(dst, buffer.data, buffer.size, "(dumped function)");
493     xbt_assert(!error, "Failed to load the function into the destination state: %s",
494         lua_tostring(dst, -1));
495   }
496 }
497
498 /**
499  * @brief Copies the light userdata on the top of src to the top of dst.
500  * @param src source state
501  * @param dst destination state
502  */
503 static void sglua_copy_lightuserdata(lua_State* src, lua_State* dst) {
504   lua_pushlightuserdata(dst, lua_touserdata(src, -1));
505 }
506
507 /**
508  * @brief Copies the full userdata on the top of src to the top of dst.
509  *
510  * If the userdata has a metatable, the metatable is also copied.
511  *
512  * @param src source state
513  * @param dst destination state
514  */
515 static void sglua_copy_userdata(lua_State* src, lua_State* dst) {
516
517   int indent = lua_gettop(dst) * 6  + 2;
518
519   /* copy the data */
520                                   /* src: ... udata
521                                      dst: ... */
522   size_t size = lua_rawlen(src, -1);
523   void* src_block = lua_touserdata(src, -1);
524   void* dst_block = lua_newuserdata(dst, size);
525                                   /* dst: ... udata */
526   memcpy(dst_block, src_block, size);
527
528   /* copy the metatable if any */
529   int has_meta_table = lua_getmetatable(src, -1);
530                                   /* src: ... udata mt? */
531   if (has_meta_table) {
532     XBT_DEBUG("%sCopying metatable of userdata (%p)",
533         sglua_get_spaces(indent), lua_topointer(src, -1));
534                                   /* src: ... udata mt */
535     sglua_copy_table(src, dst);
536                                   /* src: ... udata mt
537                                      dst: ... udata mt */
538     lua_pop(src, 1);
539                                   /* src: ... udata */
540     lua_setmetatable(dst, -2);
541                                   /* dst: ... udata */
542
543     XBT_DEBUG("%sMetatable of userdata copied", sglua_get_spaces(indent));
544   }
545   else {
546     XBT_DEBUG("%sNo metatable for this userdata",
547         sglua_get_spaces(indent));
548                                   /* src: ... udata */
549   }
550 }
551
552 /**
553  * @brief This operation is not supported (yet?) so it just pushes nil.
554  *
555  * @param src source state
556  * @param dst destination state
557  */
558 static void sglua_copy_thread(lua_State* src, lua_State* dst) {
559
560   XBT_WARN("Copying a thread from another state is not implemented (yet?).");
561   lua_pushnil(dst);
562 }
563
564 /**
565  * @brief Copies a global value or a registry value from the maestro state.
566  *
567  * The state L must have been created by sglua_clone_maestro_state().
568  * This function is meant to be an __index metamethod.
569  * Consequently, it assumes that the stack has two elements:
570  * a table (either the environment or the registry of L) and the string key of
571  * a value that does not exist yet in this table. It copies the corresponding
572  * value from maestro and pushes it on the stack of L.
573  * If the value does not exist in maestro state either, nil is pushed.
574  *
575  * TODO: make this function thread safe. If the simulation runs in parallel,
576  * several simulated processes may trigger this __index metamethod at the same
577  * time and get globals from maestro.
578  *
579  * @param L the current state
580  * @return number of return values pushed (always 1)
581  */
582 static int l_get_from_maestro(lua_State *L) {
583
584   /* check the arguments */
585   luaL_checktype(L, 1, LUA_TTABLE);
586   const char* key = luaL_checkstring(L, 2);
587                                   /* L:      table key */
588   XBT_DEBUG("__index of '%s' begins", key);
589
590   /* get the father */
591   lua_State* maestro = sglua_get_maestro(); /* maestro: */
592
593   /* want a global or a registry value?
594      get the value from maestro         */
595   if (lua_compare(L, 1, LUA_REGISTRYINDEX, LUA_OPEQ)) {
596     /* case: registry */
597     lua_getfield(maestro, LUA_REGISTRYINDEX, key); /* maestro: ... value */
598     XBT_DEBUG("Will get the value from the registry of maestro");
599   }
600   else { /* case: global */
601     lua_getglobal(maestro, key);                   /* maestro: ... value */
602     XBT_DEBUG("Will get the value from the globals of maestro");
603   }
604
605   /* L:      table key */
606
607
608   /* push the value onto the stack of L */
609   sglua_move_value(maestro, L);
610                                   /* maestro: ...
611                                      L:      table key value */
612
613   /* prepare the return value of __index */
614   lua_pushvalue(L, -1);
615                                   /* L:      table key value value */
616   lua_insert(L, 1);
617                                   /* L:      value table key value */
618
619   /* save the copied value in the table for subsequent accesses */
620   lua_settable(L, -3);
621                                   /* L:      value table */
622   lua_settop(L, 1);
623                                   /* L:      value */
624
625   XBT_DEBUG("__index of '%s' returns %s", key, sglua_tostring(L, -1));
626
627   return 1;
628 }
629
630 /**
631  * @brief Creates a new Lua state and get its environment from the maestro
632  * state.
633  *
634  * The state created is independent from maestro and has its own copies of
635  * global and registry values.
636  * However, the global and registry values are not copied right now from
637  * the original state; they are copied only the first time they are accessed.
638  * This behavior saves time and memory, and is okay for Simgrid's needs.
639  *
640  * TODO: if the simulation runs in parallel, copy everything right now?
641  *
642  * @return the state created
643  */
644 lua_State* sglua_clone_maestro(void) {
645
646   /* create the new state */
647   lua_State *L = luaL_newstate();
648
649   /* set its environment and its registry:
650    * - create a table newenv
651    * - create a metatable mt
652    * - set mt.__index = a function that copies the global from the father state
653    * - set mt as the metatable of the registry
654    * - set mt as the metatable of newenv
655    * - set newenv as the environment of the new state
656    */
657   lua_pushthread(L);                        /* thread */
658   lua_newtable(L);                          /* thread newenv */
659   lua_newtable(L);                          /* thread newenv mt */
660   lua_pushvalue(L, LUA_REGISTRYINDEX);      /* thread newenv mt reg */
661   lua_pushcfunction(L, l_get_from_maestro); /* thread newenv mt reg f */
662   lua_setfield(L, -3, "__index");           /* thread newenv mt reg */
663   lua_pushvalue(L, -2);                     /* thread newenv mt reg mt */
664   lua_setmetatable(L, -2);                  /* thread newenv mt reg */
665   lua_pop(L, 1);                            /* thread newenv mt */
666   lua_setmetatable(L, -2);                  /* thread newenv */
667   lua_pushvalue(L, LUA_REGISTRYINDEX);      /* thread newenv reg */
668   lua_insert(L, -2);                        /* thread reg newenv */
669   lua_seti(L, -2, LUA_RIDX_GLOBALS);        /* thread reg */
670   lua_pop(L, 2);                            /* -- */
671
672   /* create the table of known tables from maestro */
673   lua_pushstring(L, "simgrid.maestro_tables");
674                                             /* "simgrid.maestro_tables" */
675   lua_newtable(L);                          /* "simgrid.maestro_tables" maestrotbs */
676   lua_rawset(L, LUA_REGISTRYINDEX);
677                                             /* -- */
678
679   /* opening the standard libs is not necessary as they are
680    * inherited like any global values */
681   /* luaL_openlibs(L); */
682
683   XBT_DEBUG("New state created");
684
685   return L;
686 }