# HG changeset patch # User Mike Pavone # Date 1290283405 0 # Node ID c14698c512f1ab8867c1d6a597a65837c5a2d183 # Parent a68e6828d8960a12deb98f829a8c34f1e2058474 Untested addition of Pause/Resume diff -r a68e6828d896 -r c14698c512f1 cbackend_c.rhope --- a/cbackend_c.rhope Fri Nov 19 04:04:14 2010 -0500 +++ b/cbackend_c.rhope Sat Nov 20 20:03:25 2010 +0000 @@ -1509,14 +1509,14 @@ { out <- [[[[["typedef enum {\n" ]Append[Fold[_Dispatch Enum[?], - [Fold[_Dispatch Enum Methods[[program]Escape Pattern >>,?], "", all methods]]Append["\tFUNC_Build,\n\tFUNC_BlueprintSP_Of,\n\tFUNC_ID,\n\tFUNC_BlueprintSP_FromSP_ID,\n"], + [Fold[_Dispatch Enum Methods[[program]Escape Pattern >>,?], "", all methods]]Append["\tFUNC_Build,\n\tFUNC_BlueprintSP_Of,\n\tFUNC_ID,\n\tFUNC_BlueprintSP_FromSP_ID,\n\tFUNC_Pause,\n\tRES_1_Pause,\n\tFUNC_Resume,\n\tFUNC_CallSP_Async,\n"], [program]Functions >>]] - ]Append["\tEND\n} funcids;\n\n"] + ]Append["\tEND,\n\tEND_THREAD\n} funcids;\n\n"] ]Append["#define DispatchEntries \\\n"] ]Append[Fold[_Dispatch Switch[?], - [Fold[_Dispatch Switch Methods[[program]Escape Pattern >>,?], "", all methods]]Append["\tDispatchEntry(Build)\\\n\tDispatchEntry(BlueprintSP_Of)\\\n\tDispatchEntry(ID)\\\n\tDispatchEntry(BlueprintSP_FromSP_ID)\\\n"], + [Fold[_Dispatch Switch Methods[[program]Escape Pattern >>,?], "", all methods]]Append["\tDispatchEntry(Build)\\\n\tDispatchEntry(BlueprintSP_Of)\\\n\tDispatchEntry(ID)\\\n\tDispatchEntry(BlueprintSP_FromSP_ID)\\\n\tDispatchEntry(Pause)\\\n\tResumeEntry(1,Pause)\\\n\tDispatchEntry(Resume)\\\n\tDispatchEntry(CallSP_Async)\\\n"], [program]Functions >>]] - ]Append["\tEndEntry\n\n"] + ]Append["\tEndEntry\n\tEndThreadEntry\n\n"] } Not Native[func:out] @@ -1633,14 +1633,17 @@ struct timeval time; #endif uint16_t resume,idx, vcparam_offset, last_vcparam; - context * ct; + context *ct,*temp_ct; void *tmp; calldata * cdata, *temp_cdata, *my_cdata; DispatchVar FuncDef(Build) FuncDef(BlueprintSP_Of) FuncDef(ID) - FuncDef(BlueprintSP_FromSP_ID)\n"] + FuncDef(BlueprintSP_FromSP_ID) + FuncDef(Pause) + FuncDef(Resume) + FuncDef(CallSP_Async)\n"] ]Append[Fold[Local Pointers[?], "", [program]Functions >>]] ]Append[" ct = new_context(); @@ -1702,6 +1705,89 @@ } EndFunc(BlueprintSP_FromSP_ID) +DISPATCH + +FuncNoLocals(Pause, NumParams 1) + Param(0, TYPE_WORKER) + + ct->resume_cdata = my_cdata; + ct->resumeable = 1; + temp_ct = ct; + ct = new_context(); + VCPrepCall(my_cdata->params[0], 1) + VCSetParam(my_cdata->params[0], 0, make_Context(temp_ct)) + ValCall(my_cdata->params[0], 1, 1, Pause) + release_ref(my_cdata->params[0]); + DISPATCH + ValCallPostlude(1, Pause) + for(idx = 0; idx < cdata->num_params; ++idx) + { + release_ref(cdata->params[idx]); + } + free_context(ct); + ct = get_cqueue(); + if (!ct) goto NOTHING_TO_DO; + cdata = ct->resume_cdata; + ct->resume_data = NULL; + if(ct->start_func >= 0) + { + func = ct->start_func; + ct->start_func = -1; + DISPATCH + } +EndFuncNoLocals(Pause) +DISPATCH + +FuncNoLocals(Resume, NumParams 2) + Param(0, TYPE_CONTEXT) + + temp_ct = ((t_Context *)my_cdata->params[0])->ct; + release_ref(my_cdata->params[0]); + if(temp_ct->resumeable && temp_ct->resume_cdata) + { + temp_ct->resumeable = 0; + temp_ct->resume_cdata->params[0] = add_ref(my_cdata-params[1]); + my_cdata->params[0] = my_cdata->params[1]; + my_cdata->params[1] = NULL; + if(!put_cqueue(temp_ct)) + { + ct->resume_cdata = my_cdata; + temp_ct->runafter = ct; + ct = temp_ct; + cdata = ct->resume_cdata; + ct->resume_cdata = NULL; + } + } else { + my_cdata->params[0] = NULL; + } +EndFuncNoLocals(Resume) +DISPATCH + +FuncNoLocals(CallSP_Async, NumParams 1) + Param(0, TYPE_WORKER) + + temp_ct = new_context(); + cdata = alloc_cdata(temp_ct, NULL, ((t_Worker *)my_cdata->params[0])->payload.Size); + cdata->func = END_THREAD; + for(idx = 0; idx < ((t_Worker *)my_cdata->params[0])->payload.Size; ++idx) + { + cdata->params[idx] = add_ref(((object **)(((t_Worker *)my_cdata->params[0])+1))[idx]); + } + temp_ct->start_func = ((t_Worker *)my_cdata->params[0])->payload.Index; + temp_ct->resume_cdata = cdata; + if(put_cqueue(temp_ct)) + { + cdata = my_cdata; + } else { + ct->resume_cdata = my_cdata; + temp_ct->runafter = ct; + ct = temp_ct; + ct->resume_cdata = NULL; + func = ct->start_func; + ct->start_func = -1; + DISPATCH + } +EndFuncNoLocals(CallSP_Async) DISPATCH\n"] ]Append[Fold[_Text C Program[?, ?, [program]Type Registry >>], "", Filter[[program]Functions >>, Native[?]]]] ]Append[" @@ -1711,9 +1797,34 @@ free_context(ct); return cdata->num_params; +DO_END_THREAD: + for(idx = 0; idx < cdata->num_params; ++idx) + { release_ref(cdata->params[idx]); } + if(ct->runafter) + { + temp_ct = ct; + ct = ct->runafter; + free_context(temp_ct); + cdata = ct->resume_cdata; + func = cdata->func; + DISPATCH + } + free_context(ct); + if(ct = get_cqueue()) + { + cdata = ct->resume_cdata; + if(ct->start_func >= 0) + func = ct->start_func; + else + func = cdata->func; + DISPATCH + } +NOTHING_TO_DO: + return 0; + _exception: puts(\"Exception! Trace follows:\"); - while(cdata && cdata->func != END) + while(cdata && cdata->func < END) { printf(\"%d\\n\", cdata->func); cdata = cdata->lastframe; diff -r a68e6828d896 -r c14698c512f1 nworker_c.rhope --- a/nworker_c.rhope Fri Nov 19 04:04:14 2010 -0500 +++ b/nworker_c.rhope Sat Nov 20 20:03:25 2010 +0000 @@ -1601,13 +1601,16 @@ Register Builtins@NProgram[prog:out] { - registered <- [[[[[[[[prog]Register Worker["Print", "rhope", 1, 1] + registered <- [[[[[[[[[[[prog]Register Worker["Print", "rhope", 1, 1] ]Register Worker["If@Boolean", "rhope", 1, 2] ]Register Worker["Build", "rhope", 1, 1] ]Register Worker["Blueprint Of", "rhope", 1, 1] ]Register Worker["Call@Worker", "rhope", 1, 2] //We're using 2 because we need to assume that the outputs are conditional ]Register Worker["ID", "rhope", 1, 1] ]Register Worker["Blueprint From ID", "rhope", 1, 2] + ]Register Worker["Pause", "rhope", 1, 1] + ]Register Worker["Resume", "rhope", 2, 2] + ]Register Worker["Call Async", "rhope", 1, 1] ]Register Number Methods out <- [[[[[[[registered]Bind Worker["If@Boolean", diff -r a68e6828d896 -r c14698c512f1 runtime/builtin.c --- a/runtime/builtin.c Fri Nov 19 04:04:14 2010 -0500 +++ b/runtime/builtin.c Sat Nov 20 20:03:25 2010 +0000 @@ -17,6 +17,8 @@ case TYPE_BLUEPRINT: bp = register_type_byid(TYPE_BLUEPRINT, sizeof(blueprint *), NULL, NULL, NULL); break; + case TYPE_CONTEXT: + register_type_byid(TYPE_CONTEXT, sizeof(context *), NULL, NULL, NULL); } } diff -r a68e6828d896 -r c14698c512f1 runtime/builtin.h --- a/runtime/builtin.h Fri Nov 19 04:04:14 2010 -0500 +++ b/runtime/builtin.h Sat Nov 20 20:03:25 2010 +0000 @@ -26,6 +26,7 @@ TYPE_FIELDMISSINGEXCEPTION, TYPE_WRONGTYPEEXCEPTION, TYPE_MUTABLEGLOBAL, + TYPE_CONTEXT, TYPE_FIRST_USER //Insert new builtin types before this one }; diff -r a68e6828d896 -r c14698c512f1 runtime/context.c --- a/runtime/context.c Fri Nov 19 04:04:14 2010 -0500 +++ b/runtime/context.c Sat Nov 20 20:03:25 2010 +0000 @@ -1,9 +1,49 @@ #include "context.h" #include "object.h" +#include "thread.h" #include #include #include +context * contextqueue[32]; +int32_t cq_readloc=0; +int32_t cq_writeloc=0; +rh_mutex(cq_lock) + +void cqueue_init() +{ + rh_mutex_init(cq_lock); +} + +context * get_cqueue() +{ + context * ret; + rh_lock(cq_lock); + if (cq_readloc == cq_writeloc) + { + rh_unlock(cq_lock); + return NULL; + } + ret = contextqueue[cq_readloc++]; + if (cq_readloc == 32) + cq_readloc = 0; + rh_unlock(cq_lock); + return ret; +} + +int32_t put_cqueue(context * ct) +{ + rh_lock(cq_lock); + if ((cq_writeloc+1)&31 == cq_readloc) + { + rh_unlock(cq_lock); + return 0; + } + contextqueue[cq_writeloc++] = ct; + rh_unlock(cq_lock); + return 1; +} + stackchunk * new_stack() { stackchunk * st = malloc(sizeof(stackchunk)); @@ -18,7 +58,9 @@ context * c = malloc(sizeof(context)); c->stack_begin = new_stack(); c->current_stack = c->stack_begin; - c->transaction = NULL; + c->resume_cdata = c->runafter = c->transaction = NULL; + c->resumeable = 0; + c->start_func = -1; return c; } diff -r a68e6828d896 -r c14698c512f1 runtime/context.h --- a/runtime/context.h Fri Nov 19 04:04:14 2010 -0500 +++ b/runtime/context.h Sat Nov 20 20:03:25 2010 +0000 @@ -16,15 +16,23 @@ } stackchunk; typedef struct context { - stackchunk *stack_begin; - stackchunk *current_stack; - transaction *transaction; + stackchunk *stack_begin; + stackchunk *current_stack; + transaction *transaction; + struct context *runafter; + calldata *resume_cdata; + int32_t resumeable; + int32_t start_func; } context; +Box(context *,ct,Context); stackchunk * new_stack(); context * new_context(); void * alloc_stack(context * ct, uint32_t size); calldata * alloc_cdata(context * ct, calldata * lastframe, uint32_t num_params); void free_stack(context * ct, void * data); void free_context(context * c); +void cqueue_init(); +context * get_cqueue(); +int32_t put_cqueue(context * ct); #endif //_CONTEXT_H_ diff -r a68e6828d896 -r c14698c512f1 runtime/func.h --- a/runtime/func.h Fri Nov 19 04:04:14 2010 -0500 +++ b/runtime/func.h Sat Nov 20 20:03:25 2010 +0000 @@ -22,12 +22,14 @@ #define DispatchVar #define DISPATCH switch(func) { DispatchEntries } #define EndEntry case END: goto DO_END; +#define EndThreadEntry case END_THREAD: goto DO_END_THREAD; #else #define DispatchEntry(name) &&f_##name, #define ResumeEntry(num,name) &&r##num##_##name, #define DispatchVar void * funcs[] = { DispatchEntries }; #define DISPATCH goto *funcs[func]; #define EndEntry &&DO_END +#define EndThreadEntry &&DO_END_THREAD; #endif diff -r a68e6828d896 -r c14698c512f1 testpauseresume.rhope --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testpauseresume.rhope Sat Nov 20 20:03:25 2010 +0000 @@ -0,0 +1,20 @@ + +Yield[:out] +{ + out <- Pause[Resume[?,0]] +} + +Foo[:out] +{ + Print["Foo!"] +} + +Main[:out] +{ + Call Async[Foo[?]] + { Call Async[Foo[?]] + { Call Async[Foo[?]] + { Get Char[] + { out <- Yield[] } +} +