From: mquinson Date: Mon, 22 Mar 2010 10:09:51 +0000 (+0000) Subject: Second try at lua. Still does not work: I get a 'attempt to yield across metamethod... X-Git-Tag: SVN~445 X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/commitdiff_plain/521aa2e579bdf76e25487fb6b9019e78ec75ad32?hp=cf422acd1a7a2fc27b76d9d82db6f778e97a3092 Second try at lua. Still does not work: I get a 'attempt to yield across metamethod/C-call boundary' error... git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@7294 48e7efb5-ca39-0410-a469-dd3cf9ba447f --- diff --git a/src/bindings/lua/Msglua.c b/src/bindings/lua/Msglua.c deleted file mode 100644 index e152066f22..0000000000 --- a/src/bindings/lua/Msglua.c +++ /dev/null @@ -1,518 +0,0 @@ -#include -#include -#include - -// Msg Includes -#include -#include "msg/msg.h" -#include "msg/datatypes.h" -#include "xbt/sysdep.h" -#include "xbt/log.h" -#include "xbt/asserts.h" - - -XBT_LOG_NEW_DEFAULT_SUBCATEGORY(lua,bindings,"Lua Bindings"); - - -/* -============================================= - - Example Lua Bindings for Msg - -============================================= - */ - - - -#define TASK "Msg.Task" -#define HOST "Msg.Host" -#define PROCESS "Msg.Process" - -typedef m_task_t Task; -typedef m_host_t Host; -typedef m_process_t Process; - - -static void stackDump (lua_State *L) { - char buff[2048]; - char *p=buff; - int i; - int top = lua_gettop(L); - void *ptr; - fflush(stdout); - p+=sprintf(p,"STACK(top=%d): ",top); - for (i = 1; i <= top; i++) { /* repeat for each level */ - int t = lua_type(L, i); - switch (t) { - - case LUA_TSTRING: /* strings */ - p+=sprintf(p,"`%s'", lua_tostring(L, i)); - break; - - case LUA_TBOOLEAN: /* booleans */ - p+=sprintf(p,lua_toboolean(L, i) ? "true" : "false"); - break; - - case LUA_TNUMBER: /* numbers */ - p+=sprintf(p,"%g", lua_tonumber(L, i)); - break; - - default: /* other values */ - if ((ptr = luaL_checkudata(L,i,TASK))) { - p+=sprintf(p,"task"); - } else { - p+=printf(p,"%s", lua_typename(L, t)); - } - break; - - } - p+=sprintf(p," "); /* put a separator */ - } - INFO1("%s",buff); -} - -//**********************************************************TASK SECTION*************************************************** - - -static Task toTask(lua_State *L,int index) -{ - Task *pi = (Task*) lua_touserdata(L,index); - if(pi == NULL) luaL_typerror(L,index,TASK); - return *pi; -} -/** - *checkTask ensures that a userdata on the stack is the correct type, and returns the Task pointer inside the userdata - */ - -static Task checkTask (lua_State *L,int index) -{ - Task *pi,tk; - luaL_checktype(L,index,LUA_TUSERDATA); - pi = (Task*)luaL_checkudata(L,index,TASK); - if(pi == NULL ) luaL_typerror(L,index,TASK); - tk = *pi; - if(!tk) - luaL_error(L,"null Task"); - return tk; -} - -/** - *pushTask leaves a new userdata on top of the stack, sets its metatable, and sets the Task pointer inside the userdata. - */ - -static Task *pushTask (lua_State *L,Task tk) -{ - Task *pi = (Task*)lua_newuserdata(L,sizeof(Task)); - *pi=tk; - luaL_getmetatable(L,TASK); - lua_setmetatable(L,-2); - return pi; - -} - -/** - *Task.new is a constructor that returns a userdata containing a pointer the Task to be manipulated - */ - - -static int Task_new(lua_State* L) -{ - const char *name=luaL_checkstring(L,1); - int comp_size = luaL_checkint(L,2); - int msg_size = luaL_checkint(L,3); - // We Will Set The Data as a Null for The Moment - pushTask(L,MSG_task_create(name,comp_size,msg_size,NULL)); - INFO0("Created task");fflush(stdout);fflush(stderr); - return 1; - -} - -/** - * Function to return the Task Name - */ - - -static int Task_name(lua_State *L) -{ - Task tk = checkTask(L,1); - lua_pushstring(L,MSG_task_get_name(tk)); - return 1; -} - - -/** - * Function to return the Computing Size of a Task - */ - -static int Task_comp(lua_State *L) -{ - Task tk = checkTask(L,1); - lua_pushnumber(L,MSG_task_get_compute_duration (tk)); - return 1; -} - - -/** - *Function to Excute a Task - */ - -static int Task_execute(lua_State *L) -{ - Task tk = checkTask(L,1); - int res = MSG_task_execute(tk); - lua_pushnumber(L,res); - return 1; -} - -/** - *Function ro Desroy a Task - */ -static int Task_destroy(lua_State *L) -{ - Task tk = checkTask(L,1); - int res = MSG_task_destroy(tk); - lua_pushnumber(L,res); - return 1; -} - - - - - - -//*************************************************************** HOST SECTION *************************************************************************** - - - -static Host toHost(lua_State *L,int index) -{ - Host *pi = (Host*) lua_touserdata(L,index); - if(pi == NULL) luaL_typerror(L,index,HOST); - return *pi; -} - - - -static Host checkHost (lua_State *L,int index) -{ - Host *pi,ht; - luaL_checktype(L,index,LUA_TUSERDATA); - pi = (Host*)luaL_checkudata(L,index,HOST); - if(pi == NULL ) luaL_typerror(L,index,HOST); - ht = *pi; - if(!ht) - luaL_error(L,"null Host"); - return ht; -} - - - -static Host *pushHost (lua_State *L,Host ht) -{ - Host *pi = (Host*)lua_newuserdata(L,sizeof(Host)); - *pi=ht; - luaL_getmetatable(L,HOST); - lua_setmetatable(L,-2); - return pi; - -} - - -static int Host_new(lua_State* L) -{ - const char *host_name=luaL_checkstring(L,1); - pushHost(L,MSG_get_host_by_name(host_name)); - return 1; -} - - - -static int Host_name(lua_State* L) -{ - Host ht = checkHost(L,1); - lua_pushstring(L,MSG_host_get_name(ht)); - return 1; -} - - -//******************************************************* PROCESS SECTION *************************************************************************** -static Process toProcess(lua_State *L,int index) -{ - Process *pi = (Process*) lua_touserdata(L,index); - if(pi == NULL) luaL_typerror(L,index,PROCESS); - return *pi; -} - - - -static Process checkProcess (lua_State *L,int index) -{ - Process *pi,ps; - luaL_checktype(L,index,LUA_TUSERDATA); - pi = (Process*)luaL_checkudata(L,index,PROCESS); - if(pi == NULL ) luaL_typerror(L,index,PROCESS); - ps = *pi; - if(!ps) - luaL_error(L,"null Process"); - return ps; -} - - - -static Process *pushProcess (lua_State *L,Process ps) -{ - Process *pi = (Process*)lua_newuserdata(L,sizeof(Process)); - *pi=ps; - luaL_getmetatable(L,PROCESS); - lua_setmetatable(L,-2); - return pi; - -} - -/* -m_process_t MSG_process_create ( const char * name, - xbt_main_func_t code, - void * data, - m_host_t host - ) - */ - - - -static int Process_new(lua_State* L) -{ - const char *name=luaL_checkstring(L,1); - //int code = luaL_checkint(L,2); - //xbt_main_func_t << code - // We Will Set The Data as a Null for The Moment - Host ht = checkHost(L,4); - pushProcess(L,MSG_process_create(name,NULL,NULL,ht)); - return 1; - -} - - -static int Process_kill(lua_State *L) -{ - Process ps = checkProcess (L,1); - MSG_process_kill(ps); - return 0; -} - - - -//**********************************************************MSG Operating System Functions****************************************************************** -/** - * Function to Send a Task - */ -static int Task_send(lua_State *L) { - Task tk = checkTask(L,1); - const char *mailbox = luaL_checkstring(L,2); - stackDump(L);fflush(stdout);fflush(stderr); - int res = MSG_task_send(tk,mailbox); - res++;//FIXME: check it instead of avoiding the warning - stackDump(L); - return 0; -} -/** - * Function Recieve a Task - */ -static int Task_recv(lua_State *L) { - Task tk = NULL; - //stackDump(L); - const char *mailbox = luaL_checkstring(L,1); - int res = MSG_task_receive(&tk,mailbox); - res++;//FIXME: check it instead of avoiding the warning - INFO1("Task Name : >>>%s",MSG_task_get_name(tk)); - pushTask(L,tk); - // stackDump(L); - return 1; -} - -//******************************************************* PLATFORM & APPLICATION SECTION **************************************************************** - - -//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> WE WONT NEED IT (!!??) -/** - * Launch Application Function - */ - -static int launch_application(lua_State *L) -{ - - const char * file = luaL_checkstring(L,1); - MSG_launch_application(file); - return 0; - -} - -/** - * Create Environment Function - */ - -static int create_environment(lua_State *L) -{ - - const char *file = luaL_checkstring(L,1); - MSG_create_environment(file); - return 0; - -} - - -//****************************************************************** REGISTERING ************************************************************ -/** - *Registering Into Lua - */ - - -static const luaL_reg Task_methods[] = { - {"new", Task_new}, - {"name", Task_name}, - {"comp", Task_comp}, - {"execute", Task_execute}, - {"destroy", Task_destroy}, - {"send", Task_send}, - {"recv", Task_recv}, - {0,0} -}; - - -static const luaL_reg Host_methods[] = { - {"new", Host_new}, - {"name", Host_name}, - {0,0} -}; - - -static const luaL_reg Process_methods[] = { - {"new", Process_new}, - {"kill", Process_kill}, - {0,0} -}; - - - - -/** - * Task_meta - */ -static int Task_gc(lua_State *L) -{ - Task tk=toTask(L,1); - if (tk) MSG_task_destroy(tk); - //printf("GoodBye Task(%p)\n",lua_touserdata(L,1)); - return 0; -} - -static int Task_tostring(lua_State *L) -{ - lua_pushfstring(L,"Task :%p",lua_touserdata(L,1)); - return 1; -} - - -static const luaL_reg Task_meta[] = { - {"__gc", Task_gc}, - {"__tostring", Task_tostring}, - {0,0} -}; - - - - -/** - * Host_meta - */ -static int Host_gc(lua_State *L) -{ - Host ht=toHost(L,1); - if (ht) ht=NULL; - printf("GoodBye Host(%p)\n",lua_touserdata(L,1)); - return 0; -} - -static int Host_tostring(lua_State *L) -{ - lua_pushfstring(L,"Host :%p",lua_touserdata(L,1)); - return 1; -} - - -static const luaL_reg Host_meta[] = { - {"__gc", Host_gc}, - {"__tostring", Host_tostring}, - {0,0} -}; - - -/** - * Process_meta - */ -static int Process_gc(lua_State *L) -{ - Process ps=toProcess(L,1); - if (ps) MSG_process_kill(ps) ; - printf("GoodBye Process(%p)\n",lua_touserdata(L,1)); - return 0; -} - -static int Process_tostring(lua_State *L) -{ - lua_pushfstring(L,"Process :%p",lua_touserdata(L,1)); - return 1; -} - - -static const luaL_reg Process_meta[] = { - {"__gc", Process_gc}, - {"__tostring", Process_tostring}, - {0,0} -}; - - -/** - *The metatable for the userdata is put in the registry, and the __index field points to the table of methods so that the object:method() syntax will work. The methods table is stored in the table of globals so that scripts can add methods written in Lua. - */ - -/** - * Register Task, Host, and Process - */ - -int MSG_register(lua_State *L);// FIXME: better location -int MSG_register(lua_State *L) { - luaL_openlib(L,TASK,Task_methods,0); //create methods table,add it to the globals - luaL_newmetatable(L,TASK); //create metatable for Task,add it to the Lua registry - luaL_openlib(L,0,Task_meta,0);// fill metatable - lua_pushliteral(L,"__index"); - lua_pushvalue(L,-3); //dup methods table - lua_rawset(L,-3); //matatable.__index = methods - lua_pushliteral(L,"__metatable"); - lua_pushvalue(L,-3); //dup methods table - lua_rawset(L,-3); //hide metatable:metatable.__metatable = methods - lua_pop(L,1); //drop metatable - /* HOST */ - luaL_openlib(L,HOST,Host_methods,0); - luaL_newmetatable(L,HOST); - luaL_openlib(L,0,Host_meta,0); - lua_pushliteral(L,"__index"); - lua_pushvalue(L,-3); - lua_rawset(L,-3); - lua_pushliteral(L,"__metatable"); - lua_pushvalue(L,-3); - lua_rawset(L,-3); - lua_pop(L,1); - /* Process */ - luaL_openlib(L,PROCESS,Process_methods,0); - luaL_newmetatable(L,PROCESS); - luaL_openlib(L,0,Host_meta,0); - lua_pushliteral(L,"__index"); - lua_pushvalue(L,-3); - lua_rawset(L,-3); - lua_pushliteral(L,"__metatable"); - lua_pushvalue(L,-3); - lua_rawset(L,-3); - lua_pop(L,1); - return 1; -} - diff --git a/src/bindings/lua/deploy.xml b/src/bindings/lua/deploy.xml deleted file mode 100644 index 975fed4fca..0000000000 --- a/src/bindings/lua/deploy.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/src/bindings/lua/doit b/src/bindings/lua/doit deleted file mode 100755 index b95b61081f..0000000000 --- a/src/bindings/lua/doit +++ /dev/null @@ -1,4 +0,0 @@ -set -ex -make -C ../../ -gcc -g3 -o runner tasktest.c -I ../../../include/ -I /usr/include/lua5.1/ -I . ../../.libs/libsimgrid.a -ldl -llua5.1 -valgrind -q ./runner ../../../examples/msg/small_platform.xml deploy.xml tasklua.lua --log=simix.thres:debug diff --git a/src/bindings/lua/master_slave.lua b/src/bindings/lua/master_slave.lua new file mode 100644 index 0000000000..25e2c84240 --- /dev/null +++ b/src/bindings/lua/master_slave.lua @@ -0,0 +1,81 @@ + +--Master Function +function Master(...) + +simgrid.info("Hello from lua, I'm the master") +for i,v in ipairs(arg) do + simgrid.info("Got "..v) +end + +nb_task = arg[1]; +comp_size = arg[2]; +comm_size = arg[3]; +slave_count = arg[4] + + +simgrid.info("Argc="..(#arg).." (should be 4)") + +-- Dispatch the tasks + +for i=1,nb_task do + tk = simgrid.Task.new("Task "..i,comp_size,comm_size); + alias = "slave "..(i%slave_count); + simgrid.info("Master sending '" .. simgrid.Task.name(tk) .."' To '" .. alias .."'"); + simgrid.Task.send(tk,alias); -- C user data set to NULL + simgrid.info("Master done sending '".. simgrid.Task.name(tk) .."' To '" .. alias .."'"); +end + +-- Sending Finalize Message To Others + +simgrid.info("Master: All tasks have been dispatched. Let's tell everybody the computation is over."); +for i=0,slave_count-1 do + alias = "slave "..i; + simgrid.info("Master: sending finalize to "..alias); + simgrid.Task.send(simgrid.Task.new("finalize",0,0),alias); +end +simgrid.info("Master: Everything's done."); + + +end + +-- Slave Function --------------------------------------------------------- +function Slave(...) + +my_mailbox="slave "..arg[1] +simgrid.info("Hello from lua, I'm a poor slave with mbox: "..my_mailbox) + + +while true do +-- tk = simgrid.Task.new("",0,0); --?? +-- simgrid.Task.recv2(tk,my_mailbox); + tk = simgrid.Task.recv(my_mailbox); + + tk_name = simgrid.Task.name(tk) + + if (tk_name == "finalize") then + simgrid.info("Slave '" ..my_mailbox.."' got finalize msg"); + break + end + + simgrid.info("Slave '" ..my_mailbox.."' processing "..simgrid.Task.name(tk)) + simgrid.Task.execute(tk); + + simgrid.info("Slave '" ..my_mailbox.."': task "..simgrid.Task.name(tk) .. " done") +end -- while + +simgrid.info("Slave '" ..my_mailbox.."': I'm Done . See You !!"); + +end -- function ---------------------------------------------------------- +--]] + +function doyield() + coroutine.yield() +end + +require "simgrid" + +simgrid.platform("../../../examples/msg/small_platform.xml") +simgrid.application("../ruby/deploy.xml") +simgrid.run() +simgrid.info("Simulation's over. See you.") +simgrid.clean() \ No newline at end of file diff --git a/src/bindings/lua/simgrid_lua.c b/src/bindings/lua/simgrid_lua.c new file mode 100644 index 0000000000..7c395d2ff4 --- /dev/null +++ b/src/bindings/lua/simgrid_lua.c @@ -0,0 +1,286 @@ +/* SimGrid Lua bindings */ + +/* Copyright (c) 2010, the SimGrid team. All right reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#include +#include +#include + +#include "msg/msg.h" +#include "xbt.h" + +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(lua,bindings,"Lua Bindings"); + +#define TASK_MODULE_NAME "simgrid.Task" + +/* ********************************************************************************* */ +/* helper functions */ +/* ********************************************************************************* */ + +static void stackDump (lua_State *L) { + char buff[2048]; + char *p=buff; + int i; + int top = lua_gettop(L); + void *ptr; + fflush(stdout); + p+=sprintf(p,"STACK(top=%d): ",top); + for (i = 1; i <= top; i++) { /* repeat for each level */ + int t = lua_type(L, i); + switch (t) { + + case LUA_TSTRING: /* strings */ + p+=sprintf(p,"`%s'", lua_tostring(L, i)); + break; + + case LUA_TBOOLEAN: /* booleans */ + p+=sprintf(p,lua_toboolean(L, i) ? "true" : "false"); + break; + + case LUA_TNUMBER: /* numbers */ + p+=sprintf(p,"%g", lua_tonumber(L, i)); + break; + + default: /* other values */ + if ((ptr = luaL_checkudata(L,i,TASK_MODULE_NAME))) { + p+=sprintf(p,"task"); + } else { + p+=printf(p,"%s", lua_typename(L, t)); + } + break; + + } + p+=sprintf(p," "); /* put a separator */ + } + INFO1("%s",buff); +} + +/** @brief ensures that a userdata on the stack is a task and returns the pointer inside the userdata */ +static m_task_t checkTask (lua_State *L,int index) { + m_task_t *pi,tk; + luaL_checktype(L,index,LUA_TUSERDATA); + pi = (m_task_t*)luaL_checkudata(L,index,TASK_MODULE_NAME); + if(pi == NULL) + luaL_typerror(L,index,TASK_MODULE_NAME); + tk = *pi; + if(!tk) + luaL_error(L,"null Task"); + return tk; +} + +/** @brief leaves a new userdata on top of the stack, sets its metatable, and sets the Task pointer inside the userdata */ +static m_task_t *pushTask (lua_State *L,m_task_t tk) { + m_task_t *pi = (m_task_t*)lua_newuserdata(L,sizeof(m_task_t)); + *pi=tk; + luaL_getmetatable(L,TASK_MODULE_NAME); + lua_setmetatable(L,-2); + return pi; + +} + + +/* ********************************************************************************* */ +/* wrapper functions */ +/* ********************************************************************************* */ + +static int Task_new(lua_State* L) { + const char *name=luaL_checkstring(L,1); + int comp_size = luaL_checkint(L,2); + int msg_size = luaL_checkint(L,3); + // FIXME: data shouldn't be NULL I guess + pushTask(L,MSG_task_create(name,comp_size,msg_size,NULL)); + INFO0("Created task"); + return 1; +} + +static int Task_get_name(lua_State *L) { + m_task_t tk = checkTask(L,1); + lua_pushstring(L,MSG_task_get_name(tk)); + return 1; +} + +static int Task_computation_duration(lua_State *L){ + m_task_t tk = checkTask(L,1); + lua_pushnumber(L,MSG_task_get_compute_duration (tk)); + return 1; +} + +static int Task_execute(lua_State *L){ + m_task_t tk = checkTask(L,1); + int res = MSG_task_execute(tk); + lua_pushnumber(L,res); + return 1; +} + +static int Task_destroy(lua_State *L) { + m_task_t tk = checkTask(L,1); + int res = MSG_task_destroy(tk); + lua_pushnumber(L,res); + return 1; +} +static int Task_send(lua_State *L) { + m_task_t tk = checkTask(L,1); + const char *mailbox = luaL_checkstring(L,2); + stackDump(L);fflush(stdout);fflush(stderr); + int res = MSG_task_send(tk,mailbox); + res++;//FIXME: check it instead of avoiding the warning + stackDump(L); + return 0; +} +static int Task_recv(lua_State *L) { + m_task_t tk = NULL; + //stackDump(L); + const char *mailbox = luaL_checkstring(L,1); + int res = MSG_task_receive(&tk,mailbox); + res++;//FIXME: check it instead of avoiding the warning + INFO1("Task Name : >>>%s",MSG_task_get_name(tk)); + pushTask(L,tk); + // stackDump(L); + return 1; +} + +static const luaL_reg Task_methods[] = { + {"new", Task_new}, + {"name", Task_get_name}, + {"computation_duration", Task_computation_duration}, + {"execute", Task_execute}, + {"destroy", Task_destroy}, + {"send", Task_send}, + {"recv", Task_recv}, + {0,0} +}; +static int Task_gc(lua_State *L) { + m_task_t tk=checkTask(L,1); + if (tk) MSG_task_destroy(tk); + //printf("GoodBye Task(%p)\n",lua_touserdata(L,1)); + return 0; +} + +static int Task_tostring(lua_State *L) { + lua_pushfstring(L, "Task :%p",lua_touserdata(L,1)); + return 1; +} + + +static const luaL_reg Task_meta[] = { + {"__gc", Task_gc}, + {"__tostring", Task_tostring}, + {0,0} +}; + +/* + * Environment related + */ +static int launch_application(lua_State *L) { + const char * file = luaL_checkstring(L,1); + MSG_launch_application(file); + return 0; +} +#include "simix/simix.h" //FIXME: KILLME when debugging on simix internals become useless +static int create_environment(lua_State *L) { + const char *file = luaL_checkstring(L,1); + INFO1("Loading environment file %s",file); + MSG_create_environment(file); + smx_host_t *hosts = SIMIX_host_get_table(); + int i; + for (i=0;i -#include "lauxlib.h" -#include "lualib.h" - -// Msg Includes -#include -#include "msg/msg.h" -#include "msg/datatypes.h" -#include "xbt/sysdep.h" -#include "xbt/log.h" -#include "xbt/asserts.h" - - - -// *** Testing Stuff !! - -XBT_LOG_NEW_DEFAULT_CATEGORY(lua,"Lua bindings"); - -char *lua_file; -//***************************** LOAD LUA ************************************************* -static int load_lua(char * luaFile, lua_State *L) { - luaL_openlibs(L); - - - if (luaL_loadfile(L, luaFile) || lua_pcall(L, 0, 0, 0)) { - printf("error while parsing %s: %s", luaFile, lua_tostring(L, -1)); - exit(1); - } - - return 0; - -} - -int lua_wrapper(int argc, char *argv[]) { - lua_State *L = lua_open(); - load_lua(lua_file, L); - - // Seek the right lua function - lua_getglobal(L,argv[0]); - if(!lua_isfunction(L,-1)) { - lua_pop(L,1); - ERROR1("The lua function %s does not seem to exist",argv[0]); - return -1; - } - - // push arguments onto the stack - int i; - for(i=1;i /* context relative declarations */ +//#include "context_sysv_config.h" /* loads context system definitions */ +//#include "portable.h" +//#include /* context relative declarations */ #include #include /* lower this if you want to reduce the memory consumption */ -#define STACK_SIZE 128*1024 +//#define STACK_SIZE 128*1024 -#ifdef HAVE_VALGRIND_VALGRIND_H -# include -#endif /* HAVE_VALGRIND_VALGRIND_H */ - - -// FIXME: better location for that -extern void MSG_register(lua_State *L); +//#ifdef HAVE_VALGRIND_VALGRIND_H +//# include +//#endif /* HAVE_VALGRIND_VALGRIND_H */ XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(lua); typedef struct s_smx_ctx_sysv { SMX_CTX_BASE_T; - +#ifdef KILLME /* Ucontext info */ ucontext_t uc; /* the thread that execute the code */ char stack[STACK_SIZE]; /* the thread stack size */ @@ -37,6 +33,7 @@ typedef struct s_smx_ctx_sysv { #ifdef HAVE_VALGRIND_VALGRIND_H unsigned int valgrind_stack_id; /* the valgrind stack id */ #endif +#endif /* KILLME */ /* lua state info */ lua_State *state; @@ -51,13 +48,9 @@ smx_ctx_lua_create_context(xbt_main_func_t code, int argc, char** argv, void_f_pvoid_t cleanup_func, void* cleanup_arg); static int smx_ctx_lua_factory_finalize(smx_context_factory_t *factory); - static void smx_ctx_lua_free(smx_context_t context); - static void smx_ctx_lua_start(smx_context_t context); - static void smx_ctx_lua_stop(smx_context_t context); - static void smx_ctx_lua_suspend(smx_context_t context); static void @@ -65,10 +58,10 @@ smx_ctx_lua_resume(smx_context_t old_context, smx_context_t new_context); static void smx_ctx_sysv_wrapper(void); -void SIMIX_ctx_lua_factory_loadfile(const char *file) { - if (luaL_loadfile(lua_state, file) || lua_pcall(lua_state, 0, 0, 0)) - THROW2(unknown_error,0,"error while parsing %s: %s", file, lua_tostring(lua_state, -1)); - INFO1("File %s loaded",file); +/* Actually, the parameter is a lua_State*, but it got anonymized because that function + * is defined in a global header where lua may not be defined */ +void SIMIX_ctx_lua_factory_set_state(void* state) { + lua_state = state; } void SIMIX_ctx_lua_factory_init(smx_context_factory_t *factory) { @@ -83,14 +76,10 @@ void SIMIX_ctx_lua_factory_init(smx_context_factory_t *factory) { (*factory)->resume = smx_ctx_lua_resume; (*factory)->name = "smx_lua_context_factory"; - lua_state = lua_open(); - luaL_openlibs(lua_state); - MSG_register(lua_state); INFO0("Lua Factory created"); } -static int smx_ctx_lua_factory_finalize(smx_context_factory_t * factory) -{ +static int smx_ctx_lua_factory_finalize(smx_context_factory_t * factory) { lua_close(lua_state); free(*factory); @@ -100,44 +89,26 @@ static int smx_ctx_lua_factory_finalize(smx_context_factory_t * factory) static smx_context_t smx_ctx_lua_create_context(xbt_main_func_t code, int argc, char** argv, - void_f_pvoid_t cleanup_func, void* cleanup_arg) -{ + void_f_pvoid_t cleanup_func, void* cleanup_arg) { + smx_ctx_lua_t context = xbt_new0(s_smx_ctx_lua_t, 1); /* If the user provided a function for the process then use it otherwise is the context for maestro */ - if(code){ + if (code){ context->code = code; - xbt_assert2(getcontext(&(context->uc)) == 0, - "Error in context saving: %d (%s)", errno, strerror(errno)); - - context->uc.uc_link = NULL; - - context->uc.uc_stack.ss_sp = - pth_skaddr_makecontext(context->stack, STACK_SIZE); - - context->uc.uc_stack.ss_size = - pth_sksize_makecontext(context->stack, STACK_SIZE); - -#ifdef HAVE_VALGRIND_VALGRIND_H - context->valgrind_stack_id = - VALGRIND_STACK_REGISTER(context->uc.uc_stack.ss_sp, - ((char *) context->uc.uc_stack.ss_sp) + - context->uc.uc_stack.ss_size); -#endif /* HAVE_VALGRIND_VALGRIND_H */ - - - context->state = lua_newthread(lua_state); - - context->ref = luaL_ref(lua_state, LUA_REGISTRYINDEX); - //lua_pop(lua_state,1); - context->argc = argc; context->argv = argv; context->cleanup_func = cleanup_func; context->cleanup_arg = cleanup_arg; INFO1("Created context for function %s",argv[0]); + + /* start the coroutine in charge of running that code */ + context->state = lua_newthread(lua_state); + context->ref = luaL_ref(lua_state, LUA_REGISTRYINDEX); // protect the thread from being garbage collected + /* the actual co-routine starting is done in smx_ctx_lua_start */ + context->nargs = argc-1; } else { INFO0("Created context for maestro"); } @@ -149,10 +120,9 @@ static void smx_ctx_lua_free(smx_context_t pcontext) { int i; smx_ctx_lua_t context = (smx_ctx_lua_t)pcontext; + if (context){ -#ifdef HAVE_VALGRIND_VALGRIND_H - VALGRIND_STACK_DEREGISTER(((smx_ctx_lua_t) context)->valgrind_stack_id); -#endif /* HAVE_VALGRIND_VALGRIND_H */ + DEBUG1("smx_ctx_lua_free_context(%p)",context); /* free argv */ if (context->argv) { @@ -163,25 +133,22 @@ static void smx_ctx_lua_free(smx_context_t pcontext) free(context->argv); } - - /* destroy the context */ + /* let the lua garbage collector reclaim the thread used for the coroutine */ luaL_unref(lua_state,LUA_REGISTRYINDEX,context->ref ); + free(context); + context = NULL; } } static void smx_ctx_lua_start(smx_context_t pcontext) { smx_ctx_lua_t context = (smx_ctx_lua_t)pcontext; - makecontext(&context->uc, smx_ctx_sysv_wrapper, 0); - - INFO1("Starting '%s'",context->argv[0]); + DEBUG1("Starting '%s'",context->argv[0]); lua_getglobal(context->state,context->argv[0]); - if(!lua_isfunction(context->state,-1)) { - lua_pop(context->state,1); - THROW1(arg_error,0,"The lua function %s does not seem to exist",context->argv[0]); - } + xbt_assert1(lua_isfunction(context->state,-1), + "The lua function %s does not seem to exist",context->argv[0]); // push arguments onto the stack int i; @@ -195,62 +162,33 @@ static void smx_ctx_lua_start(smx_context_t pcontext) { static void smx_ctx_lua_stop(smx_context_t pcontext) { smx_ctx_lua_t context = (smx_ctx_lua_t)pcontext; + INFO1("Stopping '%s' (nothing to do)",context->argv[0]); if (context->cleanup_func) (*context->cleanup_func) (context->cleanup_arg); - smx_ctx_lua_suspend(pcontext); +// smx_ctx_lua_suspend(pcontext); } -static void smx_ctx_sysv_wrapper() -{ - /*FIXME: I would like to avoid accesing simix_global to get the current - context by passing it as an argument of the wrapper function. The problem - is that this function is called from smx_ctx_sysv_start, and uses - makecontext for calling it, and the stupid posix specification states that - all the arguments of the function should be int(32 bits), making it useless - in 64-bit architectures where pointers are 64 bit long. - */ - smx_ctx_lua_t context = - (smx_ctx_lua_t)simix_global->current_process->context; - - (context->code) (context->argc, context->argv); - - smx_ctx_lua_stop((smx_context_t)context); -} - - -static void smx_ctx_lua_suspend(smx_context_t context) -{ - int rv; - INFO1("Suspending %s",context->argv[0]); - lua_yield(((smx_ctx_lua_t)context)->state,0); // Should be the last line of the function - smx_ctx_lua_t prev_context = ((smx_ctx_lua_t) context)->prev; - - ((smx_ctx_lua_t) context)->prev = NULL; - - rv = swapcontext(&((smx_ctx_lua_t) context)->uc, &prev_context->uc); - - xbt_assert0((rv == 0), "Context swapping failure"); - // INFO1("Suspended %s",context->argv[0]); +static void smx_ctx_lua_suspend(smx_context_t pcontext) { + smx_ctx_lua_t context = (smx_ctx_lua_t)pcontext; + DEBUG1("Suspending '%s' (calling lua_yield)",context->argv[0]); + //lua_yield(context->state,0); + + lua_getglobal(context->state,"doyield"); + xbt_assert0(lua_isfunction(context->state,-1), + "Cannot find the coroutine.yield function..."); + INFO0("Call coroutine.yield"); + lua_call(context->state,0,0); + INFO0("Back from call to coroutine.yield"); } static void smx_ctx_lua_resume(smx_context_t old_context, smx_context_t new_context) { - int rv; smx_ctx_lua_t context = (smx_ctx_lua_t)new_context; - - INFO1("Resuming %s",context->argv[0]); - lua_resume(context->state,context->nargs); - context->nargs = 0; - INFO1("Resumed %s",context->argv[0]); - - ((smx_ctx_lua_t) new_context)->prev = (smx_ctx_lua_t)old_context; - - rv = swapcontext(&((smx_ctx_lua_t)old_context)->uc, - &((smx_ctx_lua_t)new_context)->uc); - - xbt_assert0((rv == 0), "Context swapping failure"); - - // INFO1("Process %s done ?",context->argv[0]); - // lua_resume(((smx_ctx_lua_t)new_context)->state,0); + DEBUG1("Resuming %s",context->argv[0]); + int ret = lua_resume(context->state,context->nargs); + INFO3("Function %s yielded back with value %d %s",context->argv[0],ret,(ret==LUA_YIELD?"(ie, LUA_YIELD)":"")); + if (lua_isstring(context->state,-1)) + INFO2("Result of %s seem to be '%s'",context->argv[0],luaL_checkstring(context->state,-1)); + context->nargs=0; }