xref: /plan9/sys/src/9/port/sysproc.c (revision bd2ae673a01b1e9c55f91f61e401358ece1883dd)
13e12c5d1SDavid du Colombier #include	"u.h"
23e12c5d1SDavid du Colombier #include	"../port/lib.h"
33e12c5d1SDavid du Colombier #include	"mem.h"
43e12c5d1SDavid du Colombier #include	"dat.h"
53e12c5d1SDavid du Colombier #include	"fns.h"
63e12c5d1SDavid du Colombier #include	"../port/error.h"
73e12c5d1SDavid du Colombier 
83e12c5d1SDavid du Colombier #include	<a.out.h>
93e12c5d1SDavid du Colombier 
103e12c5d1SDavid du Colombier int	shargs(char*, int, char**);
113e12c5d1SDavid du Colombier 
129a747e4fSDavid du Colombier Ref sysr1ref;
139a747e4fSDavid du Colombier 
143e12c5d1SDavid du Colombier long
153e12c5d1SDavid du Colombier sysr1(ulong *arg)
163e12c5d1SDavid du Colombier {
179a747e4fSDavid du Colombier 	long a;
189a747e4fSDavid du Colombier 
199a747e4fSDavid du Colombier 	a = *arg;
209a747e4fSDavid du Colombier 	if(a > 0)
219a747e4fSDavid du Colombier 		return incref(&sysr1ref);
229a747e4fSDavid du Colombier 	if(a < 0)
239a747e4fSDavid du Colombier 		return decref(&sysr1ref);
249a747e4fSDavid du Colombier 	return sysr1ref.ref;
259a747e4fSDavid du Colombier 
269a747e4fSDavid du Colombier /*
279a747e4fSDavid du Colombier 	extern int chandebug;
289a747e4fSDavid du Colombier 	extern void dumpmount(void);
299a747e4fSDavid du Colombier 
307dd7cddfSDavid du Colombier 	print("[%s %s %lud] r1 = %lud\n", up->user, up->text, up->pid, arg[0]);
319a747e4fSDavid du Colombier 	chandebug=!chandebug;
329a747e4fSDavid du Colombier 	if(chandebug)
339a747e4fSDavid du Colombier 		dumpmount();
349a747e4fSDavid du Colombier 
353e12c5d1SDavid du Colombier 	return 0;
369a747e4fSDavid du Colombier */
373e12c5d1SDavid du Colombier }
383e12c5d1SDavid du Colombier 
393e12c5d1SDavid du Colombier long
403e12c5d1SDavid du Colombier sysrfork(ulong *arg)
413e12c5d1SDavid du Colombier {
427dd7cddfSDavid du Colombier 	Proc *p;
433e12c5d1SDavid du Colombier 	int n, i;
447dd7cddfSDavid du Colombier 	Fgrp *ofg;
457dd7cddfSDavid du Colombier 	Pgrp *opg;
467dd7cddfSDavid du Colombier 	Rgrp *org;
477dd7cddfSDavid du Colombier 	Egrp *oeg;
487dd7cddfSDavid du Colombier 	ulong pid, flag;
497dd7cddfSDavid du Colombier 	Mach *wm;
503e12c5d1SDavid du Colombier 
513e12c5d1SDavid du Colombier 	flag = arg[0];
523e12c5d1SDavid du Colombier 	/* Check flags before we commit */
533e12c5d1SDavid du Colombier 	if((flag & (RFFDG|RFCFDG)) == (RFFDG|RFCFDG))
543e12c5d1SDavid du Colombier 		error(Ebadarg);
553e12c5d1SDavid du Colombier 	if((flag & (RFNAMEG|RFCNAMEG)) == (RFNAMEG|RFCNAMEG))
563e12c5d1SDavid du Colombier 		error(Ebadarg);
573e12c5d1SDavid du Colombier 	if((flag & (RFENVG|RFCENVG)) == (RFENVG|RFCENVG))
583e12c5d1SDavid du Colombier 		error(Ebadarg);
593e12c5d1SDavid du Colombier 
607dd7cddfSDavid du Colombier 	if((flag&RFPROC) == 0) {
617dd7cddfSDavid du Colombier 		if(flag & (RFMEM|RFNOWAIT))
627dd7cddfSDavid du Colombier 			error(Ebadarg);
637dd7cddfSDavid du Colombier 		if(flag & (RFFDG|RFCFDG)) {
647dd7cddfSDavid du Colombier 			ofg = up->fgrp;
657dd7cddfSDavid du Colombier 			if(flag & RFFDG)
667dd7cddfSDavid du Colombier 				up->fgrp = dupfgrp(ofg);
677dd7cddfSDavid du Colombier 			else
687dd7cddfSDavid du Colombier 				up->fgrp = dupfgrp(nil);
697dd7cddfSDavid du Colombier 			closefgrp(ofg);
707dd7cddfSDavid du Colombier 		}
717dd7cddfSDavid du Colombier 		if(flag & (RFNAMEG|RFCNAMEG)) {
727dd7cddfSDavid du Colombier 			opg = up->pgrp;
737dd7cddfSDavid du Colombier 			up->pgrp = newpgrp();
747dd7cddfSDavid du Colombier 			if(flag & RFNAMEG)
757dd7cddfSDavid du Colombier 				pgrpcpy(up->pgrp, opg);
767dd7cddfSDavid du Colombier 			/* inherit noattach */
777dd7cddfSDavid du Colombier 			up->pgrp->noattach = opg->noattach;
787dd7cddfSDavid du Colombier 			closepgrp(opg);
797dd7cddfSDavid du Colombier 		}
807dd7cddfSDavid du Colombier 		if(flag & RFNOMNT)
817dd7cddfSDavid du Colombier 			up->pgrp->noattach = 1;
827dd7cddfSDavid du Colombier 		if(flag & RFREND) {
837dd7cddfSDavid du Colombier 			org = up->rgrp;
847dd7cddfSDavid du Colombier 			up->rgrp = newrgrp();
857dd7cddfSDavid du Colombier 			closergrp(org);
867dd7cddfSDavid du Colombier 		}
877dd7cddfSDavid du Colombier 		if(flag & (RFENVG|RFCENVG)) {
887dd7cddfSDavid du Colombier 			oeg = up->egrp;
897dd7cddfSDavid du Colombier 			up->egrp = smalloc(sizeof(Egrp));
907dd7cddfSDavid du Colombier 			up->egrp->ref = 1;
917dd7cddfSDavid du Colombier 			if(flag & RFENVG)
927dd7cddfSDavid du Colombier 				envcpy(up->egrp, oeg);
937dd7cddfSDavid du Colombier 			closeegrp(oeg);
947dd7cddfSDavid du Colombier 		}
957dd7cddfSDavid du Colombier 		if(flag & RFNOTEG)
967dd7cddfSDavid du Colombier 			up->noteid = incref(&noteidalloc);
977dd7cddfSDavid du Colombier 		return 0;
987dd7cddfSDavid du Colombier 	}
997dd7cddfSDavid du Colombier 
1003e12c5d1SDavid du Colombier 	p = newproc();
1013e12c5d1SDavid du Colombier 
1027dd7cddfSDavid du Colombier 	p->fpsave = up->fpsave;
1037dd7cddfSDavid du Colombier 	p->scallnr = up->scallnr;
1047dd7cddfSDavid du Colombier 	p->s = up->s;
1057dd7cddfSDavid du Colombier 	p->nerrlab = 0;
1067dd7cddfSDavid du Colombier 	p->slash = up->slash;
1077dd7cddfSDavid du Colombier 	p->dot = up->dot;
1087dd7cddfSDavid du Colombier 	incref(p->dot);
1093e12c5d1SDavid du Colombier 
1107dd7cddfSDavid du Colombier 	memmove(p->note, up->note, sizeof(p->note));
1119a747e4fSDavid du Colombier 	p->privatemem = up->privatemem;
112b7b24591SDavid du Colombier 	p->noswap = up->noswap;
1137dd7cddfSDavid du Colombier 	p->nnote = up->nnote;
1147dd7cddfSDavid du Colombier 	p->notified = 0;
1157dd7cddfSDavid du Colombier 	p->lastnote = up->lastnote;
1167dd7cddfSDavid du Colombier 	p->notify = up->notify;
1177dd7cddfSDavid du Colombier 	p->ureg = up->ureg;
1187dd7cddfSDavid du Colombier 	p->dbgreg = 0;
1193e12c5d1SDavid du Colombier 
1203e12c5d1SDavid du Colombier 	/* Make a new set of memory segments */
1213e12c5d1SDavid du Colombier 	n = flag & RFMEM;
1227dd7cddfSDavid du Colombier 	qlock(&p->seglock);
1237dd7cddfSDavid du Colombier 	if(waserror()){
1247dd7cddfSDavid du Colombier 		qunlock(&p->seglock);
1257dd7cddfSDavid du Colombier 		nexterror();
1267dd7cddfSDavid du Colombier 	}
1273e12c5d1SDavid du Colombier 	for(i = 0; i < NSEG; i++)
1287dd7cddfSDavid du Colombier 		if(up->seg[i])
1297dd7cddfSDavid du Colombier 			p->seg[i] = dupseg(up->seg, i, n);
1307dd7cddfSDavid du Colombier 	qunlock(&p->seglock);
1317dd7cddfSDavid du Colombier 	poperror();
1323e12c5d1SDavid du Colombier 
1333e12c5d1SDavid du Colombier 	/* File descriptors */
1343e12c5d1SDavid du Colombier 	if(flag & (RFFDG|RFCFDG)) {
1353e12c5d1SDavid du Colombier 		if(flag & RFFDG)
1367dd7cddfSDavid du Colombier 			p->fgrp = dupfgrp(up->fgrp);
1377dd7cddfSDavid du Colombier 		else
1387dd7cddfSDavid du Colombier 			p->fgrp = dupfgrp(nil);
1393e12c5d1SDavid du Colombier 	}
1403e12c5d1SDavid du Colombier 	else {
1417dd7cddfSDavid du Colombier 		p->fgrp = up->fgrp;
1423e12c5d1SDavid du Colombier 		incref(p->fgrp);
1433e12c5d1SDavid du Colombier 	}
1443e12c5d1SDavid du Colombier 
1453e12c5d1SDavid du Colombier 	/* Process groups */
1463e12c5d1SDavid du Colombier 	if(flag & (RFNAMEG|RFCNAMEG)) {
1473e12c5d1SDavid du Colombier 		p->pgrp = newpgrp();
148bd389b36SDavid du Colombier 		if(flag & RFNAMEG)
1497dd7cddfSDavid du Colombier 			pgrpcpy(p->pgrp, up->pgrp);
1507dd7cddfSDavid du Colombier 		/* inherit noattach */
1517dd7cddfSDavid du Colombier 		p->pgrp->noattach = up->pgrp->noattach;
1523e12c5d1SDavid du Colombier 	}
1533e12c5d1SDavid du Colombier 	else {
1547dd7cddfSDavid du Colombier 		p->pgrp = up->pgrp;
1553e12c5d1SDavid du Colombier 		incref(p->pgrp);
1563e12c5d1SDavid du Colombier 	}
1577dd7cddfSDavid du Colombier 	if(flag & RFNOMNT)
1587dd7cddfSDavid du Colombier 		up->pgrp->noattach = 1;
1597dd7cddfSDavid du Colombier 
1607dd7cddfSDavid du Colombier 	if(flag & RFREND)
1617dd7cddfSDavid du Colombier 		p->rgrp = newrgrp();
1627dd7cddfSDavid du Colombier 	else {
1637dd7cddfSDavid du Colombier 		incref(up->rgrp);
1647dd7cddfSDavid du Colombier 		p->rgrp = up->rgrp;
1657dd7cddfSDavid du Colombier 	}
1663e12c5d1SDavid du Colombier 
1673e12c5d1SDavid du Colombier 	/* Environment group */
1683e12c5d1SDavid du Colombier 	if(flag & (RFENVG|RFCENVG)) {
1693e12c5d1SDavid du Colombier 		p->egrp = smalloc(sizeof(Egrp));
1703e12c5d1SDavid du Colombier 		p->egrp->ref = 1;
1713e12c5d1SDavid du Colombier 		if(flag & RFENVG)
1727dd7cddfSDavid du Colombier 			envcpy(p->egrp, up->egrp);
1733e12c5d1SDavid du Colombier 	}
1743e12c5d1SDavid du Colombier 	else {
1757dd7cddfSDavid du Colombier 		p->egrp = up->egrp;
1763e12c5d1SDavid du Colombier 		incref(p->egrp);
1773e12c5d1SDavid du Colombier 	}
1787dd7cddfSDavid du Colombier 	p->hang = up->hang;
1797dd7cddfSDavid du Colombier 	p->procmode = up->procmode;
1803e12c5d1SDavid du Colombier 
1817dd7cddfSDavid du Colombier 	/* Craft a return frame which will cause the child to pop out of
1827dd7cddfSDavid du Colombier 	 * the scheduler in user mode with the return register zero
1833e12c5d1SDavid du Colombier 	 */
1847dd7cddfSDavid du Colombier 	forkchild(p, up->dbgreg);
1853e12c5d1SDavid du Colombier 
1867dd7cddfSDavid du Colombier 	p->parent = up;
1877dd7cddfSDavid du Colombier 	p->parentpid = up->pid;
1883e12c5d1SDavid du Colombier 	if(flag&RFNOWAIT)
1899a747e4fSDavid du Colombier 		p->parentpid = 0;
1903e12c5d1SDavid du Colombier 	else {
1917dd7cddfSDavid du Colombier 		lock(&up->exl);
1927dd7cddfSDavid du Colombier 		up->nchild++;
1937dd7cddfSDavid du Colombier 		unlock(&up->exl);
1943e12c5d1SDavid du Colombier 	}
1953e12c5d1SDavid du Colombier 	if((flag&RFNOTEG) == 0)
1967dd7cddfSDavid du Colombier 		p->noteid = up->noteid;
1973e12c5d1SDavid du Colombier 
1987dd7cddfSDavid du Colombier 	p->fpstate = up->fpstate;
1993e12c5d1SDavid du Colombier 	pid = p->pid;
2003e12c5d1SDavid du Colombier 	memset(p->time, 0, sizeof(p->time));
2013e12c5d1SDavid du Colombier 	p->time[TReal] = MACHP(0)->ticks;
2029a747e4fSDavid du Colombier 
2039a747e4fSDavid du Colombier 	kstrdup(&p->text, up->text);
2049a747e4fSDavid du Colombier 	kstrdup(&p->user, up->user);
2053e12c5d1SDavid du Colombier 	/*
2063e12c5d1SDavid du Colombier 	 *  since the bss/data segments are now shareable,
2073e12c5d1SDavid du Colombier 	 *  any mmu info about this process is now stale
2083e12c5d1SDavid du Colombier 	 *  (i.e. has bad properties) and has to be discarded.
2093e12c5d1SDavid du Colombier 	 */
2103e12c5d1SDavid du Colombier 	flushmmu();
2117dd7cddfSDavid du Colombier 	p->basepri = up->basepri;
2129a747e4fSDavid du Colombier 	p->priority = up->basepri;
21380ee5cbfSDavid du Colombier 	p->fixedpri = up->fixedpri;
2147dd7cddfSDavid du Colombier 	p->mp = up->mp;
2157dd7cddfSDavid du Colombier 	wm = up->wired;
2167dd7cddfSDavid du Colombier 	if(wm)
2177dd7cddfSDavid du Colombier 		procwired(p, wm->machno);
2183e12c5d1SDavid du Colombier 	ready(p);
219219b2ee8SDavid du Colombier 	sched();
2203e12c5d1SDavid du Colombier 	return pid;
2213e12c5d1SDavid du Colombier }
2223e12c5d1SDavid du Colombier 
2233e12c5d1SDavid du Colombier static ulong
2243e12c5d1SDavid du Colombier l2be(long l)
2253e12c5d1SDavid du Colombier {
2263e12c5d1SDavid du Colombier 	uchar *cp;
2273e12c5d1SDavid du Colombier 
2283e12c5d1SDavid du Colombier 	cp = (uchar*)&l;
2293e12c5d1SDavid du Colombier 	return (cp[0]<<24) | (cp[1]<<16) | (cp[2]<<8) | cp[3];
2303e12c5d1SDavid du Colombier }
2313e12c5d1SDavid du Colombier 
2323e12c5d1SDavid du Colombier long
2333e12c5d1SDavid du Colombier sysexec(ulong *arg)
2343e12c5d1SDavid du Colombier {
2353e12c5d1SDavid du Colombier 	Segment *s, *ts;
2363e12c5d1SDavid du Colombier 	ulong t, d, b;
2373e12c5d1SDavid du Colombier 	int i;
2383e12c5d1SDavid du Colombier 	Chan *tc;
2393e12c5d1SDavid du Colombier 	char **argv, **argp;
2409a747e4fSDavid du Colombier 	char *a, *charp, *args, *file;
2419a747e4fSDavid du Colombier 	char *progarg[sizeof(Exec)/2+1], *elem, progelem[64];
2423e12c5d1SDavid du Colombier 	ulong ssize, spage, nargs, nbytes, n, bssend;
2433e12c5d1SDavid du Colombier 	int indir;
2443e12c5d1SDavid du Colombier 	Exec exec;
2453e12c5d1SDavid du Colombier 	char line[sizeof(Exec)];
2463e12c5d1SDavid du Colombier 	Fgrp *f;
2473e12c5d1SDavid du Colombier 	Image *img;
2483e12c5d1SDavid du Colombier 	ulong magic, text, entry, data, bss;
2493e12c5d1SDavid du Colombier 
2503e12c5d1SDavid du Colombier 	validaddr(arg[0], 1, 0);
2513e12c5d1SDavid du Colombier 	file = (char*)arg[0];
2523e12c5d1SDavid du Colombier 	indir = 0;
2539a747e4fSDavid du Colombier 	elem = nil;
2549a747e4fSDavid du Colombier 	if(waserror()){
2559a747e4fSDavid du Colombier 		free(elem);
2569a747e4fSDavid du Colombier 		nexterror();
2579a747e4fSDavid du Colombier 	}
2587dd7cddfSDavid du Colombier 	for(;;){
2593e12c5d1SDavid du Colombier 		tc = namec(file, Aopen, OEXEC, 0);
2603e12c5d1SDavid du Colombier 		if(waserror()){
2617dd7cddfSDavid du Colombier 			cclose(tc);
2623e12c5d1SDavid du Colombier 			nexterror();
2633e12c5d1SDavid du Colombier 		}
2643e12c5d1SDavid du Colombier 		if(!indir)
2659a747e4fSDavid du Colombier 			kstrdup(&elem, up->genbuf);
2663e12c5d1SDavid du Colombier 
2677dd7cddfSDavid du Colombier 		n = devtab[tc->type]->read(tc, &exec, sizeof(Exec), 0);
2683e12c5d1SDavid du Colombier 		if(n < 2)
2693e12c5d1SDavid du Colombier 			error(Ebadexec);
2703e12c5d1SDavid du Colombier 		magic = l2be(exec.magic);
2713e12c5d1SDavid du Colombier 		text = l2be(exec.text);
2723e12c5d1SDavid du Colombier 		entry = l2be(exec.entry);
2737dd7cddfSDavid du Colombier 		if(n==sizeof(Exec) && (magic == AOUT_MAGIC)){
27459cc4ca5SDavid du Colombier 			if((text&KZERO) == KZERO
2753e12c5d1SDavid du Colombier 			|| entry < UTZERO+sizeof(Exec)
2763e12c5d1SDavid du Colombier 			|| entry >= UTZERO+sizeof(Exec)+text)
2777dd7cddfSDavid du Colombier 				error(Ebadexec);
2787dd7cddfSDavid du Colombier 			break; /* for binary */
2793e12c5d1SDavid du Colombier 		}
2803e12c5d1SDavid du Colombier 
2813e12c5d1SDavid du Colombier 		/*
2823e12c5d1SDavid du Colombier 		 * Process #! /bin/sh args ...
2833e12c5d1SDavid du Colombier 		 */
2843e12c5d1SDavid du Colombier 		memmove(line, &exec, sizeof(Exec));
2853e12c5d1SDavid du Colombier 		if(indir || line[0]!='#' || line[1]!='!')
2867dd7cddfSDavid du Colombier 			error(Ebadexec);
2873e12c5d1SDavid du Colombier 		n = shargs(line, n, progarg);
2883e12c5d1SDavid du Colombier 		if(n == 0)
2897dd7cddfSDavid du Colombier 			error(Ebadexec);
2903e12c5d1SDavid du Colombier 		indir = 1;
2913e12c5d1SDavid du Colombier 		/*
2923e12c5d1SDavid du Colombier 		 * First arg becomes complete file name
2933e12c5d1SDavid du Colombier 		 */
2943e12c5d1SDavid du Colombier 		progarg[n++] = file;
2953e12c5d1SDavid du Colombier 		progarg[n] = 0;
2963e12c5d1SDavid du Colombier 		validaddr(arg[1], BY2WD, 1);
2973e12c5d1SDavid du Colombier 		arg[1] += BY2WD;
2983e12c5d1SDavid du Colombier 		file = progarg[0];
2999a747e4fSDavid du Colombier 		if(strlen(elem) >= sizeof progelem)
3009a747e4fSDavid du Colombier 			error(Ebadexec);
3019a747e4fSDavid du Colombier 		strcpy(progelem, elem);
3029a747e4fSDavid du Colombier 		progarg[0] = progelem;
3033e12c5d1SDavid du Colombier 		poperror();
3047dd7cddfSDavid du Colombier 		cclose(tc);
3057dd7cddfSDavid du Colombier 	}
3063e12c5d1SDavid du Colombier 
3073e12c5d1SDavid du Colombier 	data = l2be(exec.data);
3083e12c5d1SDavid du Colombier 	bss = l2be(exec.bss);
3093e12c5d1SDavid du Colombier 	t = (UTZERO+sizeof(Exec)+text+(BY2PG-1)) & ~(BY2PG-1);
3103e12c5d1SDavid du Colombier 	d = (t + data + (BY2PG-1)) & ~(BY2PG-1);
3113e12c5d1SDavid du Colombier 	bssend = t + data + bss;
3123e12c5d1SDavid du Colombier 	b = (bssend + (BY2PG-1)) & ~(BY2PG-1);
31359cc4ca5SDavid du Colombier 	if(((t|d|b) & KZERO) == KZERO)
3143e12c5d1SDavid du Colombier 		error(Ebadexec);
3153e12c5d1SDavid du Colombier 
3163e12c5d1SDavid du Colombier 	/*
3173e12c5d1SDavid du Colombier 	 * Args: pass 1: count
3183e12c5d1SDavid du Colombier 	 */
3193e12c5d1SDavid du Colombier 	nbytes = BY2WD;		/* hole for profiling clock at top of stack */
3203e12c5d1SDavid du Colombier 	nargs = 0;
3213e12c5d1SDavid du Colombier 	if(indir){
3223e12c5d1SDavid du Colombier 		argp = progarg;
3233e12c5d1SDavid du Colombier 		while(*argp){
3243e12c5d1SDavid du Colombier 			a = *argp++;
3253e12c5d1SDavid du Colombier 			nbytes += strlen(a) + 1;
3263e12c5d1SDavid du Colombier 			nargs++;
3273e12c5d1SDavid du Colombier 		}
3283e12c5d1SDavid du Colombier 	}
3293e12c5d1SDavid du Colombier 	evenaddr(arg[1]);
3303e12c5d1SDavid du Colombier 	argp = (char**)arg[1];
3313e12c5d1SDavid du Colombier 	validaddr((ulong)argp, BY2WD, 0);
3323e12c5d1SDavid du Colombier 	while(*argp){
3333e12c5d1SDavid du Colombier 		a = *argp++;
3343e12c5d1SDavid du Colombier 		if(((ulong)argp&(BY2PG-1)) < BY2WD)
3353e12c5d1SDavid du Colombier 			validaddr((ulong)argp, BY2WD, 0);
3363e12c5d1SDavid du Colombier 		validaddr((ulong)a, 1, 0);
337219b2ee8SDavid du Colombier 		nbytes += (vmemchr(a, 0, 0x7FFFFFFF) - a) + 1;
3383e12c5d1SDavid du Colombier 		nargs++;
3393e12c5d1SDavid du Colombier 	}
3403e12c5d1SDavid du Colombier 	ssize = BY2WD*(nargs+1) + ((nbytes+(BY2WD-1)) & ~(BY2WD-1));
341bd389b36SDavid du Colombier 
3423e12c5d1SDavid du Colombier 	/*
3433e12c5d1SDavid du Colombier 	 * 8-byte align SP for those (e.g. sparc) that need it.
3443e12c5d1SDavid du Colombier 	 * execregs() will subtract another 4 bytes for argc.
3453e12c5d1SDavid du Colombier 	 */
3463e12c5d1SDavid du Colombier 	if((ssize+4) & 7)
3473e12c5d1SDavid du Colombier 		ssize += 4;
3483e12c5d1SDavid du Colombier 	spage = (ssize+(BY2PG-1)) >> PGSHIFT;
3497dd7cddfSDavid du Colombier 
3503e12c5d1SDavid du Colombier 	/*
3513e12c5d1SDavid du Colombier 	 * Build the stack segment, putting it in kernel virtual for the moment
3523e12c5d1SDavid du Colombier 	 */
3533e12c5d1SDavid du Colombier 	if(spage > TSTKSIZ)
3543e12c5d1SDavid du Colombier 		error(Enovmem);
3553e12c5d1SDavid du Colombier 
3567dd7cddfSDavid du Colombier 	qlock(&up->seglock);
3577dd7cddfSDavid du Colombier 	if(waserror()){
3587dd7cddfSDavid du Colombier 		qunlock(&up->seglock);
3597dd7cddfSDavid du Colombier 		nexterror();
3607dd7cddfSDavid du Colombier 	}
3617dd7cddfSDavid du Colombier 	up->seg[ESEG] = newseg(SG_STACK, TSTKTOP-USTKSIZE, USTKSIZE/BY2PG);
3623e12c5d1SDavid du Colombier 
3633e12c5d1SDavid du Colombier 	/*
3643e12c5d1SDavid du Colombier 	 * Args: pass 2: assemble; the pages will be faulted in
3653e12c5d1SDavid du Colombier 	 */
3663e12c5d1SDavid du Colombier 	argv = (char**)(TSTKTOP - ssize);
3673e12c5d1SDavid du Colombier 	charp = (char*)(TSTKTOP - nbytes);
3689a747e4fSDavid du Colombier 	args = charp;
3693e12c5d1SDavid du Colombier 	if(indir)
3703e12c5d1SDavid du Colombier 		argp = progarg;
3713e12c5d1SDavid du Colombier 	else
3723e12c5d1SDavid du Colombier 		argp = (char**)arg[1];
3733e12c5d1SDavid du Colombier 
3743e12c5d1SDavid du Colombier 	for(i=0; i<nargs; i++){
3753e12c5d1SDavid du Colombier 		if(indir && *argp==0) {
3763e12c5d1SDavid du Colombier 			indir = 0;
3773e12c5d1SDavid du Colombier 			argp = (char**)arg[1];
3783e12c5d1SDavid du Colombier 		}
3793e12c5d1SDavid du Colombier 		*argv++ = charp + (USTKTOP-TSTKTOP);
3803e12c5d1SDavid du Colombier 		n = strlen(*argp) + 1;
3813e12c5d1SDavid du Colombier 		memmove(charp, *argp++, n);
3823e12c5d1SDavid du Colombier 		charp += n;
3833e12c5d1SDavid du Colombier 	}
3843e12c5d1SDavid du Colombier 
3859a747e4fSDavid du Colombier 	free(up->text);
3869a747e4fSDavid du Colombier 	up->text = elem;
3879a747e4fSDavid du Colombier 	elem = nil;	/* so waserror() won't free elem */
3889a747e4fSDavid du Colombier 	USED(elem);
3899a747e4fSDavid du Colombier 
3909a747e4fSDavid du Colombier 	/* copy args; easiest from new process's stack */
3919a747e4fSDavid du Colombier 	n = charp - args;
3929a747e4fSDavid du Colombier 	if(n > 128)	/* don't waste too much space on huge arg lists */
3939a747e4fSDavid du Colombier 		n = 128;
3949a747e4fSDavid du Colombier 	a = up->args;
3959a747e4fSDavid du Colombier 	up->args = nil;
3969a747e4fSDavid du Colombier 	free(a);
3979a747e4fSDavid du Colombier 	up->args = smalloc(n);
3989a747e4fSDavid du Colombier 	memmove(up->args, args, n);
3999a747e4fSDavid du Colombier 	if(n>0 && up->args[n-1]!='\0'){
4009a747e4fSDavid du Colombier 		/* make sure last arg is NUL-terminated */
4019a747e4fSDavid du Colombier 		/* put NUL at UTF-8 character boundary */
4029a747e4fSDavid du Colombier 		for(i=n-1; i>0; --i)
4039a747e4fSDavid du Colombier 			if(fullrune(up->args+i, n-i))
4049a747e4fSDavid du Colombier 				break;
4059a747e4fSDavid du Colombier 		up->args[i] = 0;
4069a747e4fSDavid du Colombier 		n = i+1;
4079a747e4fSDavid du Colombier 	}
4089a747e4fSDavid du Colombier 	up->nargs = n;
4093e12c5d1SDavid du Colombier 
4103e12c5d1SDavid du Colombier 	/*
411bd389b36SDavid du Colombier 	 * Committed.
412bd389b36SDavid du Colombier 	 * Free old memory.
4137dd7cddfSDavid du Colombier 	 * Special segments are maintained across exec
4143e12c5d1SDavid du Colombier 	 */
4153e12c5d1SDavid du Colombier 	for(i = SSEG; i <= BSEG; i++) {
4167dd7cddfSDavid du Colombier 		putseg(up->seg[i]);
417219b2ee8SDavid du Colombier 		/* prevent a second free if we have an error */
4187dd7cddfSDavid du Colombier 		up->seg[i] = 0;
419219b2ee8SDavid du Colombier 	}
420219b2ee8SDavid du Colombier 	for(i = BSEG+1; i < NSEG; i++) {
4217dd7cddfSDavid du Colombier 		s = up->seg[i];
422219b2ee8SDavid du Colombier 		if(s != 0 && (s->type&SG_CEXEC)) {
423219b2ee8SDavid du Colombier 			putseg(s);
4247dd7cddfSDavid du Colombier 			up->seg[i] = 0;
425219b2ee8SDavid du Colombier 		}
4263e12c5d1SDavid du Colombier 	}
4273e12c5d1SDavid du Colombier 
4283e12c5d1SDavid du Colombier 	/*
4293e12c5d1SDavid du Colombier 	 * Close on exec
4303e12c5d1SDavid du Colombier 	 */
4317dd7cddfSDavid du Colombier 	f = up->fgrp;
4323e12c5d1SDavid du Colombier 	for(i=0; i<=f->maxfd; i++)
4333e12c5d1SDavid du Colombier 		fdclose(i, CCEXEC);
4343e12c5d1SDavid du Colombier 
4353e12c5d1SDavid du Colombier 	/* Text.  Shared. Attaches to cache image if possible */
4363e12c5d1SDavid du Colombier 	/* attachimage returns a locked cache image */
4373e12c5d1SDavid du Colombier 	img = attachimage(SG_TEXT|SG_RONLY, tc, UTZERO, (t-UTZERO)>>PGSHIFT);
4383e12c5d1SDavid du Colombier 	ts = img->s;
4397dd7cddfSDavid du Colombier 	up->seg[TSEG] = ts;
4403e12c5d1SDavid du Colombier 	ts->flushme = 1;
4413e12c5d1SDavid du Colombier 	ts->fstart = 0;
4423e12c5d1SDavid du Colombier 	ts->flen = sizeof(Exec)+text;
4433e12c5d1SDavid du Colombier 	unlock(img);
4443e12c5d1SDavid du Colombier 
4453e12c5d1SDavid du Colombier 	/* Data. Shared. */
4463e12c5d1SDavid du Colombier 	s = newseg(SG_DATA, t, (d-t)>>PGSHIFT);
4477dd7cddfSDavid du Colombier 	up->seg[DSEG] = s;
4483e12c5d1SDavid du Colombier 
4493e12c5d1SDavid du Colombier 	/* Attached by hand */
4503e12c5d1SDavid du Colombier 	incref(img);
4513e12c5d1SDavid du Colombier 	s->image = img;
4523e12c5d1SDavid du Colombier 	s->fstart = ts->fstart+ts->flen;
4533e12c5d1SDavid du Colombier 	s->flen = data;
4543e12c5d1SDavid du Colombier 
4553e12c5d1SDavid du Colombier 	/* BSS. Zero fill on demand */
4567dd7cddfSDavid du Colombier 	up->seg[BSEG] = newseg(SG_BSS, d, (b-d)>>PGSHIFT);
4573e12c5d1SDavid du Colombier 
4583e12c5d1SDavid du Colombier 	/*
4593e12c5d1SDavid du Colombier 	 * Move the stack
4603e12c5d1SDavid du Colombier 	 */
4617dd7cddfSDavid du Colombier 	s = up->seg[ESEG];
4627dd7cddfSDavid du Colombier 	up->seg[ESEG] = 0;
4637dd7cddfSDavid du Colombier 	up->seg[SSEG] = s;
4647dd7cddfSDavid du Colombier 	qunlock(&up->seglock);
4659a747e4fSDavid du Colombier 	poperror();	/* seglock */
4669a747e4fSDavid du Colombier 	poperror();	/* elem */
4673e12c5d1SDavid du Colombier 	s->base = USTKTOP-USTKSIZE;
4683e12c5d1SDavid du Colombier 	s->top = USTKTOP;
4697dd7cddfSDavid du Colombier 	relocateseg(s, USTKTOP-TSTKTOP);
4703e12c5d1SDavid du Colombier 
471219b2ee8SDavid du Colombier 	/*
472219b2ee8SDavid du Colombier 	 *  '/' processes are higher priority (hack to make /ip more responsive).
473219b2ee8SDavid du Colombier 	 */
4747dd7cddfSDavid du Colombier 	if(devtab[tc->type]->dc == L'/')
4757dd7cddfSDavid du Colombier 		up->basepri = PriRoot;
4767dd7cddfSDavid du Colombier 	up->priority = up->basepri;
4777dd7cddfSDavid du Colombier 	poperror();
4787dd7cddfSDavid du Colombier 	cclose(tc);
4793e12c5d1SDavid du Colombier 
4803e12c5d1SDavid du Colombier 	/*
4813e12c5d1SDavid du Colombier 	 *  At this point, the mmu contains info about the old address
4823e12c5d1SDavid du Colombier 	 *  space and needs to be flushed
4833e12c5d1SDavid du Colombier 	 */
4843e12c5d1SDavid du Colombier 	flushmmu();
4857dd7cddfSDavid du Colombier 	qlock(&up->debug);
4867dd7cddfSDavid du Colombier 	up->nnote = 0;
4877dd7cddfSDavid du Colombier 	up->notify = 0;
4887dd7cddfSDavid du Colombier 	up->notified = 0;
4899a747e4fSDavid du Colombier 	up->privatemem = 0;
4907dd7cddfSDavid du Colombier 	procsetup(up);
4917dd7cddfSDavid du Colombier 	qunlock(&up->debug);
4927dd7cddfSDavid du Colombier 	if(up->hang)
4937dd7cddfSDavid du Colombier 		up->procctl = Proc_stopme;
4943e12c5d1SDavid du Colombier 
4953e12c5d1SDavid du Colombier 	return execregs(entry, ssize, nargs);
4963e12c5d1SDavid du Colombier }
4973e12c5d1SDavid du Colombier 
4983e12c5d1SDavid du Colombier int
4993e12c5d1SDavid du Colombier shargs(char *s, int n, char **ap)
5003e12c5d1SDavid du Colombier {
5013e12c5d1SDavid du Colombier 	int i;
5023e12c5d1SDavid du Colombier 
503bd389b36SDavid du Colombier 	s += 2;
504bd389b36SDavid du Colombier 	n -= 2;		/* skip #! */
5053e12c5d1SDavid du Colombier 	for(i=0; s[i]!='\n'; i++)
5063e12c5d1SDavid du Colombier 		if(i == n-1)
5073e12c5d1SDavid du Colombier 			return 0;
5083e12c5d1SDavid du Colombier 	s[i] = 0;
5093e12c5d1SDavid du Colombier 	*ap = 0;
5103e12c5d1SDavid du Colombier 	i = 0;
5113e12c5d1SDavid du Colombier 	for(;;) {
5123e12c5d1SDavid du Colombier 		while(*s==' ' || *s=='\t')
5133e12c5d1SDavid du Colombier 			s++;
5143e12c5d1SDavid du Colombier 		if(*s == 0)
5153e12c5d1SDavid du Colombier 			break;
5163e12c5d1SDavid du Colombier 		i++;
5173e12c5d1SDavid du Colombier 		*ap++ = s;
5183e12c5d1SDavid du Colombier 		*ap = 0;
5193e12c5d1SDavid du Colombier 		while(*s && *s!=' ' && *s!='\t')
5203e12c5d1SDavid du Colombier 			s++;
5213e12c5d1SDavid du Colombier 		if(*s == 0)
5223e12c5d1SDavid du Colombier 			break;
5233e12c5d1SDavid du Colombier 		else
5243e12c5d1SDavid du Colombier 			*s++ = 0;
5253e12c5d1SDavid du Colombier 	}
5263e12c5d1SDavid du Colombier 	return i;
5273e12c5d1SDavid du Colombier }
5283e12c5d1SDavid du Colombier 
5293e12c5d1SDavid du Colombier int
5307dd7cddfSDavid du Colombier return0(void*)
5313e12c5d1SDavid du Colombier {
5323e12c5d1SDavid du Colombier 	return 0;
5333e12c5d1SDavid du Colombier }
5343e12c5d1SDavid du Colombier 
5353e12c5d1SDavid du Colombier long
5363e12c5d1SDavid du Colombier syssleep(ulong *arg)
5373e12c5d1SDavid du Colombier {
5387dd7cddfSDavid du Colombier 
539219b2ee8SDavid du Colombier 	int n;
540219b2ee8SDavid du Colombier 
541219b2ee8SDavid du Colombier 	n = arg[0];
5427dd7cddfSDavid du Colombier 	if(n <= 0) {
543*bd2ae673SDavid du Colombier 		yield();
544219b2ee8SDavid du Colombier 		return 0;
545219b2ee8SDavid du Colombier 	}
5467dd7cddfSDavid du Colombier 	if(n < TK2MS(1))
547219b2ee8SDavid du Colombier 		n = TK2MS(1);
5487dd7cddfSDavid du Colombier 	tsleep(&up->sleep, return0, 0, n);
5493e12c5d1SDavid du Colombier 	return 0;
5503e12c5d1SDavid du Colombier }
5513e12c5d1SDavid du Colombier 
5523e12c5d1SDavid du Colombier long
5533e12c5d1SDavid du Colombier sysalarm(ulong *arg)
5543e12c5d1SDavid du Colombier {
5553e12c5d1SDavid du Colombier 	return procalarm(arg[0]);
5563e12c5d1SDavid du Colombier }
5573e12c5d1SDavid du Colombier 
5583e12c5d1SDavid du Colombier long
5593e12c5d1SDavid du Colombier sysexits(ulong *arg)
5603e12c5d1SDavid du Colombier {
5613e12c5d1SDavid du Colombier 	char *status;
5623e12c5d1SDavid du Colombier 	char *inval = "invalid exit string";
5639a747e4fSDavid du Colombier 	char buf[ERRMAX];
5643e12c5d1SDavid du Colombier 
5653e12c5d1SDavid du Colombier 	status = (char*)arg[0];
5663e12c5d1SDavid du Colombier 	if(status){
5673e12c5d1SDavid du Colombier 		if(waserror())
5683e12c5d1SDavid du Colombier 			status = inval;
5693e12c5d1SDavid du Colombier 		else{
5703e12c5d1SDavid du Colombier 			validaddr((ulong)status, 1, 0);
5719a747e4fSDavid du Colombier 			if(vmemchr(status, 0, ERRMAX) == 0){
5729a747e4fSDavid du Colombier 				memmove(buf, status, ERRMAX);
5739a747e4fSDavid du Colombier 				buf[ERRMAX-1] = 0;
574219b2ee8SDavid du Colombier 				status = buf;
575219b2ee8SDavid du Colombier 			}
5763e12c5d1SDavid du Colombier 		}
5773e12c5d1SDavid du Colombier 		poperror();
5783e12c5d1SDavid du Colombier 
5793e12c5d1SDavid du Colombier 	}
5803e12c5d1SDavid du Colombier 	pexit(status, 1);
5813e12c5d1SDavid du Colombier 	return 0;		/* not reached */
5823e12c5d1SDavid du Colombier }
5833e12c5d1SDavid du Colombier 
5843e12c5d1SDavid du Colombier long
5859a747e4fSDavid du Colombier sys_wait(ulong *arg)
5863e12c5d1SDavid du Colombier {
5879a747e4fSDavid du Colombier 	int pid;
5889a747e4fSDavid du Colombier 	Waitmsg w;
5899a747e4fSDavid du Colombier 	OWaitmsg *ow;
5909a747e4fSDavid du Colombier 
5919a747e4fSDavid du Colombier 	if(arg[0] == 0)
5929a747e4fSDavid du Colombier 		return pwait(nil);
5939a747e4fSDavid du Colombier 
5949a747e4fSDavid du Colombier 	validaddr(arg[0], sizeof(OWaitmsg), 1);
5953e12c5d1SDavid du Colombier 	evenaddr(arg[0]);
5969a747e4fSDavid du Colombier 	pid = pwait(&w);
5979a747e4fSDavid du Colombier 	if(pid >= 0){
5989a747e4fSDavid du Colombier 		ow = (OWaitmsg*)arg[0];
5999a747e4fSDavid du Colombier 		readnum(0, ow->pid, NUMSIZE, w.pid, NUMSIZE);
6009a747e4fSDavid du Colombier 		readnum(0, ow->time+TUser*NUMSIZE, NUMSIZE, w.time[TUser], NUMSIZE);
6019a747e4fSDavid du Colombier 		readnum(0, ow->time+TSys*NUMSIZE, NUMSIZE, w.time[TSys], NUMSIZE);
6029a747e4fSDavid du Colombier 		readnum(0, ow->time+TReal*NUMSIZE, NUMSIZE, w.time[TReal], NUMSIZE);
6039a747e4fSDavid du Colombier 		strncpy(ow->msg, w.msg, sizeof(ow->msg));
6049a747e4fSDavid du Colombier 		ow->msg[sizeof(ow->msg)-1] = '\0';
6053e12c5d1SDavid du Colombier 	}
6069a747e4fSDavid du Colombier 	return pid;
6079a747e4fSDavid du Colombier }
6089a747e4fSDavid du Colombier 
6099a747e4fSDavid du Colombier long
6109a747e4fSDavid du Colombier sysawait(ulong *arg)
6119a747e4fSDavid du Colombier {
6129a747e4fSDavid du Colombier 	int i;
6139a747e4fSDavid du Colombier 	int pid;
6149a747e4fSDavid du Colombier 	Waitmsg w;
6159a747e4fSDavid du Colombier 	ulong n;
6169a747e4fSDavid du Colombier 
6179a747e4fSDavid du Colombier 	n = arg[1];
6189a747e4fSDavid du Colombier 	validaddr(arg[0], n, 1);
6199a747e4fSDavid du Colombier 	pid = pwait(&w);
6209a747e4fSDavid du Colombier 	if(pid < 0)
6219a747e4fSDavid du Colombier 		return -1;
6229a747e4fSDavid du Colombier 	i = snprint((char*)arg[0], n, "%d %lud %lud %lud %q",
6239a747e4fSDavid du Colombier 		w.pid,
6249a747e4fSDavid du Colombier 		w.time[TUser], w.time[TSys], w.time[TReal],
6259a747e4fSDavid du Colombier 		w.msg);
6269a747e4fSDavid du Colombier 
6279a747e4fSDavid du Colombier 	return i;
6283e12c5d1SDavid du Colombier }
6293e12c5d1SDavid du Colombier 
6303e12c5d1SDavid du Colombier long
6317dd7cddfSDavid du Colombier sysdeath(ulong*)
6323e12c5d1SDavid du Colombier {
6333e12c5d1SDavid du Colombier 	pprint("deprecated system call\n");
6343e12c5d1SDavid du Colombier 	pexit("Suicide", 0);
6353e12c5d1SDavid du Colombier 	return 0;	/* not reached */
6363e12c5d1SDavid du Colombier }
6373e12c5d1SDavid du Colombier 
6387dd7cddfSDavid du Colombier void
6397dd7cddfSDavid du Colombier werrstr(char *fmt, ...)
6407dd7cddfSDavid du Colombier {
6417dd7cddfSDavid du Colombier 	va_list va;
6427dd7cddfSDavid du Colombier 
6437dd7cddfSDavid du Colombier 	if(up == nil)
6447dd7cddfSDavid du Colombier 		return;
6457dd7cddfSDavid du Colombier 
6467dd7cddfSDavid du Colombier 	va_start(va, fmt);
6479a747e4fSDavid du Colombier 	vseprint(up->syserrstr, up->syserrstr+ERRMAX, fmt, va);
6487dd7cddfSDavid du Colombier 	va_end(va);
6497dd7cddfSDavid du Colombier }
6507dd7cddfSDavid du Colombier 
6519a747e4fSDavid du Colombier static long
6529a747e4fSDavid du Colombier generrstr(char *buf, uint nbuf)
6539a747e4fSDavid du Colombier {
6549a747e4fSDavid du Colombier 	char tmp[ERRMAX];
6559a747e4fSDavid du Colombier 
6569a747e4fSDavid du Colombier 	if(nbuf == 0)
6579a747e4fSDavid du Colombier 		error(Ebadarg);
6589a747e4fSDavid du Colombier 	validaddr((ulong)buf, nbuf, 1);
6599a747e4fSDavid du Colombier 	if(nbuf > sizeof tmp)
6609a747e4fSDavid du Colombier 		nbuf = sizeof tmp;
6619a747e4fSDavid du Colombier 	memmove(tmp, buf, nbuf);
6629a747e4fSDavid du Colombier 	/* make sure it's NUL-terminated */
6639a747e4fSDavid du Colombier 	tmp[nbuf-1] = '\0';
6649a747e4fSDavid du Colombier 	memmove(buf, up->syserrstr, nbuf);
6659a747e4fSDavid du Colombier 	buf[nbuf-1] = '\0';
6669a747e4fSDavid du Colombier 	memmove(up->syserrstr, tmp, nbuf);
6679a747e4fSDavid du Colombier 	return 0;
6689a747e4fSDavid du Colombier }
6699a747e4fSDavid du Colombier 
6703e12c5d1SDavid du Colombier long
6713e12c5d1SDavid du Colombier syserrstr(ulong *arg)
6723e12c5d1SDavid du Colombier {
6739a747e4fSDavid du Colombier 	return generrstr((char*)arg[0], arg[1]);
6749a747e4fSDavid du Colombier }
675219b2ee8SDavid du Colombier 
6769a747e4fSDavid du Colombier /* compatibility for old binaries */
6779a747e4fSDavid du Colombier long
6789a747e4fSDavid du Colombier sys_errstr(ulong *arg)
6799a747e4fSDavid du Colombier {
6809a747e4fSDavid du Colombier 	return generrstr((char*)arg[0], 64);
6813e12c5d1SDavid du Colombier }
6823e12c5d1SDavid du Colombier 
6833e12c5d1SDavid du Colombier long
6843e12c5d1SDavid du Colombier sysnotify(ulong *arg)
6853e12c5d1SDavid du Colombier {
6863e12c5d1SDavid du Colombier 	if(arg[0] != 0)
6873e12c5d1SDavid du Colombier 		validaddr(arg[0], sizeof(ulong), 0);
6887dd7cddfSDavid du Colombier 	up->notify = (int(*)(void*, char*))(arg[0]);
6893e12c5d1SDavid du Colombier 	return 0;
6903e12c5d1SDavid du Colombier }
6913e12c5d1SDavid du Colombier 
6923e12c5d1SDavid du Colombier long
6933e12c5d1SDavid du Colombier sysnoted(ulong *arg)
6943e12c5d1SDavid du Colombier {
6957dd7cddfSDavid du Colombier 	if(arg[0]!=NRSTR && !up->notified)
6963e12c5d1SDavid du Colombier 		error(Egreg);
6973e12c5d1SDavid du Colombier 	return 0;
6983e12c5d1SDavid du Colombier }
6993e12c5d1SDavid du Colombier 
7003e12c5d1SDavid du Colombier long
7013e12c5d1SDavid du Colombier syssegbrk(ulong *arg)
7023e12c5d1SDavid du Colombier {
7033e12c5d1SDavid du Colombier 	int i;
7047dd7cddfSDavid du Colombier 	ulong addr;
7057dd7cddfSDavid du Colombier 	Segment *s;
7063e12c5d1SDavid du Colombier 
7077dd7cddfSDavid du Colombier 	addr = arg[0];
708219b2ee8SDavid du Colombier 	for(i = 0; i < NSEG; i++) {
7097dd7cddfSDavid du Colombier 		s = up->seg[i];
7107dd7cddfSDavid du Colombier 		if(s == 0 || addr < s->base || addr >= s->top)
7117dd7cddfSDavid du Colombier 			continue;
7123e12c5d1SDavid du Colombier 		switch(s->type&SG_TYPE) {
7133e12c5d1SDavid du Colombier 		case SG_TEXT:
7143e12c5d1SDavid du Colombier 		case SG_DATA:
715219b2ee8SDavid du Colombier 		case SG_STACK:
7163e12c5d1SDavid du Colombier 			error(Ebadarg);
7173e12c5d1SDavid du Colombier 		default:
7183e12c5d1SDavid du Colombier 			return ibrk(arg[1], i);
7193e12c5d1SDavid du Colombier 		}
7203e12c5d1SDavid du Colombier 	}
7213e12c5d1SDavid du Colombier 
7223e12c5d1SDavid du Colombier 	error(Ebadarg);
7233e12c5d1SDavid du Colombier 	return 0;		/* not reached */
7243e12c5d1SDavid du Colombier }
7253e12c5d1SDavid du Colombier 
7263e12c5d1SDavid du Colombier long
7273e12c5d1SDavid du Colombier syssegattach(ulong *arg)
7283e12c5d1SDavid du Colombier {
7297dd7cddfSDavid du Colombier 	return segattach(up, arg[0], (char*)arg[1], arg[2], arg[3]);
7303e12c5d1SDavid du Colombier }
7313e12c5d1SDavid du Colombier 
7323e12c5d1SDavid du Colombier long
7333e12c5d1SDavid du Colombier syssegdetach(ulong *arg)
7343e12c5d1SDavid du Colombier {
7353e12c5d1SDavid du Colombier 	int i;
7367dd7cddfSDavid du Colombier 	ulong addr;
7373e12c5d1SDavid du Colombier 	Segment *s;
7383e12c5d1SDavid du Colombier 
7397dd7cddfSDavid du Colombier 	qlock(&up->seglock);
7407dd7cddfSDavid du Colombier 	if(waserror()){
7417dd7cddfSDavid du Colombier 		qunlock(&up->seglock);
7427dd7cddfSDavid du Colombier 		nexterror();
7437dd7cddfSDavid du Colombier 	}
7447dd7cddfSDavid du Colombier 
7453e12c5d1SDavid du Colombier 	s = 0;
7467dd7cddfSDavid du Colombier 	addr = arg[0];
7473e12c5d1SDavid du Colombier 	for(i = 0; i < NSEG; i++)
7487dd7cddfSDavid du Colombier 		if(s = up->seg[i]) {
7493e12c5d1SDavid du Colombier 			qlock(&s->lk);
7507dd7cddfSDavid du Colombier 			if((addr >= s->base && addr < s->top) ||
7517dd7cddfSDavid du Colombier 			   (s->top == s->base && addr == s->base))
7523e12c5d1SDavid du Colombier 				goto found;
7533e12c5d1SDavid du Colombier 			qunlock(&s->lk);
7543e12c5d1SDavid du Colombier 		}
7553e12c5d1SDavid du Colombier 
7563e12c5d1SDavid du Colombier 	error(Ebadarg);
7573e12c5d1SDavid du Colombier 
7583e12c5d1SDavid du Colombier found:
7597dd7cddfSDavid du Colombier 	/* Check we are not detaching the current stack segment */
7603e12c5d1SDavid du Colombier 	if((ulong)arg >= s->base && (ulong)arg < s->top) {
7613e12c5d1SDavid du Colombier 		qunlock(&s->lk);
7623e12c5d1SDavid du Colombier 		error(Ebadarg);
7633e12c5d1SDavid du Colombier 	}
7647dd7cddfSDavid du Colombier 	up->seg[i] = 0;
7653e12c5d1SDavid du Colombier 	qunlock(&s->lk);
7663e12c5d1SDavid du Colombier 	putseg(s);
7677dd7cddfSDavid du Colombier 	qunlock(&up->seglock);
7687dd7cddfSDavid du Colombier 	poperror();
7693e12c5d1SDavid du Colombier 
7703e12c5d1SDavid du Colombier 	/* Ensure we flush any entries from the lost segment */
7713e12c5d1SDavid du Colombier 	flushmmu();
7723e12c5d1SDavid du Colombier 	return 0;
7733e12c5d1SDavid du Colombier }
7743e12c5d1SDavid du Colombier 
7753e12c5d1SDavid du Colombier long
7763e12c5d1SDavid du Colombier syssegfree(ulong *arg)
7773e12c5d1SDavid du Colombier {
7783e12c5d1SDavid du Colombier 	Segment *s;
7799a747e4fSDavid du Colombier 	ulong from, to;
7803e12c5d1SDavid du Colombier 
7819a747e4fSDavid du Colombier 	from = arg[0];
7827dd7cddfSDavid du Colombier 	s = seg(up, from, 1);
7839a747e4fSDavid du Colombier 	if(s == nil)
7843e12c5d1SDavid du Colombier 		error(Ebadarg);
7859a747e4fSDavid du Colombier 	to = (from + arg[1]) & ~(BY2PG-1);
7869a747e4fSDavid du Colombier 	from = PGROUND(from);
7873e12c5d1SDavid du Colombier 
7889a747e4fSDavid du Colombier 	if(to > s->top) {
7893e12c5d1SDavid du Colombier 		qunlock(&s->lk);
7903e12c5d1SDavid du Colombier 		error(Ebadarg);
7913e12c5d1SDavid du Colombier 	}
7923e12c5d1SDavid du Colombier 
7939a747e4fSDavid du Colombier 	mfreeseg(s, from, (to - from) / BY2PG);
7943e12c5d1SDavid du Colombier 	qunlock(&s->lk);
795bd389b36SDavid du Colombier 	flushmmu();
7963e12c5d1SDavid du Colombier 
7973e12c5d1SDavid du Colombier 	return 0;
7983e12c5d1SDavid du Colombier }
7993e12c5d1SDavid du Colombier 
8007dd7cddfSDavid du Colombier /* For binary compatibility */
8013e12c5d1SDavid du Colombier long
8023e12c5d1SDavid du Colombier sysbrk_(ulong *arg)
8033e12c5d1SDavid du Colombier {
8043e12c5d1SDavid du Colombier 	return ibrk(arg[0], BSEG);
8053e12c5d1SDavid du Colombier }
8063e12c5d1SDavid du Colombier 
8073e12c5d1SDavid du Colombier long
8083e12c5d1SDavid du Colombier sysrendezvous(ulong *arg)
8093e12c5d1SDavid du Colombier {
8107dd7cddfSDavid du Colombier 	ulong tag;
8113e12c5d1SDavid du Colombier 	ulong val;
8127dd7cddfSDavid du Colombier 	Proc *p, **l;
8133e12c5d1SDavid du Colombier 
8143e12c5d1SDavid du Colombier 	tag = arg[0];
8157dd7cddfSDavid du Colombier 	l = &REND(up->rgrp, tag);
8169a747e4fSDavid du Colombier 	up->rendval = ~0UL;
8173e12c5d1SDavid du Colombier 
8187dd7cddfSDavid du Colombier 	lock(up->rgrp);
8193e12c5d1SDavid du Colombier 	for(p = *l; p; p = p->rendhash) {
8203e12c5d1SDavid du Colombier 		if(p->rendtag == tag) {
8213e12c5d1SDavid du Colombier 			*l = p->rendhash;
8223e12c5d1SDavid du Colombier 			val = p->rendval;
8233e12c5d1SDavid du Colombier 			p->rendval = arg[1];
8247dd7cddfSDavid du Colombier 
825219b2ee8SDavid du Colombier 			while(p->mach != 0)
8263e12c5d1SDavid du Colombier 				;
8273e12c5d1SDavid du Colombier 			ready(p);
8287dd7cddfSDavid du Colombier 			unlock(up->rgrp);
8293e12c5d1SDavid du Colombier 			return val;
8303e12c5d1SDavid du Colombier 		}
8313e12c5d1SDavid du Colombier 		l = &p->rendhash;
8323e12c5d1SDavid du Colombier 	}
8333e12c5d1SDavid du Colombier 
8343e12c5d1SDavid du Colombier 	/* Going to sleep here */
8357dd7cddfSDavid du Colombier 	up->rendtag = tag;
8367dd7cddfSDavid du Colombier 	up->rendval = arg[1];
8377dd7cddfSDavid du Colombier 	up->rendhash = *l;
8387dd7cddfSDavid du Colombier 	*l = up;
8397dd7cddfSDavid du Colombier 	up->state = Rendezvous;
8407dd7cddfSDavid du Colombier 	unlock(up->rgrp);
8413ff48bf5SDavid du Colombier 	if (edf->isedf(up))
8423ff48bf5SDavid du Colombier 		edf->edfblock(up);
843219b2ee8SDavid du Colombier 
8443e12c5d1SDavid du Colombier 	sched();
8453e12c5d1SDavid du Colombier 
8467dd7cddfSDavid du Colombier 	return up->rendval;
8473e12c5d1SDavid du Colombier }
848