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:
rsc 2004-09-17 00:38:29 +00:00
parent 984e353160
commit 06bb4ed20d
15 changed files with 205 additions and 218 deletions

View file

@ -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);
}