aboutsummaryrefslogtreecommitdiff
path: root/src/keeper.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/keeper.c')
-rw-r--r--src/keeper.c112
1 files changed, 85 insertions, 27 deletions
diff --git a/src/keeper.c b/src/keeper.c
index 5b355cb..1f69d40 100644
--- a/src/keeper.c
+++ b/src/keeper.c
@@ -90,61 +90,119 @@ char const *init_keepers( int const _nbKeepers)
90 // Initialize Keeper states with bare minimum of libs (those required 90 // Initialize Keeper states with bare minimum of libs (those required
91 // by 'keeper.lua') 91 // by 'keeper.lua')
92 // 92 //
93 lua_State *L= luaL_newstate(); 93 lua_State *K = luaL_newstate();
94 if (!L) 94 if (!K)
95 return "out of memory"; 95 return "out of memory";
96 96
97 // to see VM name in Decoda debugger 97 // to see VM name in Decoda debugger
98 lua_pushliteral( L, "Keeper #"); 98 lua_pushliteral( K, "Keeper #");
99 lua_pushinteger( L, i + 1); 99 lua_pushinteger( K, i + 1);
100 lua_concat( L, 2); 100 lua_concat( K, 2);
101 lua_setglobal( L, "decoda_name"); 101 lua_setglobal( K, "decoda_name");
102
103 luaG_openlibs( L, "io,table,package" ); // 'io' for debugging messages, package because we need to require modules exporting idfuncs
104 serialize_require( L);
105 102
103 // 'io' for debugging messages, 'package' because we need to require modules exporting idfuncs
104 // the others because they export functions that we may store in a keeper for transfer between lanes
105 luaG_openlibs( K, "*");
106 serialize_require( K);
106 107
107 // Read in the preloaded chunk (and run it) 108 // Read in the preloaded chunk (and run it)
108 // 109 //
109 if (luaL_loadbuffer( L, keeper_chunk, sizeof(keeper_chunk), "@keeper.lua")) 110 if( luaL_loadbuffer( K, keeper_chunk, sizeof(keeper_chunk), "@keeper.lua"))
110 return "luaL_loadbuffer() failed"; // LUA_ERRMEM 111 return "luaL_loadbuffer() failed"; // LUA_ERRMEM
111 112
112 if (lua_pcall( L, 0 /*args*/, 0 /*results*/, 0 /*errfunc*/ )) 113 if( lua_pcall( K, 0 /*args*/, 0 /*results*/, 0 /*errfunc*/))
113 { 114 {
114 // LUA_ERRRUN / LUA_ERRMEM / LUA_ERRERR 115 // LUA_ERRRUN / LUA_ERRMEM / LUA_ERRERR
115 // 116 //
116 const char *err= lua_tostring(L,-1); 117 const char *err = lua_tostring(K, -1);
117 assert(err); 118 assert( err);
118 return err; 119 return err;
119 } 120 }
120 121
121 MUTEX_INIT( &GKeepers[i].lock_ ); 122 MUTEX_INIT( &GKeepers[i].lock_);
122 GKeepers[i].L= L; 123 GKeepers[i].L = K;
123 //GKeepers[i].count = 0; 124 //GKeepers[i].count = 0;
124 } 125 }
125 return NULL; // ok 126 return NULL; // ok
126} 127}
127 128
129// cause each keeper state to populate its database of transferable functions with those from the specified module
130void populate_keepers( lua_State *L)
131{
132 size_t name_len;
133 char const *name = luaL_checklstring( L, -1, &name_len);
134 size_t package_path_len;
135 char const *package_path;
136 size_t package_cpath_len;
137 char const *package_cpath;
138 int i;
139
140 // we need to make sure that package.path & package.cpath are the same in the keepers
141// than what is currently in use when the module is required in the caller's Lua state
142 STACK_CHECK(L)
143 STACK_GROW( L, 3);
144 lua_getglobal( L, "package");
145 lua_getfield( L, -1, "path");
146 package_path = luaL_checklstring( L, -1, &package_path_len);
147 lua_getfield( L, -2, "cpath");
148 package_cpath = luaL_checklstring( L, -1, &package_cpath_len);
149
150 for( i = 0; i < GNbKeepers; ++ i)
151 {
152 lua_State *K = GKeepers[i].L;
153 int res;
154 MUTEX_LOCK( &GKeepers[i].lock_);
155 STACK_CHECK(K)
156 STACK_GROW( K, 2);
157 lua_getglobal( K, "package");
158 lua_pushlstring( K, package_path, package_path_len);
159 lua_setfield( K, -2, "path");
160 lua_pushlstring( K, package_cpath, package_cpath_len);
161 lua_setfield( K, -2, "cpath");
162 lua_pop( K, 1);
163 lua_getglobal( K, "require");
164 lua_pushlstring( K, name, name_len);
165 res = lua_pcall( K, 1, 0, 0);
166 if( res != 0)
167 {
168 char const *err = luaL_checkstring( K, -1);
169 luaL_error( L, "error requiring '%s' in keeper state: %s", name, err);
170 }
171 STACK_END(K, 0)
172 MUTEX_UNLOCK( &GKeepers[i].lock_);
173 }
174 lua_pop( L, 3);
175 STACK_END(L, 0)
176}
177
128struct s_Keeper *keeper_acquire( const void *ptr) 178struct s_Keeper *keeper_acquire( const void *ptr)
129{ 179{
130 /* 180 // can be 0 if this happens during main state shutdown (lanes is being GC'ed -> no keepers)
131 * Any hashing will do that maps pointers to 0..GNbKeepers-1 181 if( GNbKeepers == 0)
132 * consistently. 182 {
133 * 183 return NULL;
134 * Pointers are often aligned by 8 or so - ignore the low order bits 184 }
135 */ 185 else
136 unsigned int i= ((unsigned long)(ptr) >> 3) % GNbKeepers; 186 {
137 struct s_Keeper *K= &GKeepers[i]; 187 /*
188 * Any hashing will do that maps pointers to 0..GNbKeepers-1
189 * consistently.
190 *
191 * Pointers are often aligned by 8 or so - ignore the low order bits
192 */
193 unsigned int i= ((unsigned long)(ptr) >> 3) % GNbKeepers;
194 struct s_Keeper *K= &GKeepers[i];
138 195
139 MUTEX_LOCK( &K->lock_); 196 MUTEX_LOCK( &K->lock_);
140 //++ K->count; 197 //++ K->count;
141 return K; 198 return K;
199 }
142} 200}
143 201
144void keeper_release( struct s_Keeper *K) 202void keeper_release( struct s_Keeper *K)
145{ 203{
146 //-- K->count; 204 //-- K->count;
147 MUTEX_UNLOCK( &K->lock_); 205 if( K) MUTEX_UNLOCK( &K->lock_);
148} 206}
149 207
150void keeper_toggle_nil_sentinels( lua_State *L, int _val_i, int _nil_to_sentinel) 208void keeper_toggle_nil_sentinels( lua_State *L, int _val_i, int _nil_to_sentinel)