xref: /plan9/sys/src/libthread/rendez.c (revision 74f16c8187aab477889167f2422d0597b1b7d0ff)
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