diff options
Diffstat (limited to 'src/keeper.c')
-rw-r--r-- | src/keeper.c | 112 |
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 | ||
130 | void 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 | |||
128 | struct s_Keeper *keeper_acquire( const void *ptr) | 178 | struct 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 | ||
144 | void keeper_release( struct s_Keeper *K) | 202 | void 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 | ||
150 | void keeper_toggle_nil_sentinels( lua_State *L, int _val_i, int _nil_to_sentinel) | 208 | void keeper_toggle_nil_sentinels( lua_State *L, int _val_i, int _nil_to_sentinel) |