plan 9 kernel history: overview | file list | diff list

1991/1216/port/sysproc.c (diff list | history)

1991/1216/sys/src/9/port/sysproc.c:1,6491991/1219/sys/src/9/port/sysproc.c:1,653 (short | long | prev | next)
1990/0227    
#include	"u.h" 
#include	"lib.h" 
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"ureg.h" 
#include	"errno.h" 
 
1990/0330    
#include	<a.out.h> 
1990/0227    
 
int	shargs(char*, int, char**); 
1991/0807    
long	rfork(ulong); 
1990/0227    
 
long 
sysr1(ulong *arg) 
{ 
1991/1105    
	print("[%s %s %d] r1 = %d\n", u->p->user, u->p->text, u->p->pid, arg[0]); 
1990/0227    
	return 0; 
} 
 
long 
sysfork(ulong *arg) 
{ 
1991/1115    
	USED(arg); 
1991/0808    
	return rfork(Forkfd); 
1991/0807    
} 
 
/* This call will obsolete fork */ 
long 
sysrfork(ulong *arg) 
{ 
	return rfork(arg[0]); 
} 
 
long 
rfork(ulong flag) 
{ 
1990/0227    
	Proc *p; 
1991/0705    
	Segment *s; 
1990/0227    
	Page *np, *op; 
	ulong usp, upa, pid; 
	Chan *c; 
1990/0614    
	KMap *k; 
1990/0227    
	int n, on, i; 
1991/0807    
	/* 
	 * used to compute last valid system stack address for copy 
	 */ 
	int lastvar;	 
1991/0709    
 
1990/0227    
	p = newproc(); 
1991/0705    
 
	/* Page va of upage used as check in mapstack */ 
1990/0227    
	p->upage = newpage(1, 0, USERADDR|(p->pid&0xFFFF)); 
1990/0614    
	k = kmap(p->upage); 
	upa = VA(k); 
 
1991/1110    
	/* Save time: only copy u-> data and useful stack */ 
	clearmmucache(); 
1991/0318    
	memmove((void*)upa, u, sizeof(User)); 
1990/0227    
	n = USERADDR+BY2PG - (ulong)&lastvar; 
	n = (n+32) & ~(BY2WD-1);	/* be safe & word align */ 
1991/0318    
	memmove((void*)(upa+BY2PG-n), (void*)(USERADDR+BY2PG-n), n); 
1990/0227    
	((User *)upa)->p = p; 
1990/0614    
	kunmap(k); 
1990/0227    
 
1991/0705    
	/* Make a new set of memory segments */ 
	for(i = 0; i < NSEG; i++) 
		if(u->p->seg[i]) 
			p->seg[i] = dupseg(u->p->seg[i]); 
 
1991/1110    
	/* Refs */ 
1991/0705    
	incref(u->dot);				/* File descriptors etc. */ 
 
1991/0807    
	if(flag & Forkfd) 
		p->fgrp = dupfgrp(u->p->fgrp); 
1991/0808    
	else{ 
1991/0807    
		p->fgrp = u->p->fgrp; 
		incref(p->fgrp); 
	} 
1991/0705    
 
1991/0807    
	if(flag & Forkpg) { 
		p->pgrp = newpgrp(); 
		pgrpcpy(p->pgrp, u->p->pgrp); 
	} 
1991/0808    
	else { 
		p->pgrp = u->p->pgrp;			/* Process groups */ 
		incref(p->pgrp); 
	} 
1991/0705    
 
1991/0807    
	if(flag & Forkeg) { 
		p->egrp = newegrp(); 
		envcpy(p->egrp, u->p->egrp); 
	} 
1991/0808    
	else { 
		p->egrp = u->p->egrp;			/* Environment group */ 
		incref(p->egrp); 
	} 
1991/0807    
 
1991/1110    
	p->hang = u->p->hang; 
	p->procmode = u->p->procmode; 
 
1990/0227    
	/* 
	 * Sched 
	 */ 
	if(setlabel(&p->sched)){ 
1991/0919    
		/* 
		 *  use u->p instead of p, because we 
		 *  don't trust the compiler, after a 
		 *  gotolabel, to find the correct contents 
		 *  of a local variable. 
		 */ 
		p = u->p; 
1990/0227    
		p->state = Running; 
		p->mach = m; 
		m->proc = p; 
		spllo(); 
		return 0; 
	} 
1991/0705    
 
1990/0227    
	p->parent = u->p; 
	p->parentpid = u->p->pid; 
1991/0705    
 
1991/0118    
	p->fpstate = u->p->fpstate; 
1991/0926    
	lock(&u->p->exl); 
1990/0324    
	u->p->nchild++; 
1991/0926    
	unlock(&u->p->exl); 
1990/0227    
	pid = p->pid; 
	memset(p->time, 0, sizeof(p->time)); 
	p->time[TReal] = MACHP(0)->ticks; 
1991/0318    
	memmove(p->text, u->p->text, NAMELEN); 
1991/1105    
	memmove(p->user, u->p->user, NAMELEN); 
1991/0529    
	/* 
	 *  since the bss/data segments are now shareable, 
	 *  any mmu info about this process is now stale 
	 *  (i.e. has bad properties) and has to be discarded. 
	 */ 
1990/0227    
	flushmmu(); 
1990/1211    
	clearmmucache(); 
1991/0430    
	ready(p); 
1990/0227    
	return pid; 
} 
 
1991/0723    
static ulong 
l2be(long l) 
{ 
	uchar *cp; 
 
	cp = (uchar*)&l; 
	return (cp[0]<<24) | (cp[1]<<16) | (cp[2]<<8) | cp[3]; 
} 
 
1990/0227    
long 
sysexec(ulong *arg) 
{ 
	Proc *p; 
1991/0705    
	Segment *s, *ts; 
1990/0227    
	ulong l, t, d, b, v; 
	int i; 
1990/08141    
	Chan *tc, *c; 
1990/0227    
	char **argv, **argp; 
	char *a, *charp, *file; 
	char *progarg[sizeof(Exec)/2+1], elem[NAMELEN]; 
1991/0523    
	ulong ssize, spage, nargs, nbytes, n, bssend; 
1990/0227    
	ulong *sp; 
	int indir; 
	Exec exec; 
	char line[sizeof(Exec)]; 
1991/0705    
	Fgrp *f; 
	Image *img; 
1991/0723    
	ulong magic, text, entry, data, bss; 
1990/0227    
 
	p = u->p; 
	validaddr(arg[0], 1, 0); 
	file = (char*)arg[0]; 
	indir = 0; 
    Header: 
	tc = namec(file, Aopen, OEXEC, 0); 
	if(waserror()){ 
		close(tc); 
		nexterror(); 
	} 
	if(!indir) 
		strcpy(elem, u->elem); 
1991/0706    
 
1991/0411    
	n = (*devtab[tc->type].read)(tc, &exec, sizeof(Exec), 0); 
1990/0227    
	if(n < 2) 
    Err: 
1990/11211    
		error(Ebadexec); 
1991/0723    
	magic = l2be(exec.magic); 
	text = l2be(exec.text); 
	entry = l2be(exec.entry); 
	if(n==sizeof(Exec) && magic==AOUT_MAGIC){ 
		if((text&KZERO) 
		|| entry < UTZERO+sizeof(Exec) 
		|| entry >= UTZERO+sizeof(Exec)+text) 
1990/0227    
			goto Err; 
		goto Binary; 
	} 
 
	/* 
	 * Process #! /bin/sh args ... 
	 */ 
1991/0318    
	memmove(line, &exec, sizeof(Exec)); 
1990/0227    
	if(indir || line[0]!='#' || line[1]!='!') 
		goto Err; 
	n = shargs(line, n, progarg); 
	if(n == 0) 
		goto Err; 
	indir = 1; 
	/* 
	 * First arg becomes complete file name 
	 */ 
	progarg[n++] = file; 
	progarg[n] = 0; 
	validaddr(arg[1], BY2WD, 1); 
	arg[1] += BY2WD; 
	file = progarg[0]; 
	progarg[0] = elem; 
	poperror(); 
1991/0614    
	close(tc); 
1990/0227    
	goto Header; 
 
    Binary: 
1991/0705    
	poperror(); 
1991/0723    
	data = l2be(exec.data); 
	bss = l2be(exec.bss); 
	t = (UTZERO+sizeof(Exec)+text+(BY2PG-1)) & ~(BY2PG-1); 
	d = (t + data + (BY2PG-1)) & ~(BY2PG-1); 
	bssend = t + data + bss; 
1990/1211    
	b = (bssend + (BY2PG-1)) & ~(BY2PG-1); 
1990/0227    
	if((t|d|b) & KZERO) 
1990/11211    
		error(Ebadexec); 
1990/0227    
 
	/* 
	 * Args: pass 1: count 
	 */ 
1991/0710    
	nbytes = BY2WD;		/* hole for profiling clock at top of stack */ 
1990/0227    
	nargs = 0; 
	if(indir){ 
		argp = progarg; 
		while(*argp){ 
			a = *argp++; 
			nbytes += strlen(a) + 1; 
			nargs++; 
		} 
	} 
	evenaddr(arg[1]); 
	argp = (char**)arg[1]; 
	validaddr((ulong)argp, BY2WD, 0); 
	while(*argp){ 
		a = *argp++; 
		if(((ulong)argp&(BY2PG-1)) < BY2WD) 
			validaddr((ulong)argp, BY2WD, 0); 
		validaddr((ulong)a, 1, 0); 
1991/0705    
		nbytes += (vmemchr(a, 0, 0xFFFFFFFF) - a) + 1; 
1990/1226    
		nargs++; 
1990/0227    
	} 
	ssize = BY2WD*(nargs+1) + ((nbytes+(BY2WD-1)) & ~(BY2WD-1)); 
	spage = (ssize+(BY2PG-1)) >> PGSHIFT; 
	/* 
	 * Build the stack segment, putting it in kernel virtual for the moment 
	 */ 
1991/0523    
	if(spage > TSTKSIZ) 
1991/0709    
		errors("too many arguments"); 
1991/0522    
 
1991/0705    
	  
	p->seg[ESEG] = newseg(SG_STACK, TSTKTOP-USTKSIZE, USTKSIZE/BY2PG); 
1990/0227    
 
	/* 
	 * Args: pass 2: assemble; the pages will be faulted in 
	 */ 
	argv = (char**)(TSTKTOP - ssize); 
	charp = (char*)(TSTKTOP - nbytes); 
	if(indir) 
		argp = progarg; 
	else 
		argp = (char**)arg[1]; 
1991/0705    
 
1990/0227    
	for(i=0; i<nargs; i++){ 
1991/0705    
		if(indir && *argp==0) { 
1990/0227    
			indir = 0; 
			argp = (char**)arg[1]; 
		} 
		*argv++ = charp + (USTKTOP-TSTKTOP); 
		n = strlen(*argp) + 1; 
1991/0318    
		memmove(charp, *argp++, n); 
1990/0227    
		charp += n; 
	} 
 
1991/0318    
	memmove(p->text, elem, NAMELEN); 
1990/0227    
 
	/* 
1991/0705    
	 * Committed.  Free old memory. Special segments are maintained accross exec 
1990/0227    
	 */ 
1991/0709    
	for(i = SSEG; i <= BSEG; i++) { 
		putseg(p->seg[i]); 
		p->seg[i] = 0;	    /* prevent a second free if we have an error */ 
	} 
1990/08141    
 
	/* 
	 * Close on exec 
	 */ 
1991/0705    
	f = u->p->fgrp; 
	for(i=0; i<=f->maxfd; i++) 
		fdclose(i, CCEXEC); 
1990/0227    
 
1991/0705    
	/* Text.  Shared. Attaches to cache image if possible */ 
1991/0724    
	/* attachimage returns a locked cache image */ 
1991/0705    
	img = attachimage(SG_TEXT|SG_RONLY, tc, UTZERO, (t-UTZERO)>>PGSHIFT); 
	ts = img->s; 
	p->seg[TSEG] = ts; 
1991/0706    
	ts->flushme = 1; 
1991/0705    
	ts->fstart = 0; 
1991/0723    
	ts->flen = sizeof(Exec)+text; 
1991/0724    
	unlock(img); 
1990/0227    
 
1991/0705    
	/* Data. Shared. */ 
	s = newseg(SG_DATA, t, (d-t)>>PGSHIFT); 
	p->seg[DSEG] = s; 
1990/0227    
 
1991/0705    
	/* Attached by hand */ 
	incref(img); 
	s->image = img; 
	s->fstart = ts->fstart+ts->flen; 
1991/0723    
	s->flen = data; 
1990/0227    
 
1991/0705    
	/* BSS. Zero fill on demand */ 
	p->seg[BSEG] = newseg(SG_BSS, d, (b-d)>>PGSHIFT); 
1990/1211    
 
1990/0227    
	/* 
	 * Move the stack 
	 */ 
1991/0705    
	s = p->seg[ESEG]; 
1991/0707    
	p->seg[ESEG] = 0; 
1991/0705    
	p->seg[SSEG] = s; 
	s->base = USTKTOP-USTKSIZE; 
	s->top = USTKTOP; 
	relocateseg(s, TSTKTOP-USTKTOP); 
1990/0227    
 
1991/0706    
	close(tc); 
1991/0705    
 
1991/0529    
	/* 
1991/0705    
	 *  At this point, the mmu contains info about the old address 
1991/0529    
	 *  space and needs to be flushed 
	 */ 
1990/0227    
	flushmmu(); 
1990/1212    
	clearmmucache(); 
1991/1216    
	qlock(&p->debug); 
1990/0227    
	u->nnote = 0; 
	u->notify = 0; 
	u->notified = 0; 
1990/1212    
	procsetup(p); 
1991/1216    
	qunlock(&p->debug); 
1991/1110    
	if(p->hang) 
		p->procctl = Proc_stopme; 
 
1991/1214    
	return execregs(entry, ssize, nargs); 
1990/0227    
} 
 
int 
shargs(char *s, int n, char **ap) 
{ 
	int i; 
 
	s += 2, n -= 2;		/* skip #! */ 
	for(i=0; s[i]!='\n'; i++) 
		if(i == n-1) 
			return 0; 
	s[i] = 0; 
	*ap = 0; 
	i = 0; 
	for(;;){ 
		while(*s==' ' || *s=='\t') 
			s++; 
		if(*s == 0) 
			break; 
		i++; 
		*ap++ = s; 
		*ap = 0; 
		while(*s && *s!=' ' && *s!='\t') 
			s++; 
		if(*s == 0) 
			break; 
		else 
			*s++ = 0; 
	} 
	return i; 
} 
 
int 
return0(void *a) 
{ 
1991/1115    
	USED(a); 
1990/0227    
	return 0; 
} 
 
long 
syssleep(ulong *arg) 
{ 
	tsleep(&u->p->sleep, return0, 0, arg[0]); 
1991/1219    
	if(arg[0] == 0) 
		sched(); 
	else 
		tsleep(&u->p->sleep, return0, 0, arg[0]); 
 
1990/0227    
	return 0; 
} 
 
1991/0513    
long 
sysalarm(ulong *arg) 
{ 
	return procalarm(arg[0]);		 
} 
1990/0227    
 
long 
sysexits(ulong *arg) 
{ 
	char *status; 
1991/0808    
	char *inval = "invalid exit string"; 
1990/0227    
 
	status = (char*)arg[0]; 
	if(status){ 
		if(waserror()) 
1991/0808    
			status = inval; 
1990/0227    
		else{ 
			validaddr((ulong)status, 1, 0); 
1991/0808    
			if(vmemchr(status, 0, ERRLEN) == 0) 
				status = inval; 
1990/0227    
		} 
1991/0614    
		poperror(); 
1991/0705    
 
1990/0227    
	} 
	pexit(status, 1); 
} 
 
long 
syswait(ulong *arg) 
{ 
	if(arg[0]){ 
		validaddr(arg[0], sizeof(Waitmsg), 1); 
		evenaddr(arg[0]); 
	} 
	return pwait((Waitmsg*)arg[0]); 
} 
 
long 
1990/11211    
sysdeath(ulong *arg) 
1990/0227    
{ 
1991/1115    
	USED(arg); 
1990/11211    
	pprint("deprecated system call"); 
	pexit("Suicide", 0); 
1990/0227    
} 
 
long 
syserrstr(ulong *arg) 
{ 
	char buf[ERRLEN]; 
 
1990/11211    
	validaddr(arg[0], ERRLEN, 1); 
1991/0318    
	memmove((char*)arg[0], u->error, ERRLEN); 
1991/0724    
	strncpy(u->error, errstrtab[0], ERRLEN); 
1990/0227    
	return 0; 
} 
 
long 
sysforkpgrp(ulong *arg) 
{ 
1991/0514    
	int mask; 
1990/0227    
	Pgrp *pg; 
1991/0705    
	Egrp *eg; 
1990/0227    
 
	pg = newpgrp(); 
1991/0705    
	eg = newegrp(); 
1990/0227    
	if(waserror()){ 
		closepgrp(pg); 
1991/0705    
		closeegrp(eg); 
1990/0227    
		nexterror(); 
	} 
1991/0514    
 
	mask = arg[0]; 
	if(mask == FPall) 
		mask = FPnote|FPenv|FPnamespc; 
 
	if(mask & FPnamespc) 
1990/0227    
		pgrpcpy(pg, u->p->pgrp); 
1991/0514    
 
	if(mask & FPenv) 
1991/0705    
		envcpy(eg, u->p->egrp); 
1991/0514    
 
	if((mask & FPnote) == 0) { 
		u->nnote = 0; 
		u->notified = 0; 
		memset(u->note, 0, sizeof(u->note)); 
	} 
 
1991/0614    
	poperror(); 
1990/0227    
	closepgrp(u->p->pgrp); 
1991/0705    
	closeegrp(u->p->egrp); 
1990/0227    
	u->p->pgrp = pg; 
1991/0705    
	u->p->egrp = eg; 
1990/0227    
	return pg->pgrpid; 
} 
 
long 
sysnotify(ulong *arg) 
{ 
1991/1115    
	USED(arg); 
1991/0326    
	if(arg[0] != 0) 
		validaddr(arg[0], sizeof(ulong), 0); 
1990/0227    
	u->notify = (int(*)(void*, char*))(arg[0]); 
	return 0; 
} 
 
long 
sysnoted(ulong *arg) 
{ 
1991/1115    
	USED(arg); 
1990/0227    
	if(u->notified == 0) 
1990/11211    
		error(Egreg); 
1990/0227    
	return 0; 
} 
 
long 
1991/0705    
syssegbrk(ulong *arg) 
1990/0227    
{ 
1991/0705    
	Segment *s; 
	int i; 
 
	for(i = 0; i < NSEG; i++) 
		if(s = u->p->seg[i]) { 
			if(arg[0] >= s->base && arg[0] < s->top) { 
				switch(s->type&SG_TYPE) { 
				case SG_TEXT: 
				case SG_DATA: 
					errors("bad segment type"); 
				default: 
					return ibrk(arg[1], i); 
				} 
			} 
		} 
 
	errors("not in address space"); 
1990/0227    
} 
1991/0606    
 
1991/0605    
long 
1991/0705    
syssegattach(ulong *arg) 
1991/0605    
{ 
1991/0705    
	return segattach(u->p, arg[0], (char*)arg[1], arg[2], arg[3]); 
} 
 
long 
syssegdetach(ulong *arg) 
{ 
	int i; 
	Segment *s; 
 
1991/0723    
	s = 0; 
1991/0705    
	for(i = 0; i < NSEG; i++) 
		if(s = u->p->seg[i]) { 
			qlock(&s->lk); 
			if((arg[0] >= s->base && arg[0] < s->top) ||  
			   (s->top == s->base && arg[0] == s->base)) 
				goto found; 
			qunlock(&s->lk); 
		} 
 
	errors("not in address space"); 
 
found: 
	if((ulong)arg >= s->base && (ulong)arg < s->top) { 
		qunlock(&s->lk); 
		errors("illegal address"); 
	} 
	u->p->seg[i] = 0; 
	qunlock(&s->lk); 
	putseg(s); 
 
	/* Ensure we flush any entries from the lost segment */ 
	flushmmu(); 
	return 0; 
} 
 
long 
syssegfree(ulong *arg) 
{ 
	Segment *s; 
1991/0712    
	ulong from, pages; 
1991/0705    
 
1991/0706    
	from = PGROUND(arg[0]); 
	s = seg(u->p, from, 1); 
1991/0705    
	if(s == 0) 
		errors("not in address space"); 
 
1991/0712    
	pages = (arg[1]+BY2PG-1)/BY2PG; 
1991/0705    
 
1991/0712    
	if(from+pages*BY2PG > s->top) { 
1991/0705    
		qunlock(&s->lk); 
		errors("segment too short"); 
	} 
 
1991/0712    
	mfreeseg(s, from, pages); 
1991/0705    
	qunlock(&s->lk); 
 
	return 0; 
} 
 
/* For binary compatability */ 
long 
sysbrk_(ulong *arg) 
{ 
	return ibrk(arg[0], BSEG); 
1991/0605    
} 
1991/0806    
 
long 
sysrendezvous(ulong *arg) 
{ 
	Proc *p, *d, **l; 
	int s, tag; 
	ulong val; 
 
	tag = arg[0]; 
	l = &REND(u->p->pgrp, tag); 
 
	lock(u->p->pgrp); 
	for(p = *l; p; p = p->rendhash) { 
		if(p->rendtag == tag) { 
			*l = p->rendhash; 
			val = p->rendval; 
			p->rendval = arg[1]; 
 
1991/0807    
			while(p->state != Rendezvous) 
				; 
1991/0806    
			ready(p); 
			unlock(u->p->pgrp); 
			return val;	 
		} 
		l = &p->rendhash; 
	} 
 
	/* Going to sleep here */ 
	p = u->p; 
	p->rendtag = tag; 
	p->rendval = arg[1]; 
	p->rendhash = *l; 
	*l = p; 
 
	s = splhi(); 
1991/0807    
	unlock(p->pgrp); 
1991/0806    
	u->p->state = Rendezvous; 
	sched(); 
	splx(s); 
 
	return u->p->rendval; 
} 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)