xref: /inferno-os/emu/port/proc.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1 #include	"dat.h"
2 #include	"fns.h"
3 #include	"error.h"
4 #include	"interp.h"
5 
6 Proc*
newproc(void)7 newproc(void)
8 {
9 	Proc *p;
10 
11 	p = malloc(sizeof(Proc));
12 	if(p == nil)
13 		return nil;
14 
15 	p->type = Unknown;
16 	p->killed = 0;
17 	p->swipend = 0;
18 	p->env = &p->defenv;
19 	kstrdup(&p->env->user, "*nouser");
20 	p->env->errstr = p->env->errbuf0;
21 	p->env->syserrstr = p->env->errbuf1;
22 	addprog(p);
23 
24 	return p;
25 }
26 
27 void
Sleep(Rendez * r,int (* f)(void *),void * arg)28 Sleep(Rendez *r, int (*f)(void*), void *arg)
29 {
30 	lock(&up->rlock);
31 	lock(&r->l);
32 
33 	/*
34 	 * if interrupted or condition happened, never mind
35 	 */
36 	if(up->killed || f(arg)) {
37 		unlock(&r->l);
38 	}else{
39 		if(r->p != nil)
40 			panic("double sleep pc=0x%lux %s[%lud] %s[%lud] r=0x%lux\n", getcallerpc(&r), r->p->text, r->p->pid, up->text, up->pid, r);
41 
42 		r->p = up;
43 		unlock(&r->l);
44 		up->swipend = 0;
45 		up->r = r;	/* for swiproc */
46 		unlock(&up->rlock);
47 
48 		osblock();
49 
50 		lock(&up->rlock);
51 		up->r = nil;
52 	}
53 
54 	if(up->killed || up->swipend) {
55 		up->killed = 0;
56 		up->swipend = 0;
57 		unlock(&up->rlock);
58 		error(Eintr);
59 	}
60 	unlock(&up->rlock);
61 }
62 
63 int
Wakeup(Rendez * r)64 Wakeup(Rendez *r)
65 {
66 	Proc *p;
67 
68 	lock(&r->l);
69 	p = r->p;
70 	if(p != nil) {
71 		r->p = nil;
72 		osready(p);
73 	}
74 	unlock(&r->l);
75 	return p != nil;
76 }
77 
78 void
swiproc(Proc * p,int interp)79 swiproc(Proc *p, int interp)
80 {
81 	Rendez *r;
82 
83 	if(p == nil)
84 		return;
85 
86 	/*
87 	 * Pull out of emu Sleep
88 	 */
89 	lock(&p->rlock);
90 	if(!interp)
91 		p->killed = 1;
92 	r = p->r;
93 	if(r != nil) {
94 		lock(&r->l);
95 		if(r->p == p){
96 			p->swipend = 1;
97 			r->p = nil;
98 			osready(p);
99 		}
100 		unlock(&r->l);
101 		unlock(&p->rlock);
102 		return;
103 	}
104 	unlock(&p->rlock);
105 
106 	/*
107 	 * Maybe pull out of Host OS
108 	 */
109 	lock(&p->sysio);
110 	if(p->syscall && p->intwait == 0) {
111 		p->swipend = 1;
112 		p->intwait = 1;
113 		unlock(&p->sysio);
114 		oshostintr(p);
115 		return;
116 	}
117 	unlock(&p->sysio);
118 }
119 
120 void
notkilled(void)121 notkilled(void)
122 {
123 	lock(&up->rlock);
124 	up->killed = 0;
125 	unlock(&up->rlock);
126 }
127 
128 void
osenter(void)129 osenter(void)
130 {
131 	up->syscall = 1;
132 }
133 
134 void
osleave(void)135 osleave(void)
136 {
137 	int r;
138 
139 	lock(&up->rlock);
140 	r = up->swipend;
141 	up->swipend = 0;
142 	unlock(&up->rlock);
143 
144 	lock(&up->sysio);
145 	up->syscall = 0;
146 	unlock(&up->sysio);
147 
148 	/* Cleared by the signal/note/exception handler */
149 	while(up->intwait)
150 		osyield();
151 
152 	if(r != 0)
153 		error(Eintr);
154 }
155 
156 void
rptwakeup(void * o,void * ar)157 rptwakeup(void *o, void *ar)
158 {
159 	Rept *r;
160 
161 	r = ar;
162 	if(r == nil)
163 		return;
164 	lock(&r->l);
165 	r->o = o;
166 	unlock(&r->l);
167 	Wakeup(&r->r);
168 }
169 
170 static int
rptactive(void * a)171 rptactive(void *a)
172 {
173 	Rept *r = a;
174 	int i;
175 	lock(&r->l);
176 	i = r->active(r->o);
177 	unlock(&r->l);
178 	return i;
179 }
180 
181 static void
rproc(void * a)182 rproc(void *a)
183 {
184 	long now, then;
185 	ulong t;
186 	int i;
187 	void *o;
188 	Rept *r;
189 
190 	up->env->fgrp = newfgrp(nil);
191 	r = a;
192 	t = (ulong)r->t;
193 
194 Wait:
195 	Sleep(&r->r, rptactive, r);
196 	lock(&r->l);
197 	o = r->o;
198 	unlock(&r->l);
199 	then = osmillisec();
200 	for(;;){
201 		osmillisleep(t);
202 		now = osmillisec();
203 		if(waserror())
204 			break;
205 		i = r->ck(o, now-then);
206 		poperror();
207 		if(i == -1)
208 			goto Wait;
209 		if(i == 0)
210 			continue;
211 		then = now;
212 		acquire();
213 		if(waserror()) {
214 			release();
215 			break;
216 		}
217 		r->f(o);
218 		poperror();
219 		release();
220 	}
221 	pexit("", 0);
222 }
223 
224 void*
rptproc(char * s,int t,void * o,int (* active)(void *),int (* ck)(void *,int),void (* f)(void *))225 rptproc(char *s, int t, void *o, int (*active)(void*), int (*ck)(void*, int), void (*f)(void*))
226 {
227 	Rept *r;
228 
229 	r = mallocz(sizeof(Rept), 1);
230 	if(r == nil)
231 		return nil;
232 	r->t = t;
233 	r->active = active;
234 	r->ck = ck;
235 	r->f = f;
236 	r->o = o;
237 	kproc(s, rproc, r, KPDUPPG);
238 	return r;
239 }
240