Rewrite to remove dependence on rendezvous and its bizarre
data structures. Makes it easier to use pthreads too. Still need to add code for non-pthreads systems. Just a checkpoint to switch work to another machine.
This commit is contained in:
parent
984e353160
commit
06bb4ed20d
15 changed files with 205 additions and 218 deletions
|
|
@ -1,104 +1,38 @@
|
|||
#include "threadimpl.h"
|
||||
|
||||
Rgrp _threadrgrp;
|
||||
static int isdirty;
|
||||
int _threadhighnrendez;
|
||||
int _threadnrendez;
|
||||
static int nrendez;
|
||||
|
||||
static ulong
|
||||
finish(Thread *t, ulong val)
|
||||
void
|
||||
_threadsleep(_Procrend *r)
|
||||
{
|
||||
ulong ret;
|
||||
Thread *t;
|
||||
|
||||
ret = t->rendval;
|
||||
t->rendval = val;
|
||||
t = _threadgetproc()->thread;
|
||||
r->arg = t;
|
||||
t->nextstate = Rendezvous;
|
||||
t->inrendez = 1;
|
||||
unlock(r->l);
|
||||
_sched();
|
||||
t->inrendez = 0;
|
||||
lock(r->l);
|
||||
}
|
||||
|
||||
void
|
||||
_threadwakeup(_Procrend *r)
|
||||
{
|
||||
Thread *t;
|
||||
|
||||
t = r->arg;
|
||||
while(t->state == Running)
|
||||
sleep(0);
|
||||
lock(&t->proc->lock);
|
||||
if(t->state == Rendezvous){ /* not always true: might be Dead */
|
||||
t->state = Ready;
|
||||
_threadready(t);
|
||||
if(t->state == Dead){
|
||||
unlock(&t->proc->lock);
|
||||
return;
|
||||
}
|
||||
assert(t->state == Rendezvous && t->inrendez);
|
||||
t->state = Ready;
|
||||
_threadready(t);
|
||||
unlock(&t->proc->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ulong
|
||||
_threadrendezvous(ulong tag, ulong val)
|
||||
{
|
||||
ulong ret;
|
||||
Thread *t, **l;
|
||||
|
||||
lock(&_threadrgrp.lock);
|
||||
_threadnrendez++;
|
||||
l = &_threadrgrp.hash[tag%nelem(_threadrgrp.hash)];
|
||||
for(t=*l; t; l=&t->rendhash, t=*l){
|
||||
if(t->rendtag==tag){
|
||||
_threaddebug(DBGREND, "Rendezvous with thread %d.%d", t->proc->pid, t->id);
|
||||
*l = t->rendhash;
|
||||
ret = finish(t, val);
|
||||
--nrendez;
|
||||
unlock(&_threadrgrp.lock);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Going to sleep here. */
|
||||
t = _threadgetproc()->thread;
|
||||
t->rendbreak = 0;
|
||||
t->inrendez = 1;
|
||||
t->rendtag = tag;
|
||||
t->rendval = val;
|
||||
t->rendhash = *l;
|
||||
*l = t;
|
||||
++nrendez;
|
||||
if(nrendez > _threadhighnrendez)
|
||||
_threadhighnrendez = nrendez;
|
||||
_threaddebug(DBGREND, "Rendezvous for tag %lud (m=%d)", t->rendtag, t->moribund);
|
||||
unlock(&_threadrgrp.lock);
|
||||
t->nextstate = Rendezvous;
|
||||
_sched();
|
||||
t->inrendez = 0;
|
||||
_threaddebug(DBGREND, "Woke after rendezvous; val is %lud", t->rendval);
|
||||
return t->rendval;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called while holding _threadpq.lock and p->lock,
|
||||
* so we can't lock _threadrgrp.lock. Instead our caller has
|
||||
* to call _threadbreakrendez after dropping those locks.
|
||||
*/
|
||||
void
|
||||
_threadflagrendez(Thread *t)
|
||||
{
|
||||
t->rendbreak = 1;
|
||||
isdirty = 1;
|
||||
}
|
||||
|
||||
void
|
||||
_threadbreakrendez(void)
|
||||
{
|
||||
int i;
|
||||
Thread *t, **l;
|
||||
|
||||
if(isdirty == 0)
|
||||
return;
|
||||
lock(&_threadrgrp.lock);
|
||||
if(isdirty == 0){
|
||||
unlock(&_threadrgrp.lock);
|
||||
return;
|
||||
}
|
||||
isdirty = 0;
|
||||
for(i=0; i<nelem(_threadrgrp.hash); i++){
|
||||
l = &_threadrgrp.hash[i];
|
||||
for(t=*l; t; t=*l){
|
||||
if(t->rendbreak){
|
||||
*l = t->rendhash;
|
||||
finish(t, ~0);
|
||||
}else
|
||||
l=&t->rendhash;
|
||||
}
|
||||
}
|
||||
unlock(&_threadrgrp.lock);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue