Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <thread.h>
4
#include "threadimpl.h"
5
 
6
Rgrp _threadrgrp;
7
static int isdirty;
8
 
9
static void*
10
finish(Thread *t, void *val)
11
{
12
	void *ret;
13
 
14
	ret = t->rendval;
15
	t->rendval = val;
16
	while(t->state == Running)
17
		sleep(0);
18
	lock(&t->proc->lock);
19
	if(t->state == Rendezvous){	/* not always true: might be Dead */
20
		t->state = Ready;
21
		_threadready(t);
22
	}
23
	unlock(&t->proc->lock);
24
	return ret;
25
}
26
 
27
void*
28
_threadrendezvous(void *tag, void *val)
29
{
30
	void *ret;
31
	Thread *t, **l;
32
 
33
	lock(&_threadrgrp.lock);
34
	l = &_threadrgrp.hash[((uintptr)tag)%nelem(_threadrgrp.hash)];
35
	for(t=*l; t; l=&t->rendhash, t=*l){
36
		if(t->rendtag==tag){
37
			_threaddebug(DBGREND, "Rendezvous with thread %d.%d", t->proc->pid, t->id);
38
			*l = t->rendhash;
39
			ret = finish(t, val);
40
			unlock(&_threadrgrp.lock);
41
			return ret;
42
		}
43
	}
44
 
45
	/* Going to sleep here. */
46
	t = _threadgetproc()->thread;
47
	t->rendbreak = 0;
48
	t->inrendez = 1;
49
	t->rendtag = tag;
50
	t->rendval = val;
51
	t->rendhash = *l;
52
	*l = t;
53
	t->nextstate = Rendezvous;
54
	_threaddebug(DBGREND, "Rendezvous for tag %p", t->rendtag);
55
	unlock(&_threadrgrp.lock);
56
	_sched();
57
	t->inrendez = 0;
58
	_threaddebug(DBGREND, "Woke after rendezvous; val is %p", t->rendval);
59
	return t->rendval;
60
}
61
 
62
/*
63
 * This is called while holding _threadpq.lock and p->lock,
64
 * so we can't lock _threadrgrp.lock.  Instead our caller has 
65
 * to call _threadbreakrendez after dropping those locks.
66
 */
67
void
68
_threadflagrendez(Thread *t)
69
{
70
	t->rendbreak = 1;
71
	isdirty = 1;
72
}
73
 
74
void
75
_threadbreakrendez(void)
76
{
77
	int i;
78
	Thread *t, **l;
79
 
80
	if(isdirty == 0)
81
		return;
82
	lock(&_threadrgrp.lock);
83
	if(isdirty == 0){
84
		unlock(&_threadrgrp.lock);
85
		return;
86
	}
87
	isdirty = 0;
88
	for(i=0; i<nelem(_threadrgrp.hash); i++){
89
		l = &_threadrgrp.hash[i];
90
		for(t=*l; t; t=*l){
91
			if(t->rendbreak){
92
				*l = t->rendhash;
93
				finish(t, (void*)~0);
94
			}else
95
				 l=&t->rendhash;
96
		}
97
	}
98
	unlock(&_threadrgrp.lock);
99
}