xref: /inferno-os/emu/DragonFly/os.c (revision ce3f4532f3f68d5c3419c4581504faff3a1d2820)
107f684ffSforsyth #include	"dat.h"
207f684ffSforsyth #include	"fns.h"
307f684ffSforsyth #include	"error.h"
407f684ffSforsyth #undef getwd
507f684ffSforsyth #include	<signal.h>
607f684ffSforsyth #include 	<sys/socket.h>
707f684ffSforsyth #include	<time.h>
807f684ffSforsyth #include	<sys/time.h>
907f684ffSforsyth #include	<termios.h>
1007f684ffSforsyth #include	<sched.h>
1107f684ffSforsyth #include	<pwd.h>
1207f684ffSforsyth #include	<errno.h>
1307f684ffSforsyth #include	<unistd.h>
1407f684ffSforsyth #include	<sys/resource.h>
1507f684ffSforsyth 
1607f684ffSforsyth enum
1707f684ffSforsyth {
1807f684ffSforsyth 	DELETE  = 0x7F,
1907f684ffSforsyth 	NSTACKSPERALLOC = 16,
2007f684ffSforsyth 	X11STACK=	256*1024
2107f684ffSforsyth };
2207f684ffSforsyth char *hosttype = "DragonFly";
2307f684ffSforsyth 
2407f684ffSforsyth extern void unlockandexit(int*);
2507f684ffSforsyth extern void executeonnewstack(void*, void (*f)(void*), void*);
2607f684ffSforsyth static void *stackalloc(Proc *p, void **tos);
2707f684ffSforsyth static void stackfreeandexit(void *stack);
2807f684ffSforsyth 
2907f684ffSforsyth extern int dflag;
3007f684ffSforsyth 
3107f684ffSforsyth void
pexit(char * msg,int t)3207f684ffSforsyth pexit(char *msg, int t)
3307f684ffSforsyth {
3407f684ffSforsyth 	Osenv *e;
3507f684ffSforsyth 	Proc *p;
3607f684ffSforsyth 	void *kstack;
3707f684ffSforsyth 
3807f684ffSforsyth 	lock(&procs.l);
3907f684ffSforsyth 	p = up;
4007f684ffSforsyth 	if(p->prev)
4107f684ffSforsyth 		p->prev->next = p->next;
4207f684ffSforsyth 	else
4307f684ffSforsyth 		procs.head = p->next;
4407f684ffSforsyth 
4507f684ffSforsyth 	if(up->next)
4607f684ffSforsyth 		p->next->prev = p->prev;
4707f684ffSforsyth 	else
4807f684ffSforsyth 		procs.tail = p->prev;
4907f684ffSforsyth 	unlock(&procs.l);
5007f684ffSforsyth 
5107f684ffSforsyth 	if(0)
5207f684ffSforsyth 		print("pexit: %s: %s\n", up->text, msg);
5307f684ffSforsyth 
5407f684ffSforsyth 	e = up->env;
5507f684ffSforsyth 	if(e != nil) {
5607f684ffSforsyth 		closefgrp(e->fgrp);
5707f684ffSforsyth 		closepgrp(e->pgrp);
5807f684ffSforsyth 		closeegrp(e->egrp);
5907f684ffSforsyth 		closesigs(e->sigs);
6007f684ffSforsyth 	}
6107f684ffSforsyth 	kstack = p->kstack;
6207f684ffSforsyth 	free(p->prog);
6307f684ffSforsyth 	free(p);
6407f684ffSforsyth 	if(kstack != nil)
6507f684ffSforsyth 		stackfreeandexit(kstack);
6607f684ffSforsyth }
6707f684ffSforsyth 
6807f684ffSforsyth void
trapBUS(int signo,siginfo_t * info,void * context)6907f684ffSforsyth trapBUS(int signo, siginfo_t *info, void *context)
7007f684ffSforsyth {
7107f684ffSforsyth 	if(info)
7207f684ffSforsyth 		print("trapBUS: signo: %d code: %d addr: %lx\n",
7307f684ffSforsyth 		info->si_signo, info->si_code, info->si_addr);
7407f684ffSforsyth 	else
7507f684ffSforsyth 		print("trapBUS: no info\n");
7607f684ffSforsyth 	disfault(nil, "Bus error");
7707f684ffSforsyth }
7807f684ffSforsyth 
7907f684ffSforsyth static void
trapUSR1(int signo)8007f684ffSforsyth trapUSR1(int signo)
8107f684ffSforsyth {
8207f684ffSforsyth 	int intwait;
8307f684ffSforsyth 
8407f684ffSforsyth 	USED(signo);
8507f684ffSforsyth 
8607f684ffSforsyth 	intwait = up->intwait;
8707f684ffSforsyth 	up->intwait = 0;	/* clear it to let proc continue in osleave */
8807f684ffSforsyth 
8907f684ffSforsyth 	if(up->type != Interp)		/* Used to unblock pending I/O */
9007f684ffSforsyth 		return;
9107f684ffSforsyth 	if(intwait == 0)		/* Not posted so its a sync error */
9207f684ffSforsyth 		disfault(nil, Eintr);	/* Should never happen */
9307f684ffSforsyth }
9407f684ffSforsyth 
9507f684ffSforsyth static void
trapUSR2(int signo)9607f684ffSforsyth trapUSR2(int signo)
9707f684ffSforsyth {
9807f684ffSforsyth 	USED(signo);
9907f684ffSforsyth 	/* we've done our work of interrupting sigsuspend */
10007f684ffSforsyth }
10107f684ffSforsyth 
10207f684ffSforsyth static void
trapILL(int signo)10307f684ffSforsyth trapILL(int signo)
10407f684ffSforsyth {
10507f684ffSforsyth 	disfault(nil, "Illegal instruction");
10607f684ffSforsyth }
10707f684ffSforsyth 
10807f684ffSforsyth static void
trapSEGV(int signo)10907f684ffSforsyth trapSEGV(int signo)
11007f684ffSforsyth {
11107f684ffSforsyth 	disfault(nil, "Segmentation violation");
11207f684ffSforsyth }
11307f684ffSforsyth 
11407f684ffSforsyth static void
trapFPE(int signo)11507f684ffSforsyth trapFPE(int signo)
11607f684ffSforsyth {
1176bf3ce61Sforsyth 	char buf[64];
11807f684ffSforsyth 	USED(signo);
1196bf3ce61Sforsyth 	snprint(buf, sizeof(buf), "sys: fp: exception status=%.4lux", getfsr());
1206bf3ce61Sforsyth 	disfault(nil, buf);
12107f684ffSforsyth }
12207f684ffSforsyth 
12307f684ffSforsyth static sigset_t initmask;
12407f684ffSforsyth 
12507f684ffSforsyth static void
setsigs(void)12607f684ffSforsyth setsigs(void)
12707f684ffSforsyth {
12807f684ffSforsyth 	struct sigaction act;
12907f684ffSforsyth 	sigset_t mask;
13007f684ffSforsyth 
13107f684ffSforsyth 	memset(&act, 0 , sizeof(act));
13207f684ffSforsyth 	sigemptyset(&initmask);
13307f684ffSforsyth 
13407f684ffSforsyth 	signal(SIGPIPE, SIG_IGN);	/* prevent signal when devcmd child exits */
13507f684ffSforsyth 	if(signal(SIGTERM, SIG_IGN) != SIG_IGN)
13607f684ffSforsyth 		signal(SIGTERM, cleanexit);
13707f684ffSforsyth 
13807f684ffSforsyth 	act.sa_handler = trapUSR1;
13907f684ffSforsyth 	act.sa_mask = initmask;
14007f684ffSforsyth 	sigaction(SIGUSR1, &act, nil);
14107f684ffSforsyth 
14207f684ffSforsyth 	act.sa_handler = trapUSR2;
14307f684ffSforsyth 	sigaction(SIGUSR2, &act, nil);
14407f684ffSforsyth 	sigemptyset(&mask);
14507f684ffSforsyth 	sigaddset(&mask, SIGUSR2);
14607f684ffSforsyth 	sigaddset(&initmask, SIGUSR2);
14707f684ffSforsyth 	sigprocmask(SIG_BLOCK, &mask, NULL);
14807f684ffSforsyth 
14907f684ffSforsyth 	/*
15007f684ffSforsyth  	 * prevent Zombies forming when any process terminates
15107f684ffSforsyth 	 */
15207f684ffSforsyth 	act.sa_sigaction = 0;
15307f684ffSforsyth 	act.sa_flags |= SA_NOCLDWAIT;
15407f684ffSforsyth 	if(sigaction(SIGCHLD, &act, nil))
15507f684ffSforsyth 		panic("sigaction SIGCHLD");
15607f684ffSforsyth 
15707f684ffSforsyth 	if(sflag == 0) {
15807f684ffSforsyth 		act.sa_sigaction = trapBUS;
15907f684ffSforsyth 		act.sa_flags |= SA_SIGINFO;
16007f684ffSforsyth 		if(sigaction(SIGBUS, &act, nil))
16107f684ffSforsyth 			panic("sigaction SIGBUS");
16207f684ffSforsyth 		act.sa_handler = trapILL;
16307f684ffSforsyth 		if(sigaction(SIGILL, &act, nil))
16407f684ffSforsyth 			panic("sigaction SIGBUS");
16507f684ffSforsyth 		act.sa_handler = trapSEGV;
16607f684ffSforsyth 		if(sigaction(SIGSEGV, &act, nil))
16707f684ffSforsyth 			panic("sigaction SIGSEGV");
16807f684ffSforsyth 		act.sa_handler = trapFPE;
16907f684ffSforsyth 		if(sigaction(SIGFPE, &act, nil))
17007f684ffSforsyth 			panic("sigaction SIGFPE");
17107f684ffSforsyth 		if(sigaddset(&initmask, SIGINT) == -1)
17207f684ffSforsyth 			panic("sigaddset");
17307f684ffSforsyth 	}
17407f684ffSforsyth 	if(sigprocmask(SIG_BLOCK, &initmask, nil)!= 0)
17507f684ffSforsyth 		panic("sigprocmask");
17607f684ffSforsyth }
17707f684ffSforsyth 
17807f684ffSforsyth static int
tramp(void * arg)17907f684ffSforsyth tramp(void *arg)
18007f684ffSforsyth {
18107f684ffSforsyth 	Proc *p;
18207f684ffSforsyth 
18307f684ffSforsyth 	p = arg;
18407f684ffSforsyth 	p->pid = p->sigid = getpid();
18507f684ffSforsyth 	sigprocmask(SIG_BLOCK, &initmask, nil);	/* in 5.3, rfork_thread doesn't copy from parent, contrary to docs? */
18607f684ffSforsyth 	(*p->func)(p->arg);
18707f684ffSforsyth 	pexit("{Tramp}", 0);
18807f684ffSforsyth 	_exit(0);
18907f684ffSforsyth }
19007f684ffSforsyth 
191*1343b7e5Sforsyth void
kproc(char * name,void (* func)(void *),void * arg,int flags)19207f684ffSforsyth kproc(char *name, void (*func)(void*), void *arg, int flags)
19307f684ffSforsyth {
19407f684ffSforsyth 	Proc *p;
19507f684ffSforsyth 	Pgrp *pg;
19607f684ffSforsyth 	Fgrp *fg;
19707f684ffSforsyth 	Egrp *eg;
19807f684ffSforsyth 	int pid;
19907f684ffSforsyth 	void *tos;
20007f684ffSforsyth 
20107f684ffSforsyth 	p = newproc();
20207f684ffSforsyth 
20307f684ffSforsyth 	if(flags & KPDUPPG) {
20407f684ffSforsyth 		pg = up->env->pgrp;
20507f684ffSforsyth 		incref(&pg->r);
20607f684ffSforsyth 		p->env->pgrp = pg;
20707f684ffSforsyth 	}
20807f684ffSforsyth 	if(flags & KPDUPFDG) {
20907f684ffSforsyth 		fg = up->env->fgrp;
21007f684ffSforsyth 		incref(&fg->r);
21107f684ffSforsyth 		p->env->fgrp = fg;
21207f684ffSforsyth 	}
21307f684ffSforsyth 	if(flags & KPDUPENVG) {
21407f684ffSforsyth 		eg = up->env->egrp;
21507f684ffSforsyth 		incref(&eg->r);
21607f684ffSforsyth 		p->env->egrp = eg;
21707f684ffSforsyth 	}
21807f684ffSforsyth 
21907f684ffSforsyth 	p->env->uid = up->env->uid;
22007f684ffSforsyth 	p->env->gid = up->env->gid;
22107f684ffSforsyth 	kstrdup(&p->env->user, up->env->user);
22207f684ffSforsyth 
22307f684ffSforsyth 	strcpy(p->text, name);
22407f684ffSforsyth 
22507f684ffSforsyth 	p->func = func;
22607f684ffSforsyth 	p->arg = arg;
22707f684ffSforsyth 
22807f684ffSforsyth 	lock(&procs.l);
22907f684ffSforsyth 	if(procs.tail != nil) {
23007f684ffSforsyth 		p->prev = procs.tail;
23107f684ffSforsyth 		procs.tail->next = p;
23207f684ffSforsyth 	}
23307f684ffSforsyth 	else {
23407f684ffSforsyth 		procs.head = p;
23507f684ffSforsyth 		p->prev = nil;
23607f684ffSforsyth 	}
23707f684ffSforsyth 	procs.tail = p;
23807f684ffSforsyth 	unlock(&procs.l);
23907f684ffSforsyth 
24007f684ffSforsyth 	if(flags & KPX11){
24107f684ffSforsyth 		p->kstack = nil;	/* never freed; also up not defined */
24207f684ffSforsyth 		tos = (char*)mallocz(X11STACK, 0) + X11STACK - sizeof(void*);
24307f684ffSforsyth 	}else
24407f684ffSforsyth 		p->kstack = stackalloc(p, &tos);
24507f684ffSforsyth 	pid = rfork_thread(RFPROC|RFMEM|RFNOWAIT, tos, tramp, p);
24607f684ffSforsyth 	if(pid < 0)
247*1343b7e5Sforsyth 		panic("rfork");
24807f684ffSforsyth }
24907f684ffSforsyth 
25007f684ffSforsyth void
oshostintr(Proc * p)25107f684ffSforsyth oshostintr(Proc *p)
25207f684ffSforsyth {
25307f684ffSforsyth 	kill(p->sigid, SIGUSR1);
25407f684ffSforsyth }
25507f684ffSforsyth 
25607f684ffSforsyth void
osblock(void)25707f684ffSforsyth osblock(void)
25807f684ffSforsyth {
25907f684ffSforsyth 	sigset_t mask;
26007f684ffSforsyth 
26107f684ffSforsyth 	sigprocmask(SIG_SETMASK, NULL, &mask);
26207f684ffSforsyth 	sigdelset(&mask, SIGUSR2);
26307f684ffSforsyth 	sigsuspend(&mask);
26407f684ffSforsyth }
26507f684ffSforsyth 
26607f684ffSforsyth void
osready(Proc * p)26707f684ffSforsyth osready(Proc *p)
26807f684ffSforsyth {
26907f684ffSforsyth 	if(kill(p->sigid, SIGUSR2) < 0)
27007f684ffSforsyth 		fprint(2, "emu: osready failed: pid %d: %s\n", p->sigid, strerror(errno));
27107f684ffSforsyth }
27207f684ffSforsyth 
27307f684ffSforsyth void
oslongjmp(void * regs,osjmpbuf env,int val)27407f684ffSforsyth oslongjmp(void *regs, osjmpbuf env, int val)
27507f684ffSforsyth {
27607f684ffSforsyth 	USED(regs);
27707f684ffSforsyth 	siglongjmp(env, val);
27807f684ffSforsyth }
27907f684ffSforsyth 
28007f684ffSforsyth struct termios tinit;
28107f684ffSforsyth 
28207f684ffSforsyth static void
termset(void)28307f684ffSforsyth termset(void)
28407f684ffSforsyth {
28507f684ffSforsyth 	struct termios t;
28607f684ffSforsyth 
28707f684ffSforsyth 	tcgetattr(0, &t);
28807f684ffSforsyth 	tinit = t;
28907f684ffSforsyth 	t.c_lflag &= ~(ICANON|ECHO|ISIG);
29007f684ffSforsyth 	t.c_cc[VMIN] = 1;
29107f684ffSforsyth 	t.c_cc[VTIME] = 0;
29207f684ffSforsyth 	tcsetattr(0, TCSANOW, &t);
29307f684ffSforsyth }
29407f684ffSforsyth 
29507f684ffSforsyth static void
termrestore(void)29607f684ffSforsyth termrestore(void)
29707f684ffSforsyth {
29807f684ffSforsyth 	tcsetattr(0, TCSANOW, &tinit);
29907f684ffSforsyth }
30007f684ffSforsyth 
30107f684ffSforsyth void
cleanexit(int x)30207f684ffSforsyth cleanexit(int x)
30307f684ffSforsyth {
30407f684ffSforsyth 	USED(x);
30507f684ffSforsyth 
30607f684ffSforsyth 	if(up->intwait) {
30707f684ffSforsyth 		up->intwait = 0;
30807f684ffSforsyth 		return;
30907f684ffSforsyth 	}
31007f684ffSforsyth 
31107f684ffSforsyth 	if(dflag == 0)
31207f684ffSforsyth 		termrestore();
31307f684ffSforsyth 
31407f684ffSforsyth 	kill(0, SIGKILL);
31507f684ffSforsyth 	exit(0);
31607f684ffSforsyth }
31707f684ffSforsyth 
31807f684ffSforsyth void
osreboot(char * file,char ** argv)31907f684ffSforsyth osreboot(char *file, char **argv)
32007f684ffSforsyth {
32107f684ffSforsyth 	if(dflag == 0)
32207f684ffSforsyth 		termrestore();
32307f684ffSforsyth 	execvp(file, argv);
32407f684ffSforsyth 	panic("reboot failure");
32507f684ffSforsyth }
32607f684ffSforsyth 
32707f684ffSforsyth int gidnobody= -1, uidnobody= -1;
32807f684ffSforsyth 
32907f684ffSforsyth void
getnobody()33007f684ffSforsyth getnobody()
33107f684ffSforsyth {
33207f684ffSforsyth 	struct passwd *pwd;
33307f684ffSforsyth 
33407f684ffSforsyth 	if(pwd = getpwnam("nobody")) {
33507f684ffSforsyth 		uidnobody = pwd->pw_uid;
33607f684ffSforsyth 		gidnobody = pwd->pw_gid;
33707f684ffSforsyth 	}
33807f684ffSforsyth }
33907f684ffSforsyth 
34007f684ffSforsyth void
libinit(char * imod)34107f684ffSforsyth libinit(char *imod)
34207f684ffSforsyth {
34307f684ffSforsyth 	struct passwd *pw;
34407f684ffSforsyth 	Proc *p;
34507f684ffSforsyth 	void *tos;
34607f684ffSforsyth 	char sys[64];
34707f684ffSforsyth 
34807f684ffSforsyth 	setsid();
34907f684ffSforsyth 
35007f684ffSforsyth 	gethostname(sys, sizeof(sys));
35107f684ffSforsyth 	kstrdup(&ossysname, sys);
35207f684ffSforsyth 	getnobody();
35307f684ffSforsyth 
35407f684ffSforsyth 	if(dflag == 0)
35507f684ffSforsyth 		termset();
35607f684ffSforsyth 
35707f684ffSforsyth 	setsigs();
35807f684ffSforsyth 
35907f684ffSforsyth 	p = newproc();
36007f684ffSforsyth 	p->kstack = stackalloc(p, &tos);
36107f684ffSforsyth 
36207f684ffSforsyth 	pw = getpwuid(getuid());
36307f684ffSforsyth 	if(pw != nil)
36407f684ffSforsyth 		kstrdup(&eve, pw->pw_name);
36507f684ffSforsyth 	else
36607f684ffSforsyth 		print("cannot getpwuid\n");
36707f684ffSforsyth 
36807f684ffSforsyth 	p->env->uid = getuid();
36907f684ffSforsyth 	p->env->gid = getgid();
37007f684ffSforsyth 
37107f684ffSforsyth 	executeonnewstack(tos, emuinit, imod);
37207f684ffSforsyth }
37307f684ffSforsyth 
37407f684ffSforsyth int
readkbd(void)37507f684ffSforsyth readkbd(void)
37607f684ffSforsyth {
37707f684ffSforsyth 	int n;
37807f684ffSforsyth 	char buf[1];
37907f684ffSforsyth 
38007f684ffSforsyth 	n = read(0, buf, sizeof(buf));
38107f684ffSforsyth 	if(n < 0)
38207f684ffSforsyth 		print("keyboard close (n=%d, %s)\n", n, strerror(errno));
38307f684ffSforsyth 	if(n <= 0)
38407f684ffSforsyth 		pexit("keyboard thread", 0);
38507f684ffSforsyth 
38607f684ffSforsyth 	switch(buf[0]) {
38707f684ffSforsyth 	case '\r':
38807f684ffSforsyth 		buf[0] = '\n';
38907f684ffSforsyth 		break;
39007f684ffSforsyth 	case DELETE:
39107f684ffSforsyth 		cleanexit(0);
39207f684ffSforsyth 		break;
39307f684ffSforsyth 	}
39407f684ffSforsyth 	return buf[0];
39507f684ffSforsyth }
39607f684ffSforsyth 
39707f684ffSforsyth /*
39807f684ffSforsyth  * Return an abitrary millisecond clock time
39907f684ffSforsyth  */
40007f684ffSforsyth long
osmillisec(void)40107f684ffSforsyth osmillisec(void)
40207f684ffSforsyth {
40307f684ffSforsyth 	static long sec0 = 0, usec0;
40407f684ffSforsyth 	struct timeval t;
40507f684ffSforsyth 
40607f684ffSforsyth 	if(gettimeofday(&t,(struct timezone*)0)<0)
40707f684ffSforsyth 		return 0;
40807f684ffSforsyth 	if(sec0==0) {
40907f684ffSforsyth 		sec0 = t.tv_sec;
41007f684ffSforsyth 		usec0 = t.tv_usec;
41107f684ffSforsyth 	}
41207f684ffSforsyth 	return (t.tv_sec-sec0)*1000+(t.tv_usec-usec0+500)/1000;
41307f684ffSforsyth }
41407f684ffSforsyth 
41507f684ffSforsyth int
limbosleep(ulong milsec)41607f684ffSforsyth limbosleep(ulong milsec)
41707f684ffSforsyth {
41807f684ffSforsyth 	return osmillisleep(milsec);
41907f684ffSforsyth }
42007f684ffSforsyth 
42107f684ffSforsyth /*
42207f684ffSforsyth  * Return the time since the epoch in nanoseconds and microseconds
42307f684ffSforsyth  * The epoch is defined at 1 Jan 1970
42407f684ffSforsyth  */
42507f684ffSforsyth vlong
osnsec(void)42607f684ffSforsyth osnsec(void)
42707f684ffSforsyth {
42807f684ffSforsyth 	struct timeval t;
42907f684ffSforsyth 
43007f684ffSforsyth 	gettimeofday(&t, nil);
43107f684ffSforsyth 	return (vlong)t.tv_sec*1000000000L + t.tv_usec*1000;
43207f684ffSforsyth }
43307f684ffSforsyth 
43407f684ffSforsyth vlong
osusectime(void)43507f684ffSforsyth osusectime(void)
43607f684ffSforsyth {
43707f684ffSforsyth 	struct timeval t;
43807f684ffSforsyth 
43907f684ffSforsyth 	gettimeofday(&t, nil);
44007f684ffSforsyth 	return (vlong)t.tv_sec * 1000000 + t.tv_usec;
44107f684ffSforsyth }
44207f684ffSforsyth 
44307f684ffSforsyth int
osmillisleep(ulong milsec)44407f684ffSforsyth osmillisleep(ulong milsec)
44507f684ffSforsyth {
44607f684ffSforsyth 	struct timespec time;
44707f684ffSforsyth 
44807f684ffSforsyth 	time.tv_sec = milsec / 1000;
44907f684ffSforsyth 	time.tv_nsec = (milsec % 1000) * 1000000;
45007f684ffSforsyth 	nanosleep(&time, 0);
45107f684ffSforsyth 	return 0;
45207f684ffSforsyth }
45307f684ffSforsyth 
45407f684ffSforsyth void
osyield(void)45507f684ffSforsyth osyield(void)
45607f684ffSforsyth {
45707f684ffSforsyth 	sched_yield();
45807f684ffSforsyth }
45907f684ffSforsyth 
46007f684ffSforsyth void
ospause(void)46107f684ffSforsyth ospause(void)
46207f684ffSforsyth {
46307f684ffSforsyth 	for(;;)
46407f684ffSforsyth 		pause();
46507f684ffSforsyth }
46607f684ffSforsyth 
46707f684ffSforsyth void
oslopri(void)46807f684ffSforsyth oslopri(void)
46907f684ffSforsyth {
47007f684ffSforsyth 	setpriority(PRIO_PROCESS, 0, getpriority(PRIO_PROCESS,0)+4);
47107f684ffSforsyth }
47207f684ffSforsyth 
47307f684ffSforsyth static struct {
47407f684ffSforsyth 	Lock l;
47507f684ffSforsyth 	void *free;
47607f684ffSforsyth } stacklist;
47707f684ffSforsyth 
47807f684ffSforsyth static void
_stackfree(void * stack)47907f684ffSforsyth _stackfree(void *stack)
48007f684ffSforsyth {
48107f684ffSforsyth 	*((void **)stack) = stacklist.free;
48207f684ffSforsyth 	stacklist.free = stack;
48307f684ffSforsyth }
48407f684ffSforsyth 
48507f684ffSforsyth static void
stackfreeandexit(void * stack)48607f684ffSforsyth stackfreeandexit(void *stack)
48707f684ffSforsyth {
48807f684ffSforsyth 	lock(&stacklist.l);
48907f684ffSforsyth 	_stackfree(stack);
49007f684ffSforsyth 	unlockandexit(&stacklist.l.val);
49107f684ffSforsyth }
49207f684ffSforsyth 
49307f684ffSforsyth static void *
stackalloc(Proc * p,void ** tos)49407f684ffSforsyth stackalloc(Proc *p, void **tos)
49507f684ffSforsyth {
49607f684ffSforsyth 	void *rv;
49707f684ffSforsyth 	lock(&stacklist.l);
49807f684ffSforsyth 	if (stacklist.free == 0) {
49907f684ffSforsyth 		int x;
50007f684ffSforsyth 		/*
50107f684ffSforsyth 		 * obtain some more by using sbrk()
50207f684ffSforsyth 		 */
50307f684ffSforsyth 		void *more = sbrk(KSTACK * (NSTACKSPERALLOC + 1));
50407f684ffSforsyth 		if (more == 0)
50507f684ffSforsyth 			panic("stackalloc: no more stacks");
50607f684ffSforsyth 		/*
50707f684ffSforsyth 		 * align to KSTACK
50807f684ffSforsyth 		 */
50907f684ffSforsyth 		more = (void *)((((unsigned long)more) + (KSTACK - 1)) & ~(KSTACK - 1));
51007f684ffSforsyth 		/*
51107f684ffSforsyth 		 * free all the new stacks onto the freelist
51207f684ffSforsyth 		 */
51307f684ffSforsyth 		for (x = 0; x < NSTACKSPERALLOC; x++)
51407f684ffSforsyth 			_stackfree((char *)more + KSTACK * x);
51507f684ffSforsyth 	}
51607f684ffSforsyth 	rv = stacklist.free;
51707f684ffSforsyth 	stacklist.free = *(void **)rv;
51807f684ffSforsyth 	unlock(&stacklist.l);
51907f684ffSforsyth 	*tos = rv + KSTACK - sizeof(void*);
52007f684ffSforsyth 	*(Proc **)rv = p;
52107f684ffSforsyth 	return rv;
52207f684ffSforsyth }
52307f684ffSforsyth 
52407f684ffSforsyth int
segflush(void * a,ulong n)52507f684ffSforsyth segflush(void *a, ulong n)
52607f684ffSforsyth {
52707f684ffSforsyth 	USED(a);
52807f684ffSforsyth 	USED(n);
52907f684ffSforsyth 	return 0;
53007f684ffSforsyth }
531