|
hi,
it would not work for coroutines
if there is more than one level of coroutine, i don't see a simple solution
with only one this seems to work ( with the issue that hook count is
not global ) :
#include <lua.h>
#include <lauxlib.h>
#include "src/lstate.h"
lua_State* resume_thread;
int resume_main;
void hookFunc(lua_State *L, lua_Debug *ar) {
lua_State* M = L->l_G->mainthread;
if(L != M) {
if(resume_thread == M)
resume_thread = L;
M->hookcount = 1;
}
resume_main = 0;
lua_yield(L, 0);
}
int main() {
lua_State *L1, *L2, *N1, *N2;
L1 = luaL_newstate();
L2 = luaL_newstate();
luaL_openlibs(L1);
luaL_openlibs(L2);
lua_sethook(L1, hookFunc, LUA_MASKCOUNT, 500);
lua_sethook(L2, hookFunc, LUA_MASKCOUNT, 500);
luaL_loadstring(L1, "function co() while true do for i=1,100 do
print('B') end coroutine.yield() end end"
" c = coroutine.create(co) coroutine.resume(c)"
" while true do for i=1,70 do print('A') end
coroutine.resume(c) end");
luaL_loadstring(L2, "while true do print('C') end");
N1 = L1;
N2 = L2;
for(;;)
{
resume_main = 1;
resume_thread = L1;
lua_resume(N1, NULL, 0);
if(N1 != L1 && resume_main) lua_resume(L1, NULL, 0);
N1 = resume_thread;
resume_main = 1;
resume_thread = L2;
lua_resume(N2, NULL, 0);
if(N2 != L2 && resume_main) lua_resume(L2, NULL, 0);
N2 = resume_thread;
}
}
/*
% ./a.out | uniq -c | head
100 B
70 A
21 B
125 C
79 B
70 A
44 B
125 C
56 B
70 A
*/
nicolas.
>> caller--which
On 3/31/14, Milind Gupta <milind.gupta@gmail.com> wrote:
> Here is a crude round robin schedules I had tried but had not tried
> coroutines in the lua code. This scheme is working good for me:
>
> #include <stdio.h>
> #include <string.h>
> #include "lua.h"
> #include "lualib.h"
> #include "lauxlib.h"
>
>
> int flag = 0;
> lua_State *luaVM1, *luaVM2, *thread1, *thread2;
> int hookFunc(lua_State *L, lua_Debug *dbg);
>
> int main(int argc, char* argv[ ])
> {
> luaVM1 = luaL_newstate();
> luaVM2 = luaL_newstate();
>
> luaL_openlibs(luaVM1);
> luaL_openlibs(luaVM2);
>
> thread1 = lua_newthread(luaVM1);
> thread2 = lua_newthread(luaVM2);
>
> if (NULL == luaVM1 || NULL == luaVM2)
> {
> printf("Error Initializing lua\n");
> return -1;
> }
> char* prog1 = "for i = 1,5 do print('x'..tostring(i)) a=io.read()
> print(a) end";
> char* prog2 = "for i = 1,10 do print('y'..tostring(i)) end";
> // Create threads in each lua state
> // Now push the function into the stack of each thread
> luaL_loadstring(thread1,prog1);
> luaL_loadstring(thread2,prog2);
> lua_sethook(thread1,(lua_Hook) hookFunc,LUA_MASKCOUNT,4);
> lua_sethook(thread2,(lua_Hook) hookFunc,LUA_MASKCOUNT,4);
>
> lua_resume(thread1,0);
> flag=1;
> lua_resume(thread2,0);
> while(lua_status(thread1) || lua_status(thread2))
> {
> if (flag==0)
> {
> flag = 1;
> if (lua_status(thread2))
> lua_resume(thread2,0);
> }
> else
> {
> flag = 0;
> if (lua_status(thread1))
> lua_resume(thread1,0);
> }
> }
>
>
> lua_close( luaVM1 );
> lua_close( luaVM2 );
>
> return 0;
> }
>
> int hookFunc(lua_State *L, lua_Debug *dbg)
> {
> printf("Hook Called\n");
> if(flag==0)
> {
> printf("Flag0\n");
> return lua_yield(thread1,0);
> }
> else
> {
> printf("flag1\n");
> return lua_yield(thread2,0);
> }
> return 0;
> }
>
>
>
> On Mon, Mar 31, 2014 at 7:53 AM, Milind Gupta
> <milind.gupta@gmail.com>wrote:
>
>> I have my debug hook function as int and don't have issues although I
>> don't use coroutines. Here is an excerpt from Programming in Lua 2nd
>> Edition in the Threads chapter:
>>
>> "
>> Standard Lua cannot yield across C function calls. This restriction
>> implies
>> that a C function cannot suspend itself. The only way for a C function to
>> yield is
>> when returning, so that it actually does not suspend itself, but its
>> should be a Lua function. To suspend its caller, a C function must call>>> *From:* lua-l-bounces@lists.lua.org [mailto:lua-l-bounces@lists.lua.org]
>> lua_yield
>> in the following way:
>> return lua_yield(L, nres);
>> "
>>
>>
>> On Mon, Mar 31, 2014 at 7:46 AM, Dominique Torette <
>> Dominique.Torette@spacebel.be> wrote:
>>
>>> From 'lua.h', debug hooks are void functions:
>>>
>>>
>>>
>>> typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
>>>
>>>
>>>
>>> Regards, Dominique.
>>>
>>>
>>>
>>> *On
>>> Behalf Of *Milind Gupta
>>> *Sent:* lundi 31 mars 2014 16:34
>>> *To:* Lua mailing list
>>> *Subject:* Re: Pre-emptive round robin scheduler around Lua VM
>>>>>> for this number of instructions and so on...
>>>
>>>
>>> Hi,
>>>
>>> One thing I have seen in the Programming in Lua book is that
>>> the Hook function in C should always have a yield in the return
>>> statement
>>> so the debug_hook function should not be void and the last statement
>>> should
>>> be return lua_yield. Does that get rid of the interactions?
>>>
>>> Regards,
>>> Milind
>>>
>>>
>>>
>>> On Mon, Mar 31, 2014 at 7:03 AM, Dominique Torette <
>>> Dominique.Torette@spacebel.be> wrote:
>>>
>>> Hi,
>>>
>>>
>>>
>>> I'm trying to build a kind of pre-emptive scheduler around Lua VM 5.2.
>>>
>>> The idea is to execute different lua_State in "parallel'.
>>>
>>> To give the illusion of parallelism, the idea is to run a thread for a
>>> given number of Lua VM instructions and then run the next thread in a
>>> list
>>>>>> "interferences"...
>>> From the LUA regular API, when starting the execution of a thread, it is
>>> not possible to control the number of Lua VM instructions to execute.
>>>
>>> But from the LUA debug API, it is possible to define a 'hook' to execute
>>> every COUNT of instructions.
>>>
>>> The first idea was to install such hook and perform the round-robin
>>> scheduling from the hook. The lua_State of active thread seems to be
>>> saved
>>> before running such hook.
>>>
>>> But I didn't found any means to overwrite the thread to be resumed from
>>> the hook.
>>>
>>> Then the idea was to 'yield' from the hook, back to the round robin
>>> scheduler.
>>>
>>> This seems to work in the simplest cases. But I've noticed some strange
>>> "intereferences" when thread use coroutines on its own.
>>>
>>>
>>>
>>> The Lua resume API has a 'from' parameter: int lua_resume (lua_State *L,
>>> lua_State *from, int nargs);
>>>
>>> But from the description, I didn't catch the how this param has to be
>>> used.
>>>
>>>
>>>
>>> I've written a small "C" main program to illustrate the concept and the
>>> *Dominique Torette*>>>
>>> In the program here below, the first iteration of the loop works as
>>> expected.
>>>
>>> Then the L[0] and its coroutine are resumed, but the hook is reached
>>> faster than for the first iteration and the L[1] is rescheduled.
>>>
>>> After L[0] will be never rescheduled, only L[1].
>>>
>>>
>>>
>>> Thanks in advance, Dominique Torette.
>>>
>>>
>>>
>>> #include "lua.h"
>>>
>>> #include "lauxlib.h"
>>>
>>> #include "lualib.h"
>>>
>>> #include "lstate.h"
>>>
>>> #include <stdio.h>
>>>
>>> #include <setjmp.h>
>>>
>>>
>>>
>>>
>>>
>>> lua_State* L[2];
>>>
>>> lua_State* S[2];
>>>
>>> int current;
>>>
>>> int previous;
>>>
>>>
>>>
>>> void debug_hook (lua_State *X, lua_Debug *ar)
>>>
>>> {
>>>
>>>
>>>
>>> printf("In debug_hook\n");
>>>
>>> if((X->l_G)->mainthread != X)
>>>
>>> {
>>>
>>> printf("from coroutine \n");
>>>
>>> }
>>>
>>> S[current] = X;
>>>
>>> current = (current+1)%2;
>>>
>>> lua_yield ((X->l_G)->mainthread,0);
>>>
>>> }
>>>
>>>
>>>
>>> int main(int argc, char * argv)
>>>
>>> {
>>>
>>> int status;
>>>
>>>
>>>
>>> L[0] = luaL_newstate();
>>>
>>> luaL_openlibs(L[0]);
>>>
>>>
>>>
>>> luaL_loadstring(L[0], "co = coroutine.create(function () while
>>> true do print('hi') coroutine.yield() end end) while true do
>>> print('hello')
>>> coroutine.resume(co) end");
>>>
>>> lua_sethook (L[0],debug_hook,LUA_MASKCOUNT,500);
>>>
>>>
>>>
>>> L[1] = luaL_newstate();
>>>
>>> luaL_openlibs(L[1]);
>>>
>>> luaL_loadstring(L[1], "while true do print('world') end");
>>>
>>> lua_sethook (L[1],debug_hook,LUA_MASKCOUNT,500);
>>>
>>>
>>>
>>> current = 0;
>>>
>>> S[0] = L[0];
>>>
>>> S[1] = L[1];
>>>
>>> for(;;)
>>>
>>> {
>>>
>>> printf("Resume 1\n");
>>>
>>> status = lua_resume (S[0],L[0],0);
>>>
>>> printf("status 1 %d\n",status);
>>>
>>> printf("Resume 2\n");
>>>
>>> status = lua_resume (S[1],L[1],0);
>>>
>>> printf("status 2 %d\n",status);
>>>
>>> printf("Reloop\n");
>>>
>>> }
>>>
>>> }
>>>
>>>
>>>
>>>
>>>
>>>
>>> [image:
>>> http://www.spacebel.be/wp-content/uploads/2011/06/image-sign-sbp.jpg]
>>>
>>> System Architect
>>> Rue des Chasseurs Ardennais - Liège Science Park - B-4031 Angleur
>>> Tel: +32 (0) 4 361 81 11 - Fax: +32 (0) 4 361 81 20
>>> www.spacebel.be
>>>
>>>
>>>
>>>
>>>
>>> ------------------------------------------------------------------------------
>>>
>>> E-MAIL DISCLAIMER
>>>
>>> The present message may contain confidential and/or legally privileged
>>> information. If you are not the intended addressee and in case of a
>>> transmission error, please notify the sender immediately and destroy
>>> this
>>> E-mail. Disclosure, reproduction or distribution of this document and
>>> its
>>> possible attachments is strictly forbidden.
>>>
>>> SPACEBEL denies all liability for incomplete, improper, inaccurate,
>>> intercepted, (partly) destroyed, lost and/or belated transmission of the
>>> current information given that unencrypted electronic transmission
>>> cannot
>>> currently be guaranteed to be secure or error free.
>>> Upon request or in conformity with formal, contractual agreements, an
>>> originally signed hard copy will be sent to you to confirm the
>>> information
>>> contained in this E-mail.
>>>
>>> SPACEBEL denies all liability where E-mail is used for private use.
>>>
>>> SPACEBEL cannot be held responsible for possible viruses that might
>>> corrupt this message and/or your computer system.
>>>
>>> -------------------------------------------------------------------------------
>>>
>>>
>>>
>>>
>>> ------------------------------------------------------------------------------
>>>
>>> E-MAIL DISCLAIMER
>>>
>>> The present message may contain confidential and/or legally privileged
>>> information. If you are not the intended addressee and in case of a
>>> transmission error, please notify the sender immediately and destroy
>>> this
>>> E-mail. Disclosure, reproduction or distribution of this document and
>>> its
>>> possible attachments is strictly forbidden.
>>>
>>> SPACEBEL denies all liability for incomplete, improper, inaccurate,
>>> intercepted, (partly) destroyed, lost and/or belated transmission of the
>>> current information given that unencrypted electronic transmission
>>> cannot
>>> currently be guaranteed to be secure or error free.
>>> Upon request or in conformity with formal, contractual agreements, an
>>> originally signed hard copy will be sent to you to confirm the
>>> information
>>> contained in this E-mail.
>>>
>>> SPACEBEL denies all liability where E-mail is used for private use.
>>>
>>> SPACEBEL cannot be held responsible for possible viruses that might
>>> corrupt this message and/or your computer system.
>>>
>>> -------------------------------------------------------------------------------
>>>
>>
>>
>