diff options
Diffstat (limited to 'concurrency.c')
-rw-r--r-- | concurrency.c | 101 |
1 files changed, 40 insertions, 61 deletions
diff --git a/concurrency.c b/concurrency.c index 28cea35..9670866 100644 --- a/concurrency.c +++ b/concurrency.c @@ -1,13 +1,10 @@ #include <u.h> #include <libc.h> -#include <thread.h> #include <bio.h> +#include <tos.h> #include "apl9.h" -/* Nasty stuff to get stack size used */ -#include "/sys/src/libthread/threadimpl.h" - typedef struct SpawnData SpawnData; struct SpawnData { @@ -15,37 +12,40 @@ struct SpawnData Array *name; Array *left; Array *right; - Channel *setupdone; }; -static void newprocfn(void *); +static void newprocfn(SpawnData *); static ThreadData *newthreaddata(Array *); +extern void **_privates; + /* global data */ static Lock threadlock; static int nthreads; static ThreadData **threads; -int mainstacksize = STACKSIZE; -void -recvtimeout(void *raw) +int +recvtimeout(void *, char *note) { - ThreadData *td = (ThreadData *)raw; - if(0 == sleep(td->timeout)){ + if(strcmp(note, "alarm") != 0) + return 0; + + ThreadData *td = getthreaddata(); + if(rfork(RFPROC|RFMEM) == 0){ qlock(&td->lock); td->timedout = 1; rwakeup(&td->newmail); qunlock(&td->lock); + exits(nil); } + return 1; } void initthreads(void) { Array *name = mkrunearray(L"main"); - ThreadData *td = newthreaddata(name); - void **tdptr = procdata(); - *tdptr = td; + _privates[0] = newthreaddata(name); freearray(name); } @@ -64,25 +64,25 @@ spawnthread(Function f, Array *name, Array *left, Array *right) unlock datastructures exit proc */ - Channel *setupdone = chancreate(sizeof(int), 0); SpawnData *sp = emalloc(sizeof(SpawnData)); sp->func = dupfunction(f); sp->func.scope = dupscope(f.scope); sp->name = duparray(name); sp->left = left ? duparray(left) : nil; sp->right = duparray(right); - sp->setupdone = setupdone; - int id = proccreate(newprocfn, sp, STACKSIZE); - recv(setupdone, nil); /* wait for new proc to signal that the setup is done */ - chanfree(setupdone); + + int id = rfork(RFPROC|RFMEM); + if(id == 0){ /* in new process*/ + newprocfn(sp); + exits(nil); + } return id; } ThreadData * getthreaddata(void) { - void **tdptr = procdata(); - return (ThreadData *)*tdptr; + return (ThreadData *)_privates[0]; } void @@ -122,11 +122,10 @@ messagerecv(Function match, int timeout) qlock(&td->lock); /* Start a "timeout thread" if needed */ - int timeoutid = 0; td->timedout = 0; /* clear the timeout bit */ if(timeout > 0){ - td->timeout = timeout; - timeoutid = proccreate(recvtimeout, td, STACKSIZE); + atnotify(recvtimeout, 1); + alarm(timeout); } /* Wait for a message, or timeout */ @@ -166,8 +165,10 @@ Retry: } /* We found a match, remove the mail from the mailbox, and kill the timeout */ - if(timeout > 0) - threadkill(timeoutid); + if(timeout > 0){ + atnotify(recvtimeout, 0); + alarm(0); + } if(td->mail == m) td->mail = m->next; else{ @@ -186,20 +187,15 @@ Retry: } static void -newprocfn(void *data) +newprocfn(SpawnData *sp) { - SpawnData *sp = (SpawnData *)data; ThreadData *td = newthreaddata(sp->name); - void **tdptr = procdata(); - *tdptr = td; + _privates[0] = td; ErrorGuard *eg = newerrorguard(mkscalarint(0), nil); /* make a catch-all error guard */ if(setjmp(eg->jmp)) displayerror(); - else{ - int done = 1; - send(sp->setupdone, &done); + else runfunc(sp->func, sp->left, sp->right); - } lock(&threadlock); for(int i = 0; i < nthreads; i++){ if(threads[i] != td) @@ -219,14 +215,15 @@ newprocfn(void *data) freefunction(sp->func); free(sp); free(td); + exits(nil); } static ThreadData * newthreaddata(Array *name) { ThreadData *td = emallocz(sizeof(ThreadData), 1); - td->id = threadid(); - td->requiredstack = REQUIREDSTACK; + td->id = getpid(); + td->stackused = 0; td->currentdfn = nil; td->mail = 0; td->lastmail = 0; @@ -240,6 +237,7 @@ newthreaddata(Array *name) threads = erealloc(threads, sizeof(ThreadData *) * nthreads); threads[nthreads-1] = td; unlock(&threadlock); + return td; } @@ -275,19 +273,16 @@ threadproperty(vlong t, vlong p) case 1: /* thread name */ res = fnSame(td->name); break; - case 2: /* stacksize max */ - res = mkscalarint(STACKSIZE); - break; - case 3: /* used stacksize */ - res = mkscalarint(stackused()); - break; - case 4: /* messages in mailbox */ + case 2: /* messages in mailbox */ qlock(&td->lock); for(Mail *tmp = td->mail; tmp != nil; tmp = tmp->next) mailcount++; qunlock(&td->lock); res = mkscalarint(mailcount); break; + case 3: /* used stacksize */ + res = mkscalarint(td->stackused); + break; default: unlock(&threadlock); throwerror(L"Invalid thread property", EDomain); @@ -298,25 +293,9 @@ threadproperty(vlong t, vlong p) return res; } -int -stackused(void) -{ - int x; - Proc *p = _threadgetproc(); - Thread *t = p->thread; - return STACKSIZE - ((uchar*)&x - (uchar*)t->stk); -} - -int -hasstack(int n) -{ - return (n+stackused()) < STACKSIZE; -} - void -checkstack(void) +stackusage(void) { ThreadData *td = getthreaddata(); - if(!hasstack(td->requiredstack)) - throwerror(L"Not enough C stack. Stuff will go bad from now on.", EStack); + td->stackused = ((uchar*)_tos - (uchar *)&td); }
\ No newline at end of file |