mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-15 11:20:03 +00:00
912fba95e7
which were completely bogus. (Libthread used to ignore them but not anymore. Maybe we really should ignore them, but that breaks Venti, which needs *really* big stacks.)
104 lines
2 KiB
C
104 lines
2 KiB
C
#include "threadimpl.h"
|
|
|
|
Rgrp _threadrgrp;
|
|
static int isdirty;
|
|
int _threadhighnrendez;
|
|
int _threadnrendez;
|
|
static int nrendez;
|
|
|
|
static ulong
|
|
finish(Thread *t, ulong val)
|
|
{
|
|
ulong ret;
|
|
|
|
ret = t->rendval;
|
|
t->rendval = val;
|
|
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);
|
|
}
|
|
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);
|
|
}
|