xref: /inferno-os/emu/FreeBSD/os.c (revision ce3f4532f3f68d5c3419c4581504faff3a1d2820)
137da2899SCharles.Forsyth #include	"dat.h"
237da2899SCharles.Forsyth #include	"fns.h"
337da2899SCharles.Forsyth #include	"error.h"
437da2899SCharles.Forsyth #undef getwd
537da2899SCharles.Forsyth #include	<signal.h>
637da2899SCharles.Forsyth #include 	<sys/socket.h>
737da2899SCharles.Forsyth #include	<time.h>
837da2899SCharles.Forsyth #include	<sys/time.h>
937da2899SCharles.Forsyth #include	<termios.h>
1037da2899SCharles.Forsyth #include	<sched.h>
1137da2899SCharles.Forsyth #include	<pwd.h>
1237da2899SCharles.Forsyth #include	<errno.h>
1337da2899SCharles.Forsyth #include	<unistd.h>
1437da2899SCharles.Forsyth #include	<sys/resource.h>
1537da2899SCharles.Forsyth 
1637da2899SCharles.Forsyth enum
1737da2899SCharles.Forsyth {
1837da2899SCharles.Forsyth 	DELETE  = 0x7F,
1937da2899SCharles.Forsyth 	NSTACKSPERALLOC = 16,
2037da2899SCharles.Forsyth 	X11STACK=	256*1024
2137da2899SCharles.Forsyth };
2237da2899SCharles.Forsyth char *hosttype = "FreeBSD";
2337da2899SCharles.Forsyth 
2437da2899SCharles.Forsyth extern void unlockandexit(int*);
2537da2899SCharles.Forsyth extern void executeonnewstack(void*, void (*f)(void*), void*);
2637da2899SCharles.Forsyth static void *stackalloc(Proc *p, void **tos);
2737da2899SCharles.Forsyth static void stackfreeandexit(void *stack);
2837da2899SCharles.Forsyth 
2937da2899SCharles.Forsyth extern int dflag;
3037da2899SCharles.Forsyth 
3137da2899SCharles.Forsyth void
pexit(char * msg,int t)3237da2899SCharles.Forsyth pexit(char *msg, int t)
3337da2899SCharles.Forsyth {
3437da2899SCharles.Forsyth 	Osenv *e;
3537da2899SCharles.Forsyth 	Proc *p;
3637da2899SCharles.Forsyth 	void *kstack;
3737da2899SCharles.Forsyth 
3837da2899SCharles.Forsyth 	lock(&procs.l);
3937da2899SCharles.Forsyth 	p = up;
4037da2899SCharles.Forsyth 	if(p->prev)
4137da2899SCharles.Forsyth 		p->prev->next = p->next;
4237da2899SCharles.Forsyth 	else
4337da2899SCharles.Forsyth 		procs.head = p->next;
4437da2899SCharles.Forsyth 
4537da2899SCharles.Forsyth 	if(up->next)
4637da2899SCharles.Forsyth 		p->next->prev = p->prev;
4737da2899SCharles.Forsyth 	else
4837da2899SCharles.Forsyth 		procs.tail = p->prev;
4937da2899SCharles.Forsyth 	unlock(&procs.l);
5037da2899SCharles.Forsyth 
5137da2899SCharles.Forsyth 	if(0)
5237da2899SCharles.Forsyth 		print("pexit: %s: %s\n", up->text, msg);
5337da2899SCharles.Forsyth 
5437da2899SCharles.Forsyth 	e = up->env;
5537da2899SCharles.Forsyth 	if(e != nil) {
5637da2899SCharles.Forsyth 		closefgrp(e->fgrp);
5737da2899SCharles.Forsyth 		closepgrp(e->pgrp);
5837da2899SCharles.Forsyth 		closeegrp(e->egrp);
5937da2899SCharles.Forsyth 		closesigs(e->sigs);
6037da2899SCharles.Forsyth 	}
6137da2899SCharles.Forsyth 	kstack = p->kstack;
6237da2899SCharles.Forsyth 	free(p->prog);
6337da2899SCharles.Forsyth 	free(p);
6437da2899SCharles.Forsyth 	if(kstack != nil)
6537da2899SCharles.Forsyth 		stackfreeandexit(kstack);
6637da2899SCharles.Forsyth }
6737da2899SCharles.Forsyth 
6837da2899SCharles.Forsyth void
trapBUS(int signo,siginfo_t * info,void * context)6937da2899SCharles.Forsyth trapBUS(int signo, siginfo_t *info, void *context)
7037da2899SCharles.Forsyth {
7137da2899SCharles.Forsyth 	if(info)
7237da2899SCharles.Forsyth 		print("trapBUS: signo: %d code: %d addr: %lx\n",
7337da2899SCharles.Forsyth 		info->si_signo, info->si_code, info->si_addr);
7437da2899SCharles.Forsyth 	else
7537da2899SCharles.Forsyth 		print("trapBUS: no info\n");
7637da2899SCharles.Forsyth 	disfault(nil, "Bus error");
7737da2899SCharles.Forsyth }
7837da2899SCharles.Forsyth 
7937da2899SCharles.Forsyth static void
trapUSR1(int signo)8037da2899SCharles.Forsyth trapUSR1(int signo)
8137da2899SCharles.Forsyth {
8237da2899SCharles.Forsyth 	int intwait;
8337da2899SCharles.Forsyth 
8437da2899SCharles.Forsyth 	USED(signo);
8537da2899SCharles.Forsyth 
8637da2899SCharles.Forsyth 	intwait = up->intwait;
8737da2899SCharles.Forsyth 	up->intwait = 0;	/* clear it to let proc continue in osleave */
8837da2899SCharles.Forsyth 
8937da2899SCharles.Forsyth 	if(up->type != Interp)		/* Used to unblock pending I/O */
9037da2899SCharles.Forsyth 		return;
9137da2899SCharles.Forsyth 	if(intwait == 0)		/* Not posted so its a sync error */
9237da2899SCharles.Forsyth 		disfault(nil, Eintr);	/* Should never happen */
9337da2899SCharles.Forsyth }
9437da2899SCharles.Forsyth 
9537da2899SCharles.Forsyth static void
trapUSR2(int signo)9637da2899SCharles.Forsyth trapUSR2(int signo)
9737da2899SCharles.Forsyth {
9837da2899SCharles.Forsyth 	USED(signo);
9937da2899SCharles.Forsyth 	/* we've done our work of interrupting sigsuspend */
10037da2899SCharles.Forsyth }
10137da2899SCharles.Forsyth 
10237da2899SCharles.Forsyth static void
trapILL(int signo)10337da2899SCharles.Forsyth trapILL(int signo)
10437da2899SCharles.Forsyth {
10537da2899SCharles.Forsyth 	disfault(nil, "Illegal instruction");
10637da2899SCharles.Forsyth }
10737da2899SCharles.Forsyth 
10837da2899SCharles.Forsyth static void
trapSEGV(int signo)10937da2899SCharles.Forsyth trapSEGV(int signo)
11037da2899SCharles.Forsyth {
11137da2899SCharles.Forsyth 	disfault(nil, "Segmentation violation");
11237da2899SCharles.Forsyth }
11337da2899SCharles.Forsyth 
1146bf3ce61Sforsyth static void
trapFPE(int signo)1156bf3ce61Sforsyth trapFPE(int signo)
1166bf3ce61Sforsyth {
1176bf3ce61Sforsyth 
1186bf3ce61Sforsyth 	char buf[64];
1196bf3ce61Sforsyth 	USED(signo);
1206bf3ce61Sforsyth 	snprint(buf, sizeof(buf), "sys: fp: exception status=%.4lux", getfsr());
1216bf3ce61Sforsyth 	disfault(nil, buf);
1226bf3ce61Sforsyth }
1236bf3ce61Sforsyth 
12437da2899SCharles.Forsyth static sigset_t initmask;
12537da2899SCharles.Forsyth 
12637da2899SCharles.Forsyth static void
setsigs(void)12737da2899SCharles.Forsyth setsigs(void)
12837da2899SCharles.Forsyth {
12937da2899SCharles.Forsyth 	struct sigaction act;
13037da2899SCharles.Forsyth 	sigset_t mask;
13137da2899SCharles.Forsyth 
13237da2899SCharles.Forsyth 	memset(&act, 0 , sizeof(act));
13337da2899SCharles.Forsyth 	sigemptyset(&initmask);
13437da2899SCharles.Forsyth 
13537da2899SCharles.Forsyth 	signal(SIGPIPE, SIG_IGN);	/* prevent signal when devcmd child exits */
13637da2899SCharles.Forsyth 	if(signal(SIGTERM, SIG_IGN) != SIG_IGN)
13737da2899SCharles.Forsyth 		signal(SIGTERM, cleanexit);
13837da2899SCharles.Forsyth 
13937da2899SCharles.Forsyth 	act.sa_handler = trapUSR1;
14037da2899SCharles.Forsyth 	act.sa_mask = initmask;
14137da2899SCharles.Forsyth 	sigaction(SIGUSR1, &act, nil);
14237da2899SCharles.Forsyth 
14337da2899SCharles.Forsyth 	act.sa_handler = trapUSR2;
14437da2899SCharles.Forsyth 	sigaction(SIGUSR2, &act, nil);
14537da2899SCharles.Forsyth 	sigemptyset(&mask);
14637da2899SCharles.Forsyth 	sigaddset(&mask, SIGUSR2);
14737da2899SCharles.Forsyth 	sigaddset(&initmask, SIGUSR2);
14837da2899SCharles.Forsyth 	sigprocmask(SIG_BLOCK, &mask, NULL);
14937da2899SCharles.Forsyth 
15037da2899SCharles.Forsyth 	/*
15137da2899SCharles.Forsyth  	 * prevent Zombies forming when any process terminates
15237da2899SCharles.Forsyth 	 */
15337da2899SCharles.Forsyth 	act.sa_sigaction = 0;
15437da2899SCharles.Forsyth 	act.sa_flags |= SA_NOCLDWAIT;
15537da2899SCharles.Forsyth 	if(sigaction(SIGCHLD, &act, nil))
15637da2899SCharles.Forsyth 		panic("sigaction SIGCHLD");
15737da2899SCharles.Forsyth 
15837da2899SCharles.Forsyth 	if(sflag == 0) {
15937da2899SCharles.Forsyth 		act.sa_sigaction = trapBUS;
16037da2899SCharles.Forsyth 		act.sa_flags |= SA_SIGINFO;
16137da2899SCharles.Forsyth 		if(sigaction(SIGBUS, &act, nil))
16237da2899SCharles.Forsyth 			panic("sigaction SIGBUS");
16337da2899SCharles.Forsyth 		act.sa_handler = trapILL;
16437da2899SCharles.Forsyth 		if(sigaction(SIGILL, &act, nil))
16537da2899SCharles.Forsyth 			panic("sigaction SIGBUS");
16637da2899SCharles.Forsyth 		act.sa_handler = trapSEGV;
16737da2899SCharles.Forsyth 		if(sigaction(SIGSEGV, &act, nil))
16837da2899SCharles.Forsyth 			panic("sigaction SIGSEGV");
1696bf3ce61Sforsyth 		act.sa_handler = trapFPE;
1706bf3ce61Sforsyth 		if(sigaction(SIGFPE, &act, nil))
1716bf3ce61Sforsyth 			panic("sigaction SIGFPE");
17237da2899SCharles.Forsyth 		if(sigaddset(&initmask, SIGINT) == -1)
17337da2899SCharles.Forsyth 			panic("sigaddset");
17437da2899SCharles.Forsyth 	}
17537da2899SCharles.Forsyth 	if(sigprocmask(SIG_BLOCK, &initmask, nil)!= 0)
17637da2899SCharles.Forsyth 		panic("sigprocmask");
17737da2899SCharles.Forsyth }
17837da2899SCharles.Forsyth 
17937da2899SCharles.Forsyth static int
tramp(void * arg)18037da2899SCharles.Forsyth tramp(void *arg)
18137da2899SCharles.Forsyth {
18237da2899SCharles.Forsyth 	Proc *p;
18337da2899SCharles.Forsyth 
18437da2899SCharles.Forsyth 	p = arg;
18537da2899SCharles.Forsyth 	p->pid = p->sigid = getpid();
18637da2899SCharles.Forsyth 	sigprocmask(SIG_BLOCK, &initmask, nil);	/* in 5.3, rfork_thread doesn't copy from parent, contrary to docs? */
18737da2899SCharles.Forsyth 	(*p->func)(p->arg);
18837da2899SCharles.Forsyth 	pexit("{Tramp}", 0);
18937da2899SCharles.Forsyth 	_exit(0);
19037da2899SCharles.Forsyth }
19137da2899SCharles.Forsyth 
192*1343b7e5Sforsyth void
kproc(char * name,void (* func)(void *),void * arg,int flags)19337da2899SCharles.Forsyth kproc(char *name, void (*func)(void*), void *arg, int flags)
19437da2899SCharles.Forsyth {
19537da2899SCharles.Forsyth 	Proc *p;
19637da2899SCharles.Forsyth 	Pgrp *pg;
19737da2899SCharles.Forsyth 	Fgrp *fg;
19837da2899SCharles.Forsyth 	Egrp *eg;
19937da2899SCharles.Forsyth 	int pid;
20037da2899SCharles.Forsyth 	void *tos;
20137da2899SCharles.Forsyth 
20237da2899SCharles.Forsyth 	p = newproc();
20337da2899SCharles.Forsyth 
20437da2899SCharles.Forsyth 	if(flags & KPDUPPG) {
20537da2899SCharles.Forsyth 		pg = up->env->pgrp;
20637da2899SCharles.Forsyth 		incref(&pg->r);
20737da2899SCharles.Forsyth 		p->env->pgrp = pg;
20837da2899SCharles.Forsyth 	}
20937da2899SCharles.Forsyth 	if(flags & KPDUPFDG) {
21037da2899SCharles.Forsyth 		fg = up->env->fgrp;
21137da2899SCharles.Forsyth 		incref(&fg->r);
21237da2899SCharles.Forsyth 		p->env->fgrp = fg;
21337da2899SCharles.Forsyth 	}
21437da2899SCharles.Forsyth 	if(flags & KPDUPENVG) {
21537da2899SCharles.Forsyth 		eg = up->env->egrp;
21637da2899SCharles.Forsyth 		incref(&eg->r);
21737da2899SCharles.Forsyth 		p->env->egrp = eg;
21837da2899SCharles.Forsyth 	}
21937da2899SCharles.Forsyth 
22037da2899SCharles.Forsyth 	p->env->uid = up->env->uid;
22137da2899SCharles.Forsyth 	p->env->gid = up->env->gid;
22237da2899SCharles.Forsyth 	kstrdup(&p->env->user, up->env->user);
22337da2899SCharles.Forsyth 
22437da2899SCharles.Forsyth 	strcpy(p->text, name);
22537da2899SCharles.Forsyth 
22637da2899SCharles.Forsyth 	p->func = func;
22737da2899SCharles.Forsyth 	p->arg = arg;
22837da2899SCharles.Forsyth 
22937da2899SCharles.Forsyth 	lock(&procs.l);
23037da2899SCharles.Forsyth 	if(procs.tail != nil) {
23137da2899SCharles.Forsyth 		p->prev = procs.tail;
23237da2899SCharles.Forsyth 		procs.tail->next = p;
23337da2899SCharles.Forsyth 	}
23437da2899SCharles.Forsyth 	else {
23537da2899SCharles.Forsyth 		procs.head = p;
23637da2899SCharles.Forsyth 		p->prev = nil;
23737da2899SCharles.Forsyth 	}
23837da2899SCharles.Forsyth 	procs.tail = p;
23937da2899SCharles.Forsyth 	unlock(&procs.l);
24037da2899SCharles.Forsyth 
24137da2899SCharles.Forsyth 	if(flags & KPX11){
24237da2899SCharles.Forsyth 		p->kstack = nil;	/* never freed; also up not defined */
24337da2899SCharles.Forsyth 		tos = (char*)mallocz(X11STACK, 0) + X11STACK - sizeof(void*);
24437da2899SCharles.Forsyth 	}else
24537da2899SCharles.Forsyth 		p->kstack = stackalloc(p, &tos);
24637da2899SCharles.Forsyth 	pid = rfork_thread(RFPROC|RFMEM|RFNOWAIT, tos, tramp, p);
24737da2899SCharles.Forsyth 	if(pid < 0)
248*1343b7e5Sforsyth 		panic("rfork");
24937da2899SCharles.Forsyth }
25037da2899SCharles.Forsyth 
25137da2899SCharles.Forsyth void
oshostintr(Proc * p)25237da2899SCharles.Forsyth oshostintr(Proc *p)
25337da2899SCharles.Forsyth {
25437da2899SCharles.Forsyth 	kill(p->sigid, SIGUSR1);
25537da2899SCharles.Forsyth }
25637da2899SCharles.Forsyth 
25737da2899SCharles.Forsyth void
osblock(void)25837da2899SCharles.Forsyth osblock(void)
25937da2899SCharles.Forsyth {
26037da2899SCharles.Forsyth 	sigset_t mask;
26137da2899SCharles.Forsyth 
26237da2899SCharles.Forsyth 	sigprocmask(SIG_SETMASK, NULL, &mask);
26337da2899SCharles.Forsyth 	sigdelset(&mask, SIGUSR2);
26437da2899SCharles.Forsyth 	sigsuspend(&mask);
26537da2899SCharles.Forsyth }
26637da2899SCharles.Forsyth 
26737da2899SCharles.Forsyth void
osready(Proc * p)26837da2899SCharles.Forsyth osready(Proc *p)
26937da2899SCharles.Forsyth {
27037da2899SCharles.Forsyth 	if(kill(p->sigid, SIGUSR2) < 0)
27137da2899SCharles.Forsyth 		fprint(2, "emu: osready failed: pid %d: %s\n", p->sigid, strerror(errno));
27237da2899SCharles.Forsyth }
27337da2899SCharles.Forsyth 
27437da2899SCharles.Forsyth void
oslongjmp(void * regs,osjmpbuf env,int val)27537da2899SCharles.Forsyth oslongjmp(void *regs, osjmpbuf env, int val)
27637da2899SCharles.Forsyth {
27737da2899SCharles.Forsyth 	USED(regs);
27837da2899SCharles.Forsyth 	siglongjmp(env, val);
27937da2899SCharles.Forsyth }
28037da2899SCharles.Forsyth 
28137da2899SCharles.Forsyth struct termios tinit;
28237da2899SCharles.Forsyth 
28337da2899SCharles.Forsyth static void
termset(void)28437da2899SCharles.Forsyth termset(void)
28537da2899SCharles.Forsyth {
28637da2899SCharles.Forsyth 	struct termios t;
28737da2899SCharles.Forsyth 
28837da2899SCharles.Forsyth 	tcgetattr(0, &t);
28937da2899SCharles.Forsyth 	tinit = t;
29037da2899SCharles.Forsyth 	t.c_lflag &= ~(ICANON|ECHO|ISIG);
29137da2899SCharles.Forsyth 	t.c_cc[VMIN] = 1;
29237da2899SCharles.Forsyth 	t.c_cc[VTIME] = 0;
29337da2899SCharles.Forsyth 	tcsetattr(0, TCSANOW, &t);
29437da2899SCharles.Forsyth }
29537da2899SCharles.Forsyth 
29637da2899SCharles.Forsyth static void
termrestore(void)29737da2899SCharles.Forsyth termrestore(void)
29837da2899SCharles.Forsyth {
29937da2899SCharles.Forsyth 	tcsetattr(0, TCSANOW, &tinit);
30037da2899SCharles.Forsyth }
30137da2899SCharles.Forsyth 
30237da2899SCharles.Forsyth void
cleanexit(int x)30337da2899SCharles.Forsyth cleanexit(int x)
30437da2899SCharles.Forsyth {
30537da2899SCharles.Forsyth 	USED(x);
30637da2899SCharles.Forsyth 
30737da2899SCharles.Forsyth 	if(up->intwait) {
30837da2899SCharles.Forsyth 		up->intwait = 0;
30937da2899SCharles.Forsyth 		return;
31037da2899SCharles.Forsyth 	}
31137da2899SCharles.Forsyth 
31237da2899SCharles.Forsyth 	if(dflag == 0)
31337da2899SCharles.Forsyth 		termrestore();
31437da2899SCharles.Forsyth 
31537da2899SCharles.Forsyth 	kill(0, SIGKILL);
31637da2899SCharles.Forsyth 	exit(0);
31737da2899SCharles.Forsyth }
31837da2899SCharles.Forsyth 
31937da2899SCharles.Forsyth void
osreboot(char * file,char ** argv)32037da2899SCharles.Forsyth osreboot(char *file, char **argv)
32137da2899SCharles.Forsyth {
32237da2899SCharles.Forsyth 	if(dflag == 0)
32337da2899SCharles.Forsyth 		termrestore();
32437da2899SCharles.Forsyth 	execvp(file, argv);
32537da2899SCharles.Forsyth 	panic("reboot failure");
32637da2899SCharles.Forsyth }
32737da2899SCharles.Forsyth 
32837da2899SCharles.Forsyth int gidnobody= -1, uidnobody= -1;
32937da2899SCharles.Forsyth 
33037da2899SCharles.Forsyth void
getnobody()33137da2899SCharles.Forsyth getnobody()
33237da2899SCharles.Forsyth {
33337da2899SCharles.Forsyth 	struct passwd *pwd;
33437da2899SCharles.Forsyth 
33537da2899SCharles.Forsyth 	if(pwd = getpwnam("nobody")) {
33637da2899SCharles.Forsyth 		uidnobody = pwd->pw_uid;
33737da2899SCharles.Forsyth 		gidnobody = pwd->pw_gid;
33837da2899SCharles.Forsyth 	}
33937da2899SCharles.Forsyth }
34037da2899SCharles.Forsyth 
34137da2899SCharles.Forsyth void
libinit(char * imod)34237da2899SCharles.Forsyth libinit(char *imod)
34337da2899SCharles.Forsyth {
34437da2899SCharles.Forsyth 	struct passwd *pw;
34537da2899SCharles.Forsyth 	Proc *p;
34637da2899SCharles.Forsyth 	void *tos;
34737da2899SCharles.Forsyth 	char sys[64];
34837da2899SCharles.Forsyth 
34937da2899SCharles.Forsyth 	setsid();
35037da2899SCharles.Forsyth 
35137da2899SCharles.Forsyth 	gethostname(sys, sizeof(sys));
35237da2899SCharles.Forsyth 	kstrdup(&ossysname, sys);
35337da2899SCharles.Forsyth 	getnobody();
35437da2899SCharles.Forsyth 
35537da2899SCharles.Forsyth 	if(dflag == 0)
35637da2899SCharles.Forsyth 		termset();
35737da2899SCharles.Forsyth 
35837da2899SCharles.Forsyth 	setsigs();
35937da2899SCharles.Forsyth 
36037da2899SCharles.Forsyth 	p = newproc();
36137da2899SCharles.Forsyth 	p->kstack = stackalloc(p, &tos);
36237da2899SCharles.Forsyth 
36337da2899SCharles.Forsyth 	pw = getpwuid(getuid());
36437da2899SCharles.Forsyth 	if(pw != nil)
36537da2899SCharles.Forsyth 		kstrdup(&eve, pw->pw_name);
36637da2899SCharles.Forsyth 	else
36737da2899SCharles.Forsyth 		print("cannot getpwuid\n");
36837da2899SCharles.Forsyth 
36937da2899SCharles.Forsyth 	p->env->uid = getuid();
37037da2899SCharles.Forsyth 	p->env->gid = getgid();
37137da2899SCharles.Forsyth 
37237da2899SCharles.Forsyth 	executeonnewstack(tos, emuinit, imod);
37337da2899SCharles.Forsyth }
37437da2899SCharles.Forsyth 
37537da2899SCharles.Forsyth int
readkbd(void)37637da2899SCharles.Forsyth readkbd(void)
37737da2899SCharles.Forsyth {
37837da2899SCharles.Forsyth 	int n;
37937da2899SCharles.Forsyth 	char buf[1];
38037da2899SCharles.Forsyth 
38137da2899SCharles.Forsyth 	n = read(0, buf, sizeof(buf));
38237da2899SCharles.Forsyth 	if(n < 0)
38337da2899SCharles.Forsyth 		print("keyboard close (n=%d, %s)\n", n, strerror(errno));
38437da2899SCharles.Forsyth 	if(n <= 0)
38537da2899SCharles.Forsyth 		pexit("keyboard thread", 0);
38637da2899SCharles.Forsyth 
38737da2899SCharles.Forsyth 	switch(buf[0]) {
38837da2899SCharles.Forsyth 	case '\r':
38937da2899SCharles.Forsyth 		buf[0] = '\n';
39037da2899SCharles.Forsyth 		break;
39137da2899SCharles.Forsyth 	case DELETE:
39237da2899SCharles.Forsyth 		cleanexit(0);
39337da2899SCharles.Forsyth 		break;
39437da2899SCharles.Forsyth 	}
39537da2899SCharles.Forsyth 	return buf[0];
39637da2899SCharles.Forsyth }
39737da2899SCharles.Forsyth 
39837da2899SCharles.Forsyth /*
39937da2899SCharles.Forsyth  * Return an abitrary millisecond clock time
40037da2899SCharles.Forsyth  */
40137da2899SCharles.Forsyth long
osmillisec(void)40237da2899SCharles.Forsyth osmillisec(void)
40337da2899SCharles.Forsyth {
40437da2899SCharles.Forsyth 	static long sec0 = 0, usec0;
40537da2899SCharles.Forsyth 	struct timeval t;
40637da2899SCharles.Forsyth 
40737da2899SCharles.Forsyth 	if(gettimeofday(&t,(struct timezone*)0)<0)
40837da2899SCharles.Forsyth 		return 0;
40937da2899SCharles.Forsyth 	if(sec0==0) {
41037da2899SCharles.Forsyth 		sec0 = t.tv_sec;
41137da2899SCharles.Forsyth 		usec0 = t.tv_usec;
41237da2899SCharles.Forsyth 	}
41337da2899SCharles.Forsyth 	return (t.tv_sec-sec0)*1000+(t.tv_usec-usec0+500)/1000;
41437da2899SCharles.Forsyth }
41537da2899SCharles.Forsyth 
41637da2899SCharles.Forsyth int
limbosleep(ulong milsec)41737da2899SCharles.Forsyth limbosleep(ulong milsec)
41837da2899SCharles.Forsyth {
41937da2899SCharles.Forsyth 	return osmillisleep(milsec);
42037da2899SCharles.Forsyth }
42137da2899SCharles.Forsyth 
42237da2899SCharles.Forsyth /*
42337da2899SCharles.Forsyth  * Return the time since the epoch in nanoseconds and microseconds
42437da2899SCharles.Forsyth  * The epoch is defined at 1 Jan 1970
42537da2899SCharles.Forsyth  */
42637da2899SCharles.Forsyth vlong
osnsec(void)42737da2899SCharles.Forsyth osnsec(void)
42837da2899SCharles.Forsyth {
42937da2899SCharles.Forsyth 	struct timeval t;
43037da2899SCharles.Forsyth 
43137da2899SCharles.Forsyth 	gettimeofday(&t, nil);
43237da2899SCharles.Forsyth 	return (vlong)t.tv_sec*1000000000L + t.tv_usec*1000;
43337da2899SCharles.Forsyth }
43437da2899SCharles.Forsyth 
43537da2899SCharles.Forsyth vlong
osusectime(void)43637da2899SCharles.Forsyth osusectime(void)
43737da2899SCharles.Forsyth {
43837da2899SCharles.Forsyth 	struct timeval t;
43937da2899SCharles.Forsyth 
44037da2899SCharles.Forsyth 	gettimeofday(&t, nil);
44137da2899SCharles.Forsyth 	return (vlong)t.tv_sec * 1000000 + t.tv_usec;
44237da2899SCharles.Forsyth }
44337da2899SCharles.Forsyth 
44437da2899SCharles.Forsyth int
osmillisleep(ulong milsec)44537da2899SCharles.Forsyth osmillisleep(ulong milsec)
44637da2899SCharles.Forsyth {
44737da2899SCharles.Forsyth 	struct timespec time;
44837da2899SCharles.Forsyth 
44937da2899SCharles.Forsyth 	time.tv_sec = milsec / 1000;
45037da2899SCharles.Forsyth 	time.tv_nsec = (milsec % 1000) * 1000000;
45137da2899SCharles.Forsyth 	nanosleep(&time, 0);
45237da2899SCharles.Forsyth 	return 0;
45337da2899SCharles.Forsyth }
45437da2899SCharles.Forsyth 
45537da2899SCharles.Forsyth void
osyield(void)45637da2899SCharles.Forsyth osyield(void)
45737da2899SCharles.Forsyth {
45837da2899SCharles.Forsyth 	sched_yield();
45937da2899SCharles.Forsyth }
46037da2899SCharles.Forsyth 
46137da2899SCharles.Forsyth void
ospause(void)46237da2899SCharles.Forsyth ospause(void)
46337da2899SCharles.Forsyth {
46437da2899SCharles.Forsyth 	for(;;)
46537da2899SCharles.Forsyth 		pause();
46637da2899SCharles.Forsyth }
46737da2899SCharles.Forsyth 
46837da2899SCharles.Forsyth void
oslopri(void)46937da2899SCharles.Forsyth oslopri(void)
47037da2899SCharles.Forsyth {
47137da2899SCharles.Forsyth 	setpriority(PRIO_PROCESS, 0, getpriority(PRIO_PROCESS,0)+4);
47237da2899SCharles.Forsyth }
47337da2899SCharles.Forsyth 
47437da2899SCharles.Forsyth static struct {
47537da2899SCharles.Forsyth 	Lock l;
47637da2899SCharles.Forsyth 	void *free;
47737da2899SCharles.Forsyth } stacklist;
47837da2899SCharles.Forsyth 
47937da2899SCharles.Forsyth static void
_stackfree(void * stack)48037da2899SCharles.Forsyth _stackfree(void *stack)
48137da2899SCharles.Forsyth {
48237da2899SCharles.Forsyth 	*((void **)stack) = stacklist.free;
48337da2899SCharles.Forsyth 	stacklist.free = stack;
48437da2899SCharles.Forsyth }
48537da2899SCharles.Forsyth 
48637da2899SCharles.Forsyth static void
stackfreeandexit(void * stack)48737da2899SCharles.Forsyth stackfreeandexit(void *stack)
48837da2899SCharles.Forsyth {
48937da2899SCharles.Forsyth 	lock(&stacklist.l);
49037da2899SCharles.Forsyth 	_stackfree(stack);
49137da2899SCharles.Forsyth 	unlockandexit(&stacklist.l.val);
49237da2899SCharles.Forsyth }
49337da2899SCharles.Forsyth 
49437da2899SCharles.Forsyth static void *
stackalloc(Proc * p,void ** tos)49537da2899SCharles.Forsyth stackalloc(Proc *p, void **tos)
49637da2899SCharles.Forsyth {
49737da2899SCharles.Forsyth 	void *rv;
49837da2899SCharles.Forsyth 	lock(&stacklist.l);
49937da2899SCharles.Forsyth 	if (stacklist.free == 0) {
50037da2899SCharles.Forsyth 		int x;
50137da2899SCharles.Forsyth 		/*
50237da2899SCharles.Forsyth 		 * obtain some more by using sbrk()
50337da2899SCharles.Forsyth 		 */
50437da2899SCharles.Forsyth 		void *more = sbrk(KSTACK * (NSTACKSPERALLOC + 1));
50537da2899SCharles.Forsyth 		if (more == 0)
50637da2899SCharles.Forsyth 			panic("stackalloc: no more stacks");
50737da2899SCharles.Forsyth 		/*
50837da2899SCharles.Forsyth 		 * align to KSTACK
50937da2899SCharles.Forsyth 		 */
51037da2899SCharles.Forsyth 		more = (void *)((((unsigned long)more) + (KSTACK - 1)) & ~(KSTACK - 1));
51137da2899SCharles.Forsyth 		/*
51237da2899SCharles.Forsyth 		 * free all the new stacks onto the freelist
51337da2899SCharles.Forsyth 		 */
51437da2899SCharles.Forsyth 		for (x = 0; x < NSTACKSPERALLOC; x++)
51537da2899SCharles.Forsyth 			_stackfree((char *)more + KSTACK * x);
51637da2899SCharles.Forsyth 	}
51737da2899SCharles.Forsyth 	rv = stacklist.free;
51837da2899SCharles.Forsyth 	stacklist.free = *(void **)rv;
51937da2899SCharles.Forsyth 	unlock(&stacklist.l);
52037da2899SCharles.Forsyth 	*tos = rv + KSTACK - sizeof(void*);
52137da2899SCharles.Forsyth 	*(Proc **)rv = p;
52237da2899SCharles.Forsyth 	return rv;
52337da2899SCharles.Forsyth }
524132f29a5Sforsyth 
525132f29a5Sforsyth int
segflush(void * a,ulong n)526132f29a5Sforsyth segflush(void *a, ulong n)
527132f29a5Sforsyth {
528132f29a5Sforsyth 	USED(a);
529132f29a5Sforsyth 	USED(n);
530132f29a5Sforsyth 	return 0;
531132f29a5Sforsyth }
532