From 3236320311f15640083c5bf420bcdeab725ff242 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Wed, 25 Jan 2012 02:29:35 +1000 Subject: Hack together LuaSL, LuaJIT, and luaproc. It's frankenstein right now. lol --- LuaSL/build.sh | 13 +- LuaSL/src/LuaSL_LSL_tree.h | 7 ++ LuaSL/src/LuaSL_main.c | 185 +++++++++++++++++++++++++++- LuaSL/testLua/luaprocTest0.lua | 7 +- LuaSL/testLua/luaprocTest0_C.lua | 37 ++++++ LuaSL/testLua/luaprocTest1_C.lua | 28 +++++ LuaSL/testLua/luaprocTest2_C.lua | 65 ++++++++++ build.sh | 4 +- libraries/README | 3 + libraries/luajit-2.0/src/libluajit-5.1.so.2 | 1 + libraries/luaproc/luaproc.c | 72 +++++++---- libraries/luaproc/luaproc.h | 5 + libraries/luaproc/sched.c | 44 ++++++- test.sh | 6 +- 14 files changed, 439 insertions(+), 38 deletions(-) create mode 100644 LuaSL/testLua/luaprocTest0_C.lua create mode 100644 LuaSL/testLua/luaprocTest1_C.lua create mode 100644 LuaSL/testLua/luaprocTest2_C.lua create mode 120000 libraries/luajit-2.0/src/libluajit-5.1.so.2 diff --git a/LuaSL/build.sh b/LuaSL/build.sh index 15e1d52..4433120 100755 --- a/LuaSL/build.sh +++ b/LuaSL/build.sh @@ -18,6 +18,9 @@ fi # No need for a make file, or dependencies, the entire thing takes only a few seconds to build. CFLAGS="-g -Wall -I include -I $LOCALDIR/src" +CFLAGS="$CFLAGS -I ../../libraries" +CFLAGS="$CFLAGS -I ../../libraries/luajit-2.0/src" +#CFLAGS="$CFLAGS -I /usr/include/lua5.1" CFLAGS="$CFLAGS -I $E17DIR/include/eina-1" CFLAGS="$CFLAGS -I $E17DIR/include/eina-1/eina" CFLAGS="$CFLAGS -I $E17DIR/include/eet-1" @@ -28,12 +31,13 @@ CFLAGS="$CFLAGS -I $E17DIR/include/ecore-1" CFLAGS="$CFLAGS -I $E17DIR/include" CFLAGS="$CFLAGS -DPACKAGE_DATA_DIR=\"$LOCALDIR\" $CFLAGOPTS" -LDFLAGS="-L lib -L /usr/lib -L /lib -L $E17DIR/lib -L ../../libraries/luajit-2.0/src" -libs="-lecore -levas -ledje -lembryo -leet -leina -lluajit -lpthread" +LDFLAGS="-L ../../libraries/luajit-2.0/src -L lib -L /usr/lib -L /lib -L $E17DIR/lib" +libs="-lecore -levas -ledje -lembryo -leet -leina -lluajit -lpthread -lm" +#LDFLAGS="-L /usr/lib/lua/5.1 -L lib -L /usr/lib -L /lib -L $E17DIR/lib" +#libs="-lecore -levas -ledje -lembryo -leet -leina -llua5.1 -lpthread -lm" # These need to be added to libs if linking staticaly, though some parts of EFL don't like that. #-lecore_evas \ #-lecore_file \ -#-lm \ #-ldl \ #-lfontconfig \ #-lfreetype \ @@ -43,6 +47,7 @@ libs="-lecore -levas -ledje -lembryo -leet -leina -lluajit -lpthread" LFLAGS="-d" EDJE_FLAGS="-id images -fd fonts" +LD_RUN_PATH="../../libraries/luajit-2.0/src:" # Run lemon first, flex depends on it to define the symbol values. @@ -59,7 +64,7 @@ echo $command $command names="LuaSL_main LuaSL_compile LuaSL_utilities LuaSL_lexer LuaSL_lemon_yaccer" -objects="" +objects="../../libraries/luaproc/channel.o ../../libraries/luaproc/list.o ../../libraries/luaproc/luaproc.o ../../libraries/luaproc/sched.o " for i in $names do command="gcc $CFLAGS -c -o $i.o $i.c" diff --git a/LuaSL/src/LuaSL_LSL_tree.h b/LuaSL/src/LuaSL_LSL_tree.h index 687c56c..20277b9 100644 --- a/LuaSL/src/LuaSL_LSL_tree.h +++ b/LuaSL/src/LuaSL_LSL_tree.h @@ -20,6 +20,13 @@ #include #include // For PATH_MAX. +#include +#include +#include +#include + +#include + #include "LuaSL_lemon_yaccer.h" #define YYERRCODE 256 diff --git a/LuaSL/src/LuaSL_main.c b/LuaSL/src/LuaSL_main.c index 3f20460..f2f4f17 100644 --- a/LuaSL/src/LuaSL_main.c +++ b/LuaSL/src/LuaSL_main.c @@ -106,6 +106,163 @@ static void dirListLua_cb(const char *name, const char *path, void *data) } } } + +#ifdef _WIN32 +# define FMT_SIZE_T "%Iu" +#else +# define FMT_SIZE_T "%zu" +#endif + +#define MAX_LUA_MEM (4 * (1024 * 1024)) + +#define _edje_lua2_error(L, err_code) _edje_lua2_error_full(__FILE__, __FUNCTION__, __LINE__, L, err_code) + +/* +typedef struct _Edje_Lua_Alloc Edje_Lua_Alloc; + +struct _Edje_Lua_Alloc +{ + size_t max, cur; +}; + +static void * +_elua_alloc(void *ud, void *ptr, size_t osize, size_t nsize) +{ + Edje_Lua_Alloc *ela = ud; + void *ptr2 = NULL; + + if (ela) + { + ela->cur += nsize - osize; + if (ela->cur > ela->max) + { + printf("Lua memory limit of " FMT_SIZE_T " bytes reached (" FMT_SIZE_T " allocated)", ela->max, ela->cur); + } + else if (nsize == 0) + { + free(ptr); + } + else + { + ptr2 = realloc(ptr, nsize); + if (NULL == ptr2) + printf("Lua cannot re-allocate " FMT_SIZE_T " bytes", nsize); + } + } + else + printf("Lua cannoct allocate memory, no Edje_Lua_Alloc"); + + return ptr2; +} + +static int panics = 0; +static int +_elua_custom_panic(lua_State *L) // Stack usage [-0, +0, m] +{ + // If we somehow manage to have multiple panics, it's likely due to being out + // of memory in the following lua_tostring() call. + panics++; + if (panics) + { + printf("Lua PANICS!!!!!"); + } + else + { + printf("Lua PANIC!!!!!: %s", lua_tostring(L, -1)); // Stack usage [-0, +0, m] + } + // The docs say that this will cause an exit(EXIT_FAILURE) if we return, + // and that we we should long jump some where to avoid that. This is only + // called for things not called from a protected environment. We always + // use pcalls though, except for the library load calls. If we can't load + // the standard libraries, then perhaps a crash is the right thing. + return 0; +} + +static void +_edje_lua2_error_full(const char *file, const char *fnc, int line, + lua_State *L, int err_code) // Stack usage [-0, +0, m] +{ + const char *err_type; + + switch (err_code) + { + case LUA_ERRRUN: + err_type = "runtime"; + break; + case LUA_ERRSYNTAX: + err_type = "syntax"; + break; + case LUA_ERRMEM: + err_type = "memory allocation"; + break; + case LUA_ERRERR: + err_type = "error handler"; + break; + default: + err_type = "unknown"; + break; + } + printf("Lua %s error: %s\n", err_type, lua_tostring(L, -1)); // Stack usage [-0, +0, m] +} + +static int errFunc(lua_State *L) +{ + int i = 0; + lua_Debug ar; + + while (lua_getstack(L, i++, &ar)) + { + if (lua_getinfo(L, "nSlu", &ar)) + { + if (NULL == ar.name) + ar.name = "DUNNO"; + printf("Lua error in the %s %s %s @ line %d in %s\n%s!", ar.what, ar.namewhat, ar.name, ar.currentline, ar.short_src, ar.source); + } + } + return 0; +} +*/ + +static void runnerSetup(gameGlobals *game) +{ + luaprocInit(); + + if ( sched_create_worker( ) != LUAPROC_SCHED_OK ) + PE("Error creating luaproc worker thread."); + if ( sched_create_worker( ) != LUAPROC_SCHED_OK ) + PE("Error creating luaproc worker thread."); + if ( sched_create_worker( ) != LUAPROC_SCHED_OK ) + PE("Error creating luaproc worker thread."); + if ( sched_create_worker( ) != LUAPROC_SCHED_OK ) + PE("Error creating luaproc worker thread."); +} + +static void runnerTearDown(gameGlobals *game) +{ +// TODO - this is what hangs the system. + sched_join_workerthreads(); +} + +static void runLuaFile(gameGlobals *game, const char *filename) +{ + newProc(filename, TRUE); + +// TODO, should set up our panic and errfunc as below. Plus the other TODO stuff. + +/* +// TODO - hack up LuaJIT so that we can limit memory per state. +// lua_setallocf(L, _elua_alloc, &ela); // LuaJIT uses a heavily hacked up dlmalloc. Seems that standard realloc is not so thread safe? + lua_atpanic(L, _elua_custom_panic); +// TODO - Sandbox out what this opens. See lib_init.c from LuaJIT. + luaL_openlibs(L); + + lua_pushcfunction(L, errFunc); + ... + if ((err = lua_pcall(L, 0, 0, -2))) + _edje_lua2_error(L, err); +*/ +} + #endif int @@ -248,6 +405,7 @@ main(int argc, char **argv) scriptCount = 0; gettimeofday(&lastTime2, 0); compilerSetup(&game); + runnerSetup(&game); snprintf(buf, sizeof(buf), "%s/Test sim/objects", PACKAGE_DATA_DIR); eina_file_dir_list(buf, EINA_TRUE, dirList_cb, &game); diff = timeDiff(&thisTime2, &lastTime2); @@ -266,35 +424,46 @@ main(int argc, char **argv) printf("Combined estimate of compiling speed is %f scripts per second.\n", 1 / ((diff0 / lslCount) + (diff / scriptCount))); gettimeofday(&lastTime2, 0); - snprintf(buf, sizeof(buf), "cd %s/testLua; LUA_SOPATH='../../libraries/luaproc/' lua luaprocTest0.lua", PACKAGE_DATA_DIR); + snprintf(buf, sizeof(buf), "lua luaprocTest0.lua"); system(buf); diff = timeDiff(&thisTime2, &lastTime2); - printf("%s TOOK %f seconds.\n", buf, diff); + printf("%s TOOK %f seconds......................................................................................................\n", buf, diff); gettimeofday(&lastTime2, 0); - snprintf(buf, sizeof(buf), "cd %s/testLua; LUA_SOPATH='../../libraries/luaproc/' lua luaprocTest1.lua", PACKAGE_DATA_DIR); + snprintf(buf, sizeof(buf), "%s/testLua/luaprocTest0_C.lua", PACKAGE_DATA_DIR); + runLuaFile(&game, buf); + diff = timeDiff(&thisTime2, &lastTime2); + printf("Running that last one locally TOOK %f seconds.\n",diff); + + gettimeofday(&lastTime2, 0); + snprintf(buf, sizeof(buf), "lua luaprocTest1.lua"); system(buf); diff = timeDiff(&thisTime2, &lastTime2); printf("%s TOOK %f seconds.\n", buf, diff); gettimeofday(&lastTime2, 0); - snprintf(buf, sizeof(buf), "cd %s/testLua; LUA_SOPATH='../../libraries/luaproc/' luajit luaprocTest1.lua", PACKAGE_DATA_DIR); + snprintf(buf, sizeof(buf), "../../libraries/luajit-2.0/src/luajit luaprocTest1.lua"); system(buf); diff = timeDiff(&thisTime2, &lastTime2); printf("%s TOOK %f seconds.\n", buf, diff); gettimeofday(&lastTime2, 0); - snprintf(buf, sizeof(buf), "cd %s/testLua; LUA_SOPATH='../../libraries/luaproc/' lua luaprocTest2.lua", PACKAGE_DATA_DIR); + snprintf(buf, sizeof(buf), "lua luaprocTest2.lua"); system(buf); diff = timeDiff(&thisTime2, &lastTime2); printf("%s TOOK %f seconds.\n", buf, diff); gettimeofday(&lastTime2, 0); - snprintf(buf, sizeof(buf), "cd %s/testLua; LUA_SOPATH='../../libraries/luaproc/' luajit luaprocTest2.lua", PACKAGE_DATA_DIR); + snprintf(buf, sizeof(buf), "../../libraries/luajit-2.0/src/luajit luaprocTest2.lua"); system(buf); diff = timeDiff(&thisTime2, &lastTime2); printf("%s TOOK %f seconds.\n", buf, diff); + gettimeofday(&lastTime2, 0); + snprintf(buf, sizeof(buf), "%s/testLua/luaprocTest2_C.lua", PACKAGE_DATA_DIR); + runLuaFile(&game, buf); + diff = timeDiff(&thisTime2, &lastTime2); + printf("Running that last one locally TOOK %f seconds.\n",diff); #endif if (game.ui) @@ -303,6 +472,10 @@ main(int argc, char **argv) ecore_animator_del(ani); ecore_evas_free(game.ee); } + + runnerTearDown(&game); + diff = timeDiff(&thisTime2, &lastTime2); + printf("Running that last one locally TOOK %f seconds.\n",diff); edje_shutdown(); ecore_evas_shutdown(); } diff --git a/LuaSL/testLua/luaprocTest0.lua b/LuaSL/testLua/luaprocTest0.lua index 5868d6f..94a1d20 100644 --- a/LuaSL/testLua/luaprocTest0.lua +++ b/LuaSL/testLua/luaprocTest0.lua @@ -33,7 +33,12 @@ luaproc.createworker() luaproc.newproc( [=[ luaproc.newchannel( "testchannel" ) luaproc.newproc( "luaproc.send( 'testchannel', 'luaproc is working fine!' )" ) - luaproc.newproc( "print( luaproc.receive( 'testchannel' ))" ) + luaproc.newproc( "print(luaproc.receive( 'testchannel'))" ) + print("End of parent proc") ]=] ) +print("About to luaproc.exit()!"); luaproc.exit() +print("Should have exited after the luaproc.exit()!"); + + diff --git a/LuaSL/testLua/luaprocTest0_C.lua b/LuaSL/testLua/luaprocTest0_C.lua new file mode 100644 index 0000000..0dd6078 --- /dev/null +++ b/LuaSL/testLua/luaprocTest0_C.lua @@ -0,0 +1,37 @@ +---------------------------------------------------- +-- +-- Copyright 2008 Alexandre Skyrme, Noemi Rodriguez, Roberto Ierusalimschy +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy +-- of this software and associated documentation files (the "Software"), to deal +-- in the Software without restriction, including without limitation the rights +-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +-- copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in +-- all copies or substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +-- THE SOFTWARE. +-- +----------------------------------------------------- +-- +-- test.lua +-- +----------------------------------------------------- + +luaproc.newproc( [=[ + luaproc.newchannel( "testchannel" ) + luaproc.newproc( "luaproc.send( 'testchannel', 'luaproc is working fine!' )" ) + luaproc.newproc( "print(luaproc.receive( 'testchannel'))" ) + print("End of parent proc") +]=] ) + +print("About to exit."); + diff --git a/LuaSL/testLua/luaprocTest1_C.lua b/LuaSL/testLua/luaprocTest1_C.lua new file mode 100644 index 0000000..61cb461 --- /dev/null +++ b/LuaSL/testLua/luaprocTest1_C.lua @@ -0,0 +1,28 @@ +result, error_msg = luaproc.newproc( [=[ + + local count = 0 + +-- Hmm, luajit 2 beta 9 crashes at about 8140, lua can go up to 50000 at least. + for i = 1, 8000 do + local channel = "channel" .. i +-- local proc = 'print(luaproc.receive("channel' .. i .. '") .. " " .. ' .. i ..')' + local proc = 'luaproc.receive("' .. channel .. '")' + +-- print(channel .. "\n" .. proc) + result, error_msg = luaproc.newchannel(channel) + if not result then print(error_msg) end + result, error_msg = luaproc.newproc(proc) + if not result then print(error_msg) else count = count + 1 end + end + + print("Started " .. count .. " Lua threads") + + if 0 ~= count then + for i = 1, count do + result, error_msg = luaproc.send("channel" .. i, 'luaproc is working fine! ' .. i) + if not result then print(error_msg .. " " .. i) end + end + end +]=] ) +if not result then print(error_msg .. " for main proc") end + diff --git a/LuaSL/testLua/luaprocTest2_C.lua b/LuaSL/testLua/luaprocTest2_C.lua new file mode 100644 index 0000000..e1a5a83 --- /dev/null +++ b/LuaSL/testLua/luaprocTest2_C.lua @@ -0,0 +1,65 @@ +count = 0 + +proc = [=[ + require "string" + local channel = "channel%d" + local message + + result, error_msg = luaproc.newchannel(channel) + if not result then print(error_msg) end + repeat + message = luaproc.receive(channel) + local x, y = string.find(message, "@") + if not x then + x, y = string.find(message, "@") + x, y = string.find(message, "@") + x, y = string.find(message, "@") + x, y = string.find(message, "@") + x, y = string.find(message, "@") + x, y = string.find(message, "@") + x, y = string.find(message, "@") + x, y = string.find(message, "@") + end + until "quit" == message +]=] + +mainProc = [=[ + local count = %d + local messages = 0 + local length = 0 + local message = "This is a test message. 56789 12" + + if 0 ~= count then + for k = 0, 16 do + for j = 0, 199 do + for i = 1, count do + result, error_msg = luaproc.send("channel" .. i, message) + if not result then print(error_msg .. " " .. i) else + messages = messages + 1 + length = length + #message + end + end + end + message = message .. message + end + + for i = 1, count do + result, error_msg = luaproc.send("channel" .. i, "quit") + if not result then print(error_msg .. " " .. i) end + end + end + + print("Sent " .. messages .. " messages totalling " .. length .. " bytes. The largest message was " .. #message .. " bytes.") +]=] + +for i = 1, 10 do + result, error_msg = luaproc.newproc(string.format(proc, i)) + if not result then print(error_msg) else count = count + 1 end +end + +print("Started " .. count .. " Lua threads.") + +result, error_msg = luaproc.newproc(string.format(mainProc, count)) +if not result then print(error_msg) end + + diff --git a/build.sh b/build.sh index 19c7ff9..41a7470 100755 --- a/build.sh +++ b/build.sh @@ -3,8 +3,8 @@ wd=$(pwd) echo "_______________ BUILDING LuaJIT _______________" -cd libraries/luajit-2.0 -make +cd $wd/libraries/luajit-2.0 +make amalg PREFIX=$()/src echo "_______________ BUILDING luaproc _______________" diff --git a/libraries/README b/libraries/README index 3f6e7c7..d24f7d2 100644 --- a/libraries/README +++ b/libraries/README @@ -6,3 +6,6 @@ should go here to. Makes it easy to compile it all. Note that in some cases, there might be changes. Such changes should be documented. +luaproc has been hacked up a bit, and will continue to be hacked up. +Merging it into LuaSL, and converting it to EFL. + diff --git a/libraries/luajit-2.0/src/libluajit-5.1.so.2 b/libraries/luajit-2.0/src/libluajit-5.1.so.2 new file mode 120000 index 0000000..deaddec --- /dev/null +++ b/libraries/luajit-2.0/src/libluajit-5.1.so.2 @@ -0,0 +1 @@ +libluajit.so \ No newline at end of file diff --git a/libraries/luaproc/luaproc.c b/libraries/luaproc/luaproc.c index 2ec5b31..ff18723 100644 --- a/libraries/luaproc/luaproc.c +++ b/libraries/luaproc/luaproc.c @@ -114,6 +114,7 @@ static const struct luaL_reg luaproc_funcs_child[] = { { NULL, NULL } }; +/* static void registerlib( lua_State *L, const char *name, lua_CFunction f ) { lua_getglobal( L, "package" ); lua_getfield( L, -1, "preload" ); @@ -121,8 +122,9 @@ static void registerlib( lua_State *L, const char *name, lua_CFunction f ) { lua_setfield( L, -2, name ); lua_pop( L, 2 ); } - +*/ static void openlibs( lua_State *L ) { +/* lua_cpcall( L, luaopen_base, NULL ); lua_cpcall( L, luaopen_package, NULL ); registerlib( L, "io", luaopen_io ); @@ -131,6 +133,8 @@ static void openlibs( lua_State *L ) { registerlib( L, "string", luaopen_string ); registerlib( L, "math", luaopen_math ); registerlib( L, "debug", luaopen_debug ); +*/ + luaL_openlibs(L); } /* return status (boolean) indicating if lua process should be recycled */ @@ -195,7 +199,7 @@ int luaproc_recycle_push( luaproc lp ) { } /* create new luaproc */ -luaproc luaproc_new( const char *code, int destroyflag ) { +static luaproc luaproc_new( const char *code, int destroyflag, int file) { luaproc lp; int ret; @@ -218,7 +222,10 @@ luaproc luaproc_new( const char *code, int destroyflag ) { luaL_register( lpst, "luaproc", luaproc_funcs_child ); /* load process' code */ - ret = luaL_loadstring( lpst, code ); + if (file) + ret = luaL_loadfile( lpst, code ); + else + ret = luaL_loadstring( lpst, code ); /* in case of errors, destroy recently created lua process */ if ( ret != 0 ) { lua_close( lpst ); @@ -231,7 +238,7 @@ luaproc luaproc_new( const char *code, int destroyflag ) { /* synchronize worker threads and exit */ static int luaproc_exit( lua_State *L ) { - sched_join_workerthreads( ); + sched_join_workerthreads(); return 0; } @@ -297,7 +304,7 @@ static int luaproc_destroy_worker( lua_State *L ) { /* create new lua process with empty code and destroy worker flag set to true (ie, conclusion of lua process WILL result in worker thread destruction */ - lp = luaproc_new( "", TRUE ); + lp = luaproc_new( "", TRUE, FALSE ); /* ensure process creation was successfull */ if ( lp == NULL ) { @@ -328,7 +335,7 @@ static int luaproc_destroy_worker( lua_State *L ) { } /* recycle a lua process */ -luaproc luaproc_recycle( luaproc lp, const char *code ) { +static luaproc luaproc_recycle( luaproc lp, const char *code, int file ) { int ret; @@ -351,12 +358,9 @@ luaproc luaproc_recycle( luaproc lp, const char *code ) { return lp; } -/* create and schedule a new lua process (luaproc.newproc) */ -static int luaproc_create_newproc( lua_State *L ) { - - /* check if first argument is a string (lua code) */ - const char *code = luaL_checkstring( L, 1 ); +int newProc(const char *code, int file) +{ /* new lua process pointer */ luaproc lp; @@ -365,21 +369,18 @@ static int luaproc_create_newproc( lua_State *L ) { /* if there is a lua process available on the recycle queue, recycle it */ if ( lp != NULL ) { - lp = luaproc_recycle( lp, code ); + lp = luaproc_recycle( lp, code, file ); } /* otherwise create a new one from scratch */ else { /* create new lua process with destroy worker flag set to false (ie, conclusion of lua process will NOT result in worker thread destruction */ - lp = luaproc_new( code, FALSE ); + lp = luaproc_new( code, FALSE, file ); } /* ensure process creation was successfull */ if ( lp == NULL ) { - /* in case of errors return nil + error msg */ - lua_pushnil( L ); - lua_pushstring( L, "error loading code string" ); - return 2; + return 1; } /* increase active luaproc count */ @@ -392,6 +393,26 @@ static int luaproc_create_newproc( lua_State *L ) { sched_lpcount_dec(); /* close lua_State */ lua_close( lp->lstate ); + return 2; + } + + return 0; +} + +/* create and schedule a new lua process (luaproc.newproc) */ +static int luaproc_create_newproc( lua_State *L ) { + + /* check if first argument is a string (lua code) */ + const char *code = luaL_checkstring( L, 1 ); + + switch (newProc(code, FALSE)) + { + case 1 : + /* in case of errors return nil + error msg */ + lua_pushnil( L ); + lua_pushstring( L, "error loading code string" ); + return 2; + case 2 : /* return nil + error msg */ lua_pushnil( L ); lua_pushstring( L, "error queuing process" ); @@ -635,17 +656,24 @@ static int luaproc_receive( lua_State *L ) { } } -LUALIB_API int luaopen_luaproc( lua_State *L ) { - - /* register luaproc functions */ - luaL_register( L, "luaproc", luaproc_funcs_parent ); - +void luaprocInit(void) +{ /* initialize recycle list */ recyclelp = list_new(); /* initialize local scheduler */ sched_init_local( LUAPROC_SCHED_DEFAULT_WORKER_THREADS ); +} +void luaprocRegister(lua_State *L) +{ + /* register luaproc functions */ + luaL_register( L, "luaproc", luaproc_funcs_parent ); +} + +LUALIB_API int luaopen_luaproc( lua_State *L ) { + luaprocRegister(L); + luaprocInit(); return 0; } diff --git a/libraries/luaproc/luaproc.h b/libraries/luaproc/luaproc.h index 86617a9..4c71685 100644 --- a/libraries/luaproc/luaproc.h +++ b/libraries/luaproc/luaproc.h @@ -44,6 +44,11 @@ THE SOFTWARE. /* lua process pointer type */ typedef struct stluaproc *luaproc; +void luaprocInit(void); +void luaprocRegister(lua_State *L); +int newProc(const char *code, int file); + + /* return a process' status */ int luaproc_get_status( luaproc lp ); diff --git a/libraries/luaproc/sched.c b/libraries/luaproc/sched.c index f19beeb..474c82b 100644 --- a/libraries/luaproc/sched.c +++ b/libraries/luaproc/sched.c @@ -83,9 +83,11 @@ void *workermain( void *args ) { /* detach thread so resources are freed as soon as thread exits (no further joining) */ pthread_detach( pthread_self( )); +//printf("NEW WORKER\n"); /* main worker loop */ while ( 1 ) { +//printf("a\n"); /* get exclusive access to the ready process queue */ pthread_mutex_lock( &mutex_queue_access ); @@ -94,62 +96,83 @@ void *workermain( void *args ) { pthread_cond_wait( &cond_wakeup_worker, &mutex_queue_access ); } +////printf("b\n"); /* pop the first node from the ready process queue */ n = list_pop_head( lpready ); +////printf("c\n"); /* ensure list pop succeeded before proceeding */ if ( n != NULL ) { +//printf("c.0\n"); /* get the popped node's data content (ie, the lua process struct) */ lp = (luaproc )list_data( n ); } else { +////printf("c.1\n"); /* free access to the process ready queue */ pthread_mutex_unlock( &mutex_queue_access ); /* finished thread */ +//printf("c.2 pthread_exit\n"); pthread_exit( NULL ); +//printf("c.3\n"); } +////printf("d\n"); /* free access to the process ready queue */ pthread_mutex_unlock( &mutex_queue_access ); +//printf("e lua_resum\n"); /* execute the lua code specified in the lua process struct */ procstat = lua_resume( luaproc_get_state( lp ), luaproc_get_args( lp )); +//printf("f\n"); /* reset the process argument count */ luaproc_set_args( lp, 0 ); +////printf("g\n"); /* check if process finished its whole execution */ if ( procstat == 0 ) { +//printf("g.0\n"); /* destroy the corresponding list node */ list_destroy_node( n ); +////printf("g.1\n"); /* check if worker thread should be destroyed */ destroyworker = luaproc_get_destroyworker( lp ); +////printf("g.2 proc finished\n"); /* set process status to finished */ luaproc_set_status( lp, LUAPROC_STAT_FINISHED ); +////printf("g.3\n"); /* check if lua process should be recycled and, if not, destroy it */ if ( luaproc_recycle_push( lp ) == FALSE ) { +//printf("g.3.0 lua_close\n"); lua_close( luaproc_get_state( lp )); } +////printf("g.4\n"); /* decrease active lua process count */ sched_lpcount_dec(); +////printf("g.5\n"); /* check if thread should be finished after lua process conclusion */ if ( destroyworker ) { +//printf("g.5.0 pthread_exit\n"); /* if so, finish thread */ pthread_exit( NULL ); } +//printf("g.6\n"); } /* check if process yielded */ else if ( procstat == LUA_YIELD ) { +//printf("??????????????h.0\n"); /* if so, further check if yield originated from an unmatched send/recv operation */ if ( luaproc_get_status( lp ) == LUAPROC_STAT_BLOCKED_SEND ) { +//printf("??????????????h.1\n"); /* queue blocked lua process on corresponding channel */ luaproc_queue_sender( lp ); /* unlock channel access */ @@ -159,6 +182,7 @@ void *workermain( void *args ) { } else if ( luaproc_get_status( lp ) == LUAPROC_STAT_BLOCKED_RECV ) { +//printf("??????????????h.2\n"); /* queue blocked lua process on corresponding channel */ luaproc_queue_receiver( lp ); /* unlock channel access */ @@ -169,6 +193,7 @@ void *workermain( void *args ) { /* or if yield resulted from an explicit call to coroutine.yield in the lua code being executed */ else { +//printf("??????????????h.3\n"); /* get exclusive access to the ready process queue */ pthread_mutex_lock( &mutex_queue_access ); /* re-insert the job at the end of the ready process queue */ @@ -180,6 +205,7 @@ void *workermain( void *args ) { /* check if there was any execution error (LUA_ERRRUN, LUA_ERRSYNTAX, LUA_ERRMEM or LUA_ERRERR) */ else { +//printf("??????????????i.0\n"); /* destroy the corresponding node */ list_destroy_node( n ); /* print error message */ @@ -189,6 +215,7 @@ void *workermain( void *args ) { /* decrease active lua process count */ sched_lpcount_dec(); } +//printf("END\n"); } } @@ -260,29 +287,42 @@ int sched_queue_proc( luaproc lp ) { /* synchronize worker threads */ void sched_join_workerthreads( void ) { +////printf(" 0\n"); pthread_mutex_lock( &mutex_lp_count ); +//printf(" 1 wait for procs to end\n"); /* wait until there is no more active lua processes */ while( lpcount != 0 ) { +//printf(" 1.0\n"); pthread_cond_wait( &cond_no_active_lp, &mutex_lp_count ); } /* get exclusive access to the ready process queue */ +////printf(" 2\n"); pthread_mutex_lock( &mutex_queue_access ); /* set the no more active lua processes flag to true */ +////printf(" 3\n"); no_more_processes = TRUE; /* wake ALL workers up */ +//printf(" 4 wake up all workers.\n"); pthread_cond_broadcast( &cond_wakeup_worker ); /* free access to the process ready queue */ +////printf(" 5\n"); pthread_mutex_unlock( &mutex_queue_access ); + +// We don't need this, as we only get here during shutdown. Linking this to EFL results in a hang otherwise anyway. /* wait for (join) worker threads */ - pthread_exit( NULL ); +//printf(" 6 pthread_exit, waiting for workers to end\n"); +// pthread_exit( NULL ); +//printf("7\n"); pthread_mutex_unlock( &mutex_lp_count ); +//printf("8\n"); } /* increase active lua process count */ void sched_lpcount_inc( void ) { +//printf("inc procs++++++++++++++++++++++++++++++++++++++++\n"); pthread_mutex_lock( &mutex_lp_count ); lpcount++; pthread_mutex_unlock( &mutex_lp_count ); @@ -290,10 +330,12 @@ void sched_lpcount_inc( void ) { /* decrease active lua process count */ void sched_lpcount_dec( void ) { +//printf("dec procs----------------------------------------\n"); pthread_mutex_lock( &mutex_lp_count ); lpcount--; /* if count reaches zero, signal there are no more active processes */ if ( lpcount == 0 ) { +//printf("dec procs AND NONE LEFT000000000000000000000000000\n"); pthread_cond_signal( &cond_no_active_lp ); } pthread_mutex_unlock( &mutex_lp_count ); diff --git a/test.sh b/test.sh index f0da24e..9c6f58a 100755 --- a/test.sh +++ b/test.sh @@ -7,6 +7,8 @@ wd=$(pwd) ./build.sh || exit echo "_______________ TESTING LuaSL _______________" -cd $wd/LuaSL -./LuaSL +cd $wd/LuaSL/testLua +export LUA_SOPATH='../../libraries/luaproc/' +export LD_LIBRARY_PATH="../../libraries/luajit-2.0/src:$LD_LIBRARY_PATH" +../LuaSL -- cgit v1.1