xref: /inferno-os/emu/Plan9/os.c (revision 06155dbb53eb0585800b239acd6e45b946c6e0cf)
1 #include	"dat.h"
2 #include	"fns.h"
3 #include	"error.h"
4 
5 enum
6 {
7 	KSTACK	= 16*1024,
8 	DELETE	= 0x7F,
9 };
10 
11 Proc	**Xup;
12 
13 extern	void	killrefresh(void);
14 extern	void	tramp(char*, void (*)(void*), void*);
15 
16 extern	int	usenewwin;
17 
18 int	*ustack;	/* address on unshared stack: see vstack in asm*.s */
19 extern	int	dflag;
20 char *hosttype = "Plan9";
21 char *cputype;
22 
23 void
24 osblock(void)
25 {
26 	rendezvous(up, nil);
27 }
28 
29 void
30 osready(Proc *p)
31 {
32 	rendezvous(p, nil);
33 }
34 
35 void
36 pexit(char *msg, int)
37 {
38 	Osenv *e;
39 
40 	USED(msg);
41 
42 	lock(&procs.l);
43 	if(up->prev)
44 		up->prev->next = up->next;
45 	else
46 		procs.head = up->next;
47 
48 	if(up->next)
49 		up->next->prev = up->prev;
50 	else
51 		procs.tail = up->prev;
52 	unlock(&procs.l);
53 
54 /*	print("pexit: %s: %s\n", up->text, msg);	/**/
55 	e = up->env;
56 	if(e != nil) {
57 		closefgrp(e->fgrp);
58 		closepgrp(e->pgrp);
59 		closeegrp(e->egrp);
60 		closesigs(e->sigs);
61 	}
62 	free(e->user);
63 	free(up->prog);
64 	up->prog = nil;
65 	up->type = Moribund;
66 	longjmp(up->privstack, 1);
67 }
68 
69 int
70 kproc1(char *name, void (*func)(void*), void *arg, int flags)
71 {
72 	int pid;
73 	Proc *p;
74 	Pgrp *pg;
75 	Fgrp *fg;
76 	Egrp *eg;
77 
78 	p = newproc();
79 	if(p == nil)
80 		panic("kproc: no memory");
81 	p->kstack = mallocz(KSTACK, 0);
82 	if(p->kstack == nil)
83 		panic("kproc: no memory");
84 
85 	if(flags & KPDUPPG) {
86 		pg = up->env->pgrp;
87 		incref(&pg->r);
88 		p->env->pgrp = pg;
89 	}
90 	if(flags & KPDUPFDG) {
91 		fg = up->env->fgrp;
92 		incref(&fg->r);
93 		p->env->fgrp = fg;
94 	}
95 	if(flags & KPDUPENVG) {
96 		eg = up->env->egrp;
97 		incref(&eg->r);
98 		p->env->egrp = eg;
99 	}
100 
101 	p->env->uid = up->env->uid;
102 	p->env->gid = up->env->gid;
103 	kstrdup(&p->env->user, up->env->user);
104 
105 	strcpy(p->text, name);
106 
107 	p->func = func;
108 	p->arg = arg;
109 
110 	lock(&procs.l);
111 	if(procs.tail != nil) {
112 		p->prev = procs.tail;
113 		procs.tail->next = p;
114 	}
115 	else {
116 		procs.head = p;
117 		p->prev = nil;
118 	}
119 	procs.tail = p;
120 	unlock(&procs.l);
121 
122 	/*
123 	 * switch back to the unshared stack to do the fork
124 	 * only the parent returns from kproc
125 	 */
126 	up->kid = p;
127 	up->kidsp = p->kstack;
128 	pid = setjmp(up->sharestack);
129 	if(pid == 0)
130 		longjmp(up->privstack, 1);
131 	return pid;
132 }
133 
134 void
135 kproc(char *name, void (*func)(void*), void *arg, int flags)
136 {
137 	kproc1(name, func, arg, flags);
138 }
139 
140 void
141 traphandler(void *reg, char *msg)
142 {
143 	int intwait;
144 
145 	intwait = up->intwait;
146 	up->intwait = 0;
147 	/* Ignore pipe writes from devcmd */
148 	if(strstr(msg, "write on closed pipe") != nil)
149 		noted(NCONT);
150 
151 	if(sflag) {
152 		if(intwait && strcmp(msg, Eintr) == 0)
153 			noted(NCONT);
154 		else
155 			noted(NDFLT);
156 	}
157 	if(intwait == 0)
158 		disfault(reg, msg);
159 	noted(NCONT);
160 }
161 
162 int
163 readfile(char *path, char *buf, int n)
164 {
165 	int fd;
166 
167 	fd = open(path, OREAD);
168 	if(fd >= 0) {
169 		n = read(fd, buf, n-1);
170 		if(n > 0)			/* both calls to readfile() have a ``default'' */
171 			buf[n] = '\0';
172 		close(fd);
173 		return n;
174 	}
175 	return 0;
176 }
177 
178 static void
179 dobinds(void)
180 {
181 	char dir[MAXROOT+9];
182 
183 	snprint(dir, sizeof(dir), "%s/net", rootdir);
184 	bind("/net", dir, MREPL);
185 
186 	snprint(dir, sizeof(dir), "%s/net.alt", rootdir);
187 	bind("/net.alt", dir, MREPL);
188 
189 	snprint(dir, sizeof(dir), "%s/dev", rootdir);
190 	bind("#t", dir, MAFTER);
191 	bind("#A", dir, MAFTER);
192 }
193 
194 void
195 libinit(char *imod)
196 {
197 	char *sp;
198 	Proc *xup, *p;
199 	int fd, n, pid;
200 	char nbuf[64];
201 
202 	xup = nil;
203 	Xup = &xup;
204 
205 	/*
206 	 * setup personality
207 	 */
208 	if(readfile("/dev/user", nbuf, sizeof nbuf))
209 		kstrdup(&eve, nbuf);
210 	if(readfile("/dev/sysname", nbuf, sizeof nbuf))
211 		kstrdup(&ossysname, nbuf);
212 	if(readfile("/env/cputype", nbuf, sizeof nbuf))
213 		kstrdup(&cputype, nbuf);
214 
215 	/*
216 	 * guess at a safe stack for vstack
217 	 */
218 	ustack = &fd;
219 
220 	rfork(RFNAMEG|RFREND);
221 
222 	if(!dflag){
223 		fd = open("/dev/consctl", OWRITE);
224 		if(fd < 0)
225 			fprint(2, "libinit: open /dev/consctl: %r\n");
226 		n = write(fd, "rawon", 5);
227 		if(n != 5)
228 			fprint(2, "keyboard rawon (n=%d, %r)\n", n);
229 	}
230 
231 	osmillisec();	/* set the epoch */
232 	dobinds();
233 
234 	notify(traphandler);
235 
236 	/*
237 	 * dummy up a up and stack so the first proc
238 	 * calls emuinit after setting up his private jmp_buf
239 	 */
240 	p = newproc();
241 	p->kstack = mallocz(KSTACK, 0);
242 	if(p == nil || p->kstack == nil)
243 		panic("libinit: no memory");
244 	sp = p->kstack;
245 	p->func = emuinit;
246 	p->arg = imod;
247 
248 	/*
249 	 * set up a stack for forking kids on separate stacks.
250 	 * longjmp back here from kproc.
251 	 */
252 	while(setjmp(p->privstack)){
253 		if(up->type == Moribund){
254 			free(up->kstack);
255 			free(up);
256 			_exits("");
257 		}
258 		p = up->kid;
259 		sp = up->kidsp;
260 		up->kid = nil;
261 		switch(pid = rfork(RFPROC|RFMEM|RFNOWAIT)){
262 		case 0:
263 			/*
264 			 * send the kid around the loop to set up his private jmp_buf
265 			 */
266 			break;
267 		default:
268 			/*
269 			 * parent just returns to his shared stack in kproc
270 			 */
271 			longjmp(up->sharestack, pid);
272 			panic("longjmp failed");
273 		}
274 	}
275 
276 	/*
277 	 * you get here only once per Proc
278 	 * go to the shared memory stack
279 	 */
280 	up = p;
281 	up->pid = up->sigid = getpid();
282 	tramp(sp+KSTACK, up->func, up->arg);
283 	panic("tramp returned");
284 }
285 
286 void
287 oshostintr(Proc *p)
288 {
289 	postnote(PNPROC, p->sigid, Eintr);
290 }
291 
292 void
293 oslongjmp(void *regs, osjmpbuf env, int val)
294 {
295 	if(regs != nil)
296 		notejmp(regs, env, val);
297 	else
298 		longjmp(env, val);
299 }
300 
301 void
302 osreboot(char*, char**)
303 {
304 }
305 
306 void
307 cleanexit(int x)
308 {
309 	USED(x);
310 	killrefresh();
311 	postnote(PNGROUP, getpid(), "interrupt");
312 	exits("interrupt");
313 }
314 
315 int
316 readkbd(void)
317 {
318 	int n;
319 	char buf[1];
320 
321 	n = read(0, buf, sizeof(buf));
322 	if(n < 0)
323 		fprint(2, "emu: keyboard read error: %r\n");
324 	if(n <= 0)
325 		pexit("keyboard", 0);
326 	switch(buf[0]) {
327 	case DELETE:
328 		cleanexit(0);
329 	case '\r':
330 		buf[0] = '\n';
331 	}
332 	return buf[0];
333 }
334 
335 static vlong
336 b2v(uchar *p)
337 {
338 	int i;
339 	vlong v;
340 
341 	v = 0;
342 	for(i=0; i<sizeof(uvlong); i++)
343 		v = (v<<8)|p[i];
344 	return v;
345 }
346 
347 vlong
348 nsec(void)
349 {
350 	int n;
351 	static int nsecfd = -1;
352 	uchar buf[sizeof(uvlong)];
353 
354 	if(nsecfd < 0){
355 		nsecfd = open("/dev/bintime", OREAD|OCEXEC);  /* never closed */
356 		if(nsecfd<0){
357 			fprint(2,"can't open /dev/bintime: %r\n");
358 			return 0;
359 		}
360 	}
361 	n = read(nsecfd, buf, sizeof(buf));
362 	if(n!=sizeof(buf)) {
363 		fprint(2,"read err on /dev/bintime: %r\n");
364 		return 0;
365 	}
366 	return b2v(buf);
367 }
368 
369 long
370 osmillisec(void)
371 {
372 	static vlong nsec0 = 0;
373 
374 	if(nsec0 == 0){
375 		nsec0 = nsec();
376 		return 0;
377 	}
378 	return (nsec()-nsec0)/1000000;
379 }
380 
381 /*
382  * Return the time since the epoch in microseconds
383  * The epoch is defined at 1 Jan 1970
384  */
385 vlong
386 osusectime(void)
387 {
388 	return nsec()/1000;
389 }
390 
391 int
392 osmillisleep(ulong milsec)
393 {
394 	sleep(milsec);
395 	return 0;
396 }
397 
398 int
399 limbosleep(ulong milsec)
400 {
401 	return osmillisleep(milsec);
402 }
403 
404 void
405 osyield(void)
406 {
407 	sleep(0);
408 }
409 
410 void
411 ospause(void)
412 {
413 	for(;;)
414 		sleep(1000000);
415 }
416 
417 void
418 oslopri(void)
419 {
420 	int fd;
421 	char buf[32];
422 
423 	snprint(buf, sizeof(buf), "/proc/%d/ctl", getpid());
424 	if((fd = open(buf, OWRITE)) >= 0){
425 		fprint(fd, "pri 8");
426 		close(fd);
427 	}
428 }
429