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

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

port/sysproc.c on 1990/0227
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**); 
 
long 
sysr1(ulong *arg) 
{ 
1990/1123    
	print("[%s %s %d] r1 = %d\n", u->p->pgrp->user, u->p->text, u->p->pid, arg[0]); 
1990/0227    
	return 0; 
} 
 
long 
sysfork(ulong *arg) 
{ 
	Proc *p; 
	Seg *s; 
	Page *np, *op; 
	ulong usp, upa, pid; 
	Chan *c; 
	Orig *o; 
1990/0614    
	KMap *k; 
1990/0227    
	int n, on, i; 
	int lastvar;	/* used to compute stack address */ 
 
	/* 
	 * Kernel stack 
	 */ 
	p = newproc(); 
	p->upage = newpage(1, 0, USERADDR|(p->pid&0xFFFF)); 
1990/0614    
	k = kmap(p->upage); 
	upa = VA(k); 
 
1990/0227    
	/* 
	 * Save time: only copy u-> data and useful stack 
	 */ 
1991/0529    
	clearmmucache();	/* so child doesn't inherit any of your mappings */ 
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    
 
	/* 
	 * User stack 
	 */ 
	p->seg[SSEG] = u->p->seg[SSEG]; 
	s = &p->seg[SSEG]; 
	s->proc = p; 
	on = (s->maxva-s->minva)>>PGSHIFT; 
1990/0614    
	usp = ((Ureg*)UREGADDR)->usp; 
1990/0227    
	if(usp >= USTKTOP) 
		panic("fork bad usp %lux", usp); 
	if(usp < u->p->seg[SSEG].minva) 
		s->minva = u->p->seg[SSEG].minva; 
	else 
		s->minva = usp & ~(BY2PG-1); 
	usp = s->minva & (BY2PG-1);	/* just low bits */ 
	s->maxva = USTKTOP; 
	n = (s->maxva-s->minva)>>PGSHIFT; 
1991/0607    
	s->o = neworig(s->minva, n, OWRPERM|OISMEM, 0); 
1990/0227    
	lock(s->o); 
	/* 
	 * Only part of last stack page 
	 */ 
	for(i=0; i<n; i++){ 
		op = u->p->seg[SSEG].o->pte[i+(on-n)].page; 
		if(op){ 
			np = newpage(1, s->o, op->va); 
1990/0614    
			k = kmap(np); 
1990/0227    
			p->seg[SSEG].o->pte[i].page = np; 
			if(i == 0){	/* only part of last stack page */ 
1990/0614    
				memset((void*)VA(k), 0, usp); 
1991/0318    
				memmove((void*)(VA(k)+usp), 
1990/0614    
					(void*)(op->va+usp), BY2PG-usp); 
1990/0227    
			}else		/* all of higher pages */ 
1991/0318    
				memmove((void*)VA(k), (void*)op->va, BY2PG); 
1990/0614    
			kunmap(k); 
1990/0227    
		} 
	} 
	unlock(s->o); 
	/* 
	 * Duplicate segments 
	 */ 
	for(s=&u->p->seg[0], n=0; n<NSEG; n++, s++){ 
		if(n == SSEG)		/* already done */ 
			continue; 
		if(s->o == 0) 
			continue; 
		p->seg[n] = *s; 
		p->seg[n].proc = p; 
		o = s->o; 
		lock(o); 
		o->nproc++; 
		if(s->mod) 
			forkmod(s, &p->seg[n], p); 
		unlock(o); 
	} 
	/* 
	 * Refs 
	 */ 
	incref(u->dot); 
	for(n=0; n<=u->maxfd; n++) 
		if(c = u->fd[n])	/* assign = */ 
			incref(c); 
	/* 
	 * Sched 
	 */ 
	if(setlabel(&p->sched)){ 
		u->p = p; 
		p->state = Running; 
		p->mach = m; 
		m->proc = p; 
		spllo(); 
		return 0; 
	} 
	p->parent = u->p; 
	p->parentpid = u->p->pid; 
	p->pgrp = u->p->pgrp; 
1991/0118    
	p->fpstate = u->p->fpstate; 
1990/0227    
	incref(p->pgrp); 
1990/0324    
	u->p->nchild++; 
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/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; 
} 
 
long 
sysexec(ulong *arg) 
{ 
	Proc *p; 
	Seg *s; 
	ulong l, t, d, b, v; 
	int i; 
1990/08141    
	Chan *tc, *c; 
1990/0227    
	Orig *o; 
	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)]; 
 
	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/0411    
	n = (*devtab[tc->type].read)(tc, &exec, sizeof(Exec), 0); 
1990/0227    
	if(n < 2) 
    Err: 
1990/11211    
		error(Ebadexec); 
1990/1211    
	if(n==sizeof(Exec) && exec.magic==AOUT_MAGIC){ 
1990/0227    
		if((exec.text&KZERO) 
		|| (ulong)exec.entry < UTZERO+sizeof(Exec) 
		|| (ulong)exec.entry >= UTZERO+sizeof(Exec)+exec.text) 
			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: 
	t = (UTZERO+sizeof(Exec)+exec.text+(BY2PG-1)) & ~(BY2PG-1); 
1990/1212    
	d = (t + exec.data + (BY2PG-1)) & ~(BY2PG-1); 
1990/1211    
	bssend = t + exec.data + exec.bss; 
	b = (bssend + (BY2PG-1)) & ~(BY2PG-1); 
1990/0227    
	if((t|d|b) & KZERO) 
1990/11211    
		error(Ebadexec); 
1990/0227    
 
	/* 
	 * Args: pass 1: count 
	 */ 
	nbytes = 0; 
	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); 
		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/0522    
		errors("not enough argument stack space"); 
 
1990/0227    
	s = &p->seg[ESEG]; 
	s->proc = p; 
1991/0607    
	s->o = neworig(TSTKTOP-(spage<<PGSHIFT), spage, OWRPERM|OISMEM, 0); 
1990/0227    
	s->minva = s->o->va; 
	s->maxva = TSTKTOP; 
 
	/* 
	 * 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]; 
	for(i=0; i<nargs; i++){ 
		if(indir && *argp==0){ 
			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    
 
	/* 
	 * Committed.  Free old memory 
	 */ 
	freesegs(ESEG); 
1990/08141    
 
	/* 
	 * Close on exec 
	 */ 
	for(i=0; i<=u->maxfd; i++) 
		if((c=u->fd[i]) && c->flag&CCEXEC){ 
			close(c); 
			fdclose(i); 
		} 
1990/0227    
 
	/* 
	 * Text.  Shared. 
	 */ 
	s = &p->seg[TSEG]; 
	s->proc = p; 
1991/0607    
	o = lookorig(UTZERO, (t-UTZERO)>>PGSHIFT, OCACHED|OISMEM, tc); 
1990/0227    
	if(o == 0){ 
1991/0607    
		o = neworig(UTZERO, (t-UTZERO)>>PGSHIFT, OCACHED|OISMEM, tc); 
1990/0227    
		o->minca = 0; 
		o->maxca = sizeof(Exec)+exec.text; 
	} 
	s->o = o; 
	s->minva = UTZERO; 
	s->maxva = t; 
	s->mod = 0; 
 
	/* 
	 * Data.  Shared. 
	 */ 
	s = &p->seg[DSEG]; 
	s->proc = p; 
1991/0607    
	o = lookorig(t, (d-t)>>PGSHIFT, OWRPERM|OPURE|OCACHED|OISMEM, tc); 
1990/0227    
	if(o == 0){ 
1991/0607    
		o = neworig(t, (d-t)>>PGSHIFT, OWRPERM|OPURE|OCACHED|OISMEM, tc); 
1990/0227    
		o->minca = p->seg[TSEG].o->maxca; 
1990/1212    
		o->maxca = o->minca + exec.data; 
1990/0227    
	} 
	s->o = o; 
	s->minva = t; 
	s->maxva = d; 
	s->mod = 0; 
 
	/* 
1990/1212    
	 * BSS.  Created afresh. 
1990/0227    
	 */ 
	s = &p->seg[BSEG]; 
	s->proc = p; 
1991/0607    
	o = neworig(d, (b-d)>>PGSHIFT, OWRPERM|OISMEM, 0); 
1990/1212    
	o->minca = 0; 
	o->maxca = 0; 
1990/0227    
	s->o = o; 
	s->minva = d; 
	s->maxva = b; 
	s->mod = 0; 
 
1991/0614    
	poperror(); 
1990/0227    
	close(tc); 
 
1991/0606    
	p->seg[BSEG].endseg = bssend; 
1990/1211    
 
1990/0227    
	/* 
	 * Move the stack 
	 */ 
	s = &p->seg[SSEG]; 
	*s = p->seg[ESEG]; 
	p->seg[ESEG].o = 0; 
	o = s->o; 
	o->va += (USTKTOP-TSTKTOP); 
	s->minva = o->va; 
	s->maxva = USTKTOP; 
	lock(o); 
	for(i=0; i<o->npte; i++) 
		o->pte[i].page->va += (USTKTOP-TSTKTOP); 
	unlock(o); 
 
1991/0529    
	/* 
	 *  at this point, the mmu contains info about the old address 
	 *  space and needs to be flushed 
	 */ 
1990/0227    
	flushmmu(); 
1990/1212    
	clearmmucache(); 
1990/1226    
	execpc(exec.entry); 
1990/0227    
	sp = (ulong*)(USTKTOP - ssize); 
	*--sp = nargs; 
1990/0614    
	((Ureg*)UREGADDR)->usp = (ulong)sp; 
1990/0227    
	lock(&p->debug); 
	u->nnote = 0; 
	u->notify = 0; 
	u->notified = 0; 
1990/1212    
	procsetup(p); 
1990/0227    
	unlock(&p->debug); 
	return 0; 
} 
 
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) 
{ 
	return 0; 
} 
 
long 
syssleep(ulong *arg) 
{ 
	tsleep(&u->p->sleep, return0, 0, arg[0]); 
	return 0; 
} 
 
1991/0513    
long 
sysalarm(ulong *arg) 
{ 
	return procalarm(arg[0]);		 
} 
1990/0227    
 
long 
sysexits(ulong *arg) 
{ 
	char *status; 
 
	status = (char*)arg[0]; 
	if(status){ 
		if(waserror()) 
			status = "invalid exit string"; 
		else{ 
			validaddr((ulong)status, 1, 0); 
			vmemchr(status, 0, ERRLEN); 
		} 
1991/0614    
		poperror(); 
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    
{ 
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); 
1990/0227    
	return 0; 
} 
 
long 
sysforkpgrp(ulong *arg) 
{ 
1991/0514    
	int mask; 
1990/0227    
	Pgrp *pg; 
 
	pg = newpgrp(); 
	if(waserror()){ 
		closepgrp(pg); 
		nexterror(); 
	} 
1991/0514    
 
	mask = arg[0]; 
	if(mask == FPall) 
		mask = FPnote|FPenv|FPnamespc; 
 
	memmove(pg->user, u->p->pgrp->user, NAMELEN); 
 
	if(mask & FPnamespc) 
1990/0227    
		pgrpcpy(pg, u->p->pgrp); 
1991/0514    
 
	if(mask & FPenv) 
		envcpy(pg, u->p->pgrp); 
 
	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); 
	u->p->pgrp = pg; 
	return pg->pgrpid; 
} 
 
long 
sysnotify(ulong *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) 
{ 
	if(u->notified == 0) 
1990/11211    
		error(Egreg); 
1990/0227    
	return 0; 
} 
 
/* 
 * Temporary; should be replaced by a generalized segment control operator 
 */ 
long 
sysbrk_(ulong *arg) 
{ 
1991/0606    
	return ibrk(arg[0], BSEG); 
1990/0227    
} 
1991/0606    
 
1991/0605    
long 
1991/0606    
syslkbrk_(ulong *arg) 
1991/0605    
{ 
1991/0606    
	return ibrk(arg[0], LSEG); 
1991/0605    
} 


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