19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <thread.h>
49a747e4fSDavid du Colombier #include "threadimpl.h"
59a747e4fSDavid du Colombier
69a747e4fSDavid du Colombier Rgrp _threadrgrp;
79a747e4fSDavid du Colombier static int isdirty;
89a747e4fSDavid du Colombier
9*74f16c81SDavid du Colombier static void*
finish(Thread * t,void * val)10*74f16c81SDavid du Colombier finish(Thread *t, void *val)
119a747e4fSDavid du Colombier {
12*74f16c81SDavid du Colombier void *ret;
139a747e4fSDavid du Colombier
149a747e4fSDavid du Colombier ret = t->rendval;
159a747e4fSDavid du Colombier t->rendval = val;
169a747e4fSDavid du Colombier while(t->state == Running)
179a747e4fSDavid du Colombier sleep(0);
189a747e4fSDavid du Colombier lock(&t->proc->lock);
199a747e4fSDavid du Colombier if(t->state == Rendezvous){ /* not always true: might be Dead */
209a747e4fSDavid du Colombier t->state = Ready;
219a747e4fSDavid du Colombier _threadready(t);
229a747e4fSDavid du Colombier }
239a747e4fSDavid du Colombier unlock(&t->proc->lock);
249a747e4fSDavid du Colombier return ret;
259a747e4fSDavid du Colombier }
269a747e4fSDavid du Colombier
27*74f16c81SDavid du Colombier void*
_threadrendezvous(void * tag,void * val)28*74f16c81SDavid du Colombier _threadrendezvous(void *tag, void *val)
299a747e4fSDavid du Colombier {
30*74f16c81SDavid du Colombier void *ret;
319a747e4fSDavid du Colombier Thread *t, **l;
329a747e4fSDavid du Colombier
339a747e4fSDavid du Colombier lock(&_threadrgrp.lock);
34*74f16c81SDavid du Colombier l = &_threadrgrp.hash[((uintptr)tag)%nelem(_threadrgrp.hash)];
359a747e4fSDavid du Colombier for(t=*l; t; l=&t->rendhash, t=*l){
369a747e4fSDavid du Colombier if(t->rendtag==tag){
379a747e4fSDavid du Colombier _threaddebug(DBGREND, "Rendezvous with thread %d.%d", t->proc->pid, t->id);
389a747e4fSDavid du Colombier *l = t->rendhash;
399a747e4fSDavid du Colombier ret = finish(t, val);
409a747e4fSDavid du Colombier unlock(&_threadrgrp.lock);
419a747e4fSDavid du Colombier return ret;
429a747e4fSDavid du Colombier }
439a747e4fSDavid du Colombier }
449a747e4fSDavid du Colombier
459a747e4fSDavid du Colombier /* Going to sleep here. */
469a747e4fSDavid du Colombier t = _threadgetproc()->thread;
479a747e4fSDavid du Colombier t->rendbreak = 0;
489a747e4fSDavid du Colombier t->inrendez = 1;
499a747e4fSDavid du Colombier t->rendtag = tag;
509a747e4fSDavid du Colombier t->rendval = val;
519a747e4fSDavid du Colombier t->rendhash = *l;
529a747e4fSDavid du Colombier *l = t;
539a747e4fSDavid du Colombier t->nextstate = Rendezvous;
54*74f16c81SDavid du Colombier _threaddebug(DBGREND, "Rendezvous for tag %p", t->rendtag);
559a747e4fSDavid du Colombier unlock(&_threadrgrp.lock);
569a747e4fSDavid du Colombier _sched();
579a747e4fSDavid du Colombier t->inrendez = 0;
58*74f16c81SDavid du Colombier _threaddebug(DBGREND, "Woke after rendezvous; val is %p", t->rendval);
599a747e4fSDavid du Colombier return t->rendval;
609a747e4fSDavid du Colombier }
619a747e4fSDavid du Colombier
629a747e4fSDavid du Colombier /*
639a747e4fSDavid du Colombier * This is called while holding _threadpq.lock and p->lock,
649a747e4fSDavid du Colombier * so we can't lock _threadrgrp.lock. Instead our caller has
659a747e4fSDavid du Colombier * to call _threadbreakrendez after dropping those locks.
669a747e4fSDavid du Colombier */
679a747e4fSDavid du Colombier void
_threadflagrendez(Thread * t)689a747e4fSDavid du Colombier _threadflagrendez(Thread *t)
699a747e4fSDavid du Colombier {
709a747e4fSDavid du Colombier t->rendbreak = 1;
719a747e4fSDavid du Colombier isdirty = 1;
729a747e4fSDavid du Colombier }
739a747e4fSDavid du Colombier
749a747e4fSDavid du Colombier void
_threadbreakrendez(void)759a747e4fSDavid du Colombier _threadbreakrendez(void)
769a747e4fSDavid du Colombier {
779a747e4fSDavid du Colombier int i;
789a747e4fSDavid du Colombier Thread *t, **l;
799a747e4fSDavid du Colombier
809a747e4fSDavid du Colombier if(isdirty == 0)
819a747e4fSDavid du Colombier return;
829a747e4fSDavid du Colombier lock(&_threadrgrp.lock);
839a747e4fSDavid du Colombier if(isdirty == 0){
849a747e4fSDavid du Colombier unlock(&_threadrgrp.lock);
859a747e4fSDavid du Colombier return;
869a747e4fSDavid du Colombier }
879a747e4fSDavid du Colombier isdirty = 0;
889a747e4fSDavid du Colombier for(i=0; i<nelem(_threadrgrp.hash); i++){
899a747e4fSDavid du Colombier l = &_threadrgrp.hash[i];
909a747e4fSDavid du Colombier for(t=*l; t; t=*l){
919a747e4fSDavid du Colombier if(t->rendbreak){
929a747e4fSDavid du Colombier *l = t->rendhash;
93*74f16c81SDavid du Colombier finish(t, (void*)~0);
949a747e4fSDavid du Colombier }else
959a747e4fSDavid du Colombier l=&t->rendhash;
969a747e4fSDavid du Colombier }
979a747e4fSDavid du Colombier }
989a747e4fSDavid du Colombier unlock(&_threadrgrp.lock);
999a747e4fSDavid du Colombier }
100