Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | 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
#include <tos.h>
6
 
7
static Thread	*runthread(Proc*);
8
 
9
static char *_psstate[] = {
10
	"Moribund",
11
	"Dead",
12
	"Exec",
13
	"Fork",
14
	"Running",
15
	"Ready",
16
	"Rendezvous",
17
};
18
 
19
static char*
20
psstate(int s)
21
{
22
	if(s < 0 || s >= nelem(_psstate))
23
		return "unknown";
24
	return _psstate[s];
25
}
26
 
27
void
28
_schedinit(void *arg)
29
{
30
	Proc *p;
31
	Thread *t, **l;
32
 
33
	p = arg;
34
	_threadsetproc(p);
35
	p->pid = _tos->pid; //getpid();
36
	while(setjmp(p->sched))
37
		;
38
	_threaddebug(DBGSCHED, "top of schedinit, _threadexitsallstatus=%p", _threadexitsallstatus);
39
	if(_threadexitsallstatus)
40
		exits(_threadexitsallstatus);
41
	lock(&p->lock);
42
	if((t=p->thread) != nil){
43
		p->thread = nil;
44
		if(t->moribund){
45
			t->state = Dead;
46
			for(l=&p->threads.head; *l; l=&(*l)->nextt)
47
				if(*l == t){
48
					*l = t->nextt;
49
					if(*l==nil)
50
						p->threads.tail = l;
51
					p->nthreads--;
52
					break;
53
				}
54
			unlock(&p->lock);
55
			if(t->inrendez){
56
				_threadflagrendez(t);
57
				_threadbreakrendez();
58
			}
59
			free(t->stk);
60
			free(t->cmdname);
61
			free(t);	/* XXX how do we know there are no references? */
62
			t = nil;
63
			_sched();
64
		}
65
		if(p->needexec){
66
			t->ret = _schedexec(&p->exec);
67
			p->needexec = 0;
68
		}
69
		if(p->newproc){
70
			t->ret = _schedfork(p->newproc);
71
			p->newproc = nil;
72
		}
73
		t->state = t->nextstate;
74
		if(t->state == Ready)
75
			_threadready(t);
76
	}
77
	unlock(&p->lock);
78
	_sched();
79
}
80
 
81
void
82
needstack(int n)
83
{
84
	int x;
85
	Proc *p;
86
	Thread *t;
87
 
88
	p = _threadgetproc();
89
	t = p->thread;
90
 
91
	if((uchar*)&x - n < (uchar*)t->stk){
92
		fprint(2, "%s %lud: &x=%p n=%d t->stk=%p\n",
93
			argv0, _tos->pid, &x, n, t->stk);
94
		fprint(2, "%s %lud: stack overflow\n", argv0, _tos->pid);
95
		abort();
96
	}
97
}
98
 
99
void
100
_sched(void)
101
{
102
	Proc *p;
103
	Thread *t;
104
 
105
Resched:
106
	p = _threadgetproc();
107
	if((t = p->thread) != nil){
108
		needstack(128);
109
		_threaddebug(DBGSCHED, "pausing, state=%s", psstate(t->state));
110
		if(setjmp(t->sched)==0)
111
			longjmp(p->sched, 1);
112
		return;
113
	}else{
114
		t = runthread(p);
115
		if(t == nil){
116
			_threaddebug(DBGSCHED, "all threads gone; exiting");
117
			_schedexit(p);
118
		}
119
		_threaddebug(DBGSCHED, "running %d.%d", t->proc->pid, t->id);
120
		p->thread = t;
121
		if(t->moribund){
122
			_threaddebug(DBGSCHED, "%d.%d marked to die");
123
			goto Resched;
124
		}
125
		t->state = Running;
126
		t->nextstate = Ready;
127
		longjmp(t->sched, 1);
128
	}
129
}
130
 
131
static Thread*
132
runthread(Proc *p)
133
{
134
	Thread *t;
135
	Tqueue *q;
136
 
137
	if(p->nthreads==0)
138
		return nil;
139
	q = &p->ready;
140
	lock(&p->readylock);
141
	if(q->head == nil){
142
		q->asleep = 1;
143
		_threaddebug(DBGSCHED, "sleeping for more work");
144
		unlock(&p->readylock);
145
		while(rendezvous(q, 0) == (void*)~0){
146
			if(_threadexitsallstatus)
147
				exits(_threadexitsallstatus);
148
		}
149
		/* lock picked up from _threadready */
150
	}
151
	t = q->head;
152
	q->head = t->next;
153
	unlock(&p->readylock);
154
	return t;
155
}
156
 
157
void
158
_threadready(Thread *t)
159
{
160
	Tqueue *q;
161
 
162
	assert(t->state == Ready);
163
	_threaddebug(DBGSCHED, "readying %d.%d", t->proc->pid, t->id);
164
	q = &t->proc->ready;
165
	lock(&t->proc->readylock);
166
	t->next = nil;
167
	if(q->head==nil)
168
		q->head = t;
169
	else
170
		*q->tail = t;
171
	q->tail = &t->next;
172
	if(q->asleep){
173
		q->asleep = 0;
174
		/* lock passes to runthread */
175
		_threaddebug(DBGSCHED, "waking process %d", t->proc->pid);
176
		while(rendezvous(q, 0) == (void*)~0){
177
			if(_threadexitsallstatus)
178
				exits(_threadexitsallstatus);
179
		}
180
	}else
181
		unlock(&t->proc->readylock);
182
}
183
 
184
void
185
yield(void)
186
{
187
	_sched();
188
}
189