Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Fix stripping of first argument.
[simgrid.git] / src / simix / smx_context_lua.c
1 /* $Id$ */
2
3 /* context_lua - implementation of context switching with lua coroutines */
4
5 /* Copyright (c) 2004-2008 the SimGrid team. All right reserved */
6
7 /* This program is free software; you can redistribute it and/or modify it
8  * under the terms of the license (GNU LGPL) which comes with this package. */
9
10 #include "private.h"
11 #include "context_sysv_config.h"        /* loads context system definitions */
12 #include "portable.h"
13 #include <lua5.1/lauxlib.h>
14 #include <lua5.1/lualib.h>
15
16 // FIXME: better location for that
17 extern void MSG_register(lua_State *L);
18
19 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(smx_lua);
20
21 typedef struct s_smx_ctx_sysv {
22   SMX_CTX_BASE_T;
23   lua_State *state;
24   int ref; /* to prevent the lua GC from collecting my threads, I ref them explicitely */
25   int nargs; /* argument to lua_resume. First time: argc-1, afterward: 0 */
26 } s_smx_ctx_lua_t, *smx_ctx_lua_t;
27
28 static lua_State *lua_state;
29
30 static smx_context_t 
31 smx_ctx_lua_create_context(xbt_main_func_t code, int argc, char** argv, 
32                                     void_f_pvoid_t cleanup_func, void* cleanup_arg);
33
34 static int smx_ctx_lua_factory_finalize(smx_context_factory_t *factory);
35
36 static void smx_ctx_lua_free(smx_context_t context);
37
38 static void smx_ctx_lua_start(smx_context_t context);
39
40 static void smx_ctx_lua_stop(smx_context_t context);
41
42 static void smx_ctx_lua_suspend(smx_context_t context);
43
44 static void 
45   smx_ctx_lua_resume(smx_context_t old_context, smx_context_t new_context);
46
47 static void smx_ctx_sysv_wrapper(void);
48
49 void SIMIX_ctx_lua_factory_loadfile(const char *file) {
50   if (luaL_loadfile(lua_state, file) || lua_pcall(lua_state, 0, 0, 0))
51     THROW2(unknown_error,0,"error while parsing %s: %s", file, lua_tostring(lua_state, -1));
52   INFO1("File %s loaded",file);
53 }
54 void SIMIX_ctx_lua_factory_init(smx_context_factory_t *factory) {
55
56   *factory = xbt_new0(s_smx_context_factory_t, 1);
57
58   (*factory)->create_context = smx_ctx_lua_create_context;
59   (*factory)->finalize = smx_ctx_lua_factory_finalize;
60   (*factory)->free = smx_ctx_lua_free;
61   (*factory)->start = smx_ctx_lua_start;
62   (*factory)->stop = smx_ctx_lua_stop;
63   (*factory)->suspend = smx_ctx_lua_suspend;
64   (*factory)->resume = smx_ctx_lua_resume;
65   (*factory)->name = "smx_lua_context_factory";
66
67   lua_state = lua_open();
68   luaL_openlibs(lua_state);
69   MSG_register(lua_state);
70   INFO0("Lua Factory created");
71 }
72
73 static int smx_ctx_lua_factory_finalize(smx_context_factory_t * factory)
74 {
75   lua_close(lua_state);
76
77   free(*factory);
78   *factory = NULL;
79   return 0;
80 }
81
82 static smx_context_t 
83 smx_ctx_lua_create_context(xbt_main_func_t code, int argc, char** argv, 
84                                     void_f_pvoid_t cleanup_func, void* cleanup_arg)
85 {
86   smx_ctx_lua_t context = xbt_new0(s_smx_ctx_lua_t, 1);
87
88   /* If the user provided a function for the process then use it
89      otherwise is the context for maestro */
90   if(code){
91     context->code = code;
92     context->state = lua_newthread(lua_state);
93
94     context->ref = luaL_ref(lua_state, LUA_REGISTRYINDEX);
95     //lua_pop(lua_state,1);
96
97     context->argc = argc;
98     context->argv = argv;
99     context->cleanup_func = cleanup_func;
100     context->cleanup_arg = cleanup_arg;
101     INFO1("Created context for function %s",argv[0]);
102   } else {
103     INFO0("Created context for maestro");
104   }
105   
106   return (smx_context_t)context;
107 }
108
109 static void smx_ctx_lua_free(smx_context_t pcontext)
110 {
111   int i;
112   smx_ctx_lua_t context = (smx_ctx_lua_t)pcontext;
113   if (context){
114
115     /* free argv */
116     if (context->argv) {
117       for (i = 0; i < context->argc; i++)
118         if (context->argv[i])
119           free(context->argv[i]);
120
121       free(context->argv);
122     }
123     
124     /* destroy the context */
125     luaL_unref(lua_state,LUA_REGISTRYINDEX,context->ref );
126     free(context);
127   }
128 }
129
130 static void smx_ctx_lua_start(smx_context_t pcontext) {
131   smx_ctx_lua_t context = (smx_ctx_lua_t)pcontext;
132   INFO1("Starting '%s'",context->argv[0]);
133
134   lua_getglobal(context->state,context->argv[0]);
135   if(!lua_isfunction(context->state,-1)) {
136     lua_pop(context->state,1);
137     THROW1(arg_error,0,"The lua function %s does not seem to exist",context->argv[0]);
138   }
139
140   // push arguments onto the stack
141   int i;
142   for(i=1;i<context->argc;i++)
143     lua_pushstring(context->state,context->argv[i]);
144
145   // Call the function
146   context->nargs = context->argc-1;
147 }
148
149 static void smx_ctx_lua_stop(smx_context_t pcontext) {
150   smx_ctx_lua_t context = (smx_ctx_lua_t)pcontext;
151   
152   if (context->cleanup_func)
153     (*context->cleanup_func) (context->cleanup_arg);
154
155   // FIXME: DO it
156 }
157
158
159 static void smx_ctx_lua_suspend(smx_context_t context)
160 {
161   INFO1("Suspending %s",context->argv[0]);
162   lua_yield(((smx_ctx_lua_t)context)->state,0); // Should be the last line of the function
163 //  INFO1("Suspended %s",context->argv[0]);
164 }
165
166 static void 
167 smx_ctx_lua_resume(smx_context_t old_context, smx_context_t new_context) {
168   smx_ctx_lua_t context = (smx_ctx_lua_t)new_context;
169
170   INFO1("Resuming %s",context->argv[0]);
171   lua_resume(context->state,context->nargs);
172   context->nargs = 0;
173   INFO1("Resumed %s",context->argv[0]);
174
175 //  INFO1("Process %s done ?",context->argv[0]);
176 //  lua_resume(((smx_ctx_lua_t)new_context)->state,0);
177 }