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

1993/1013/port/devproc.c (diff list | history)

1993/1013/sys/src/9/port/devproc.c:1,8271993/1018/sys/src/9/port/devproc.c:1,850 (short | long | prev | next)
1990/0227    
#include	"u.h" 
1992/0321    
#include	"../port/lib.h" 
1990/0227    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
1992/0111    
#include	"../port/error.h" 
1991/1110    
#include	"ureg.h" 
1990/0227    
 
#include	"devtab.h" 
 
1993/0501    
enum 
{ 
1990/0227    
	Qctl, 
1993/0818    
	Qdir, 
	Qfpregs, 
	Qkregs, 
1990/0227    
	Qmem, 
	Qnote, 
1993/1018    
	Qnoteid, 
1990/1110    
	Qnotepg, 
1993/0818    
	Qns, 
1993/0828    
	Qproc, 
1993/0818    
	Qregs, 
1991/0705    
	Qsegment, 
1990/0227    
	Qstatus, 
	Qtext, 
1993/0309    
	Qwait, 
1990/0227    
}; 
 
1992/0814    
#define	STATSIZE	(2*NAMELEN+12+7*12) 
1992/0824    
Dirtab procdir[] = 
{ 
1991/1109    
	"ctl",		{Qctl},		0,			0000, 
1993/0818    
	"fpregs",	{Qfpregs},	sizeof(FPsave),		0000, 
	"kregs",	{Qkregs},	sizeof(Ureg),		0000, 
1991/1109    
	"mem",		{Qmem},		0,			0000, 
	"note",		{Qnote},	0,			0000, 
1993/1018    
	"noteid",	{Qnoteid},	0,			0666, 
1991/1112    
	"notepg",	{Qnotepg},	0,			0000, 
1993/0818    
	"ns",		{Qns},		0,			0400, 
1993/0828    
	"proc",		{Qproc},	0,			0400, 
1993/0818    
	"regs",		{Qregs},	sizeof(Ureg),		0000, 
1991/1112    
	"segment",	{Qsegment},	0,			0444, 
	"status",	{Qstatus},	STATSIZE,		0444, 
1991/1109    
	"text",		{Qtext},	0,			0000, 
1993/0309    
	"wait",		{Qwait},	0,			0400, 
1990/0227    
}; 
 
1991/1109    
/* Segment type from portdat.h */ 
1992/0430    
char *sname[]={ "Text", "Data", "Bss", "Stack", "Shared", "Phys", "Shdata" }; 
1991/0705    
 
1990/0227    
/* 
1990/11211    
 * Qids are, in path: 
1990/0227    
 *	 4 bits of file type (qids above) 
1990/1128    
 *	23 bits of process slot number + 1 
1990/11211    
 *	     in vers, 
 *	32 bits of pid, for consistency checking 
1992/0428    
 * If notepg, c->pgrpid.path is pgrp slot, .vers is noteid. 
1990/0227    
 */ 
#define	NPROC	(sizeof procdir/sizeof(Dirtab)) 
#define	QSHIFT	4	/* location in qid of proc slot # */ 
 
1992/0428    
#define	QID(q)		(((q).path&0x0000000F)>>0) 
#define	SLOT(q)		((((q).path&0x07FFFFFF0)>>QSHIFT)-1) 
#define	PID(q)		((q).vers) 
#define	NOTEID(q)	((q).vers) 
 
1991/1109    
void	procctlreq(Proc*, char*, int); 
int	procctlmemio(Proc*, ulong, int, void*, int); 
1992/0824    
Chan*	proctext(Chan*, Proc*); 
Segment* txt2data(Proc*, Segment*); 
1991/1110    
int	procstopped(void*); 
1993/0501    
void	mntscan(Mntwalk*); 
1991/1109    
 
1990/0227    
int 
procgen(Chan *c, Dirtab *tab, int ntab, int s, Dir *dp) 
{ 
1992/0824    
	Qid qid; 
1990/0227    
	Proc *p; 
	char buf[NAMELEN]; 
1993/0311    
	ulong pid, path, perm, len; 
1990/0227    
 
1992/0711    
	USED(ntab); 
1990/11211    
	if(c->qid.path == CHDIR){ 
1990/0227    
		if(s >= conf.nproc) 
			return -1; 
		p = proctab(s); 
		pid = p->pid; 
		if(pid == 0) 
			return 0; 
		sprint(buf, "%d", pid); 
1992/0824    
		qid = (Qid){CHDIR|((s+1)<<QSHIFT), pid}; 
		devdir(c, qid, buf, 0, p->user, CHDIR|0555, dp); 
1990/0227    
		return 1; 
	} 
	if(s >= NPROC) 
		return -1; 
	if(tab) 
		panic("procgen"); 
1992/0824    
 
1990/0227    
	tab = &procdir[s]; 
1991/0705    
	path = c->qid.path&~(CHDIR|((1<<QSHIFT)-1));	/* slot component */ 
1991/1109    
 
	p = proctab(SLOT(c->qid)); 
	perm = tab->perm; 
	if(perm == 0) 
		perm = p->procmode; 
 
1993/0311    
	len = tab->length; 
	if(QID(c->qid) == Qwait) 
		len = p->nwait * sizeof(Waitmsg); 
 
1992/0824    
	qid = (Qid){path|tab->qid.path, c->qid.vers}; 
1993/0311    
	devdir(c, qid, tab->name, len, p->user, perm, dp); 
1990/0227    
	return 1; 
} 
 
void 
procinit(void) 
{ 
	if(conf.nproc >= (1<<(16-QSHIFT))-1) 
		print("warning: too many procs for devproc\n"); 
} 
 
void 
procreset(void) 
{ 
} 
 
Chan* 
procattach(char *spec) 
{ 
	return devattach('p', spec); 
} 
 
Chan* 
procclone(Chan *c, Chan *nc) 
{ 
	return devclone(c, nc); 
} 
 
int 
procwalk(Chan *c, char *name) 
{ 
1991/1106    
	if(strcmp(name, "..") == 0) { 
1991/1011    
		c->qid.path = Qdir|CHDIR; 
		return 1; 
	} 
 
1990/0227    
	return devwalk(c, name, 0, 0, procgen); 
} 
 
void 
procstat(Chan *c, char *db) 
{ 
	devstat(c, db, 0, 0, procgen); 
} 
 
Chan * 
procopen(Chan *c, int omode) 
{ 
	Proc *p; 
1990/1110    
	Pgrp *pg; 
1990/0227    
	Chan *tc; 
 
1991/1112    
	if(c->qid.path & CHDIR) 
		return devopen(c, omode, 0, 0, procgen); 
 
1990/0227    
	p = proctab(SLOT(c->qid)); 
1990/1110    
	pg = p->pgrp; 
1990/11211    
	if(p->pid != PID(c->qid)) 
		error(Eprocdied); 
1991/1110    
 
1990/0227    
	omode = openmode(omode); 
 
	switch(QID(c->qid)){ 
	case Qtext: 
1993/0501    
		if(omode != OREAD) 
			error(Eperm); 
1991/1110    
		tc = proctext(c, p); 
1990/0227    
		tc->offset = 0; 
		return tc; 
1991/1110    
 
1993/0828    
	case Qproc: 
1993/0818    
	case Qkregs: 
	case Qsegment: 
		if(omode != OREAD) 
			error(Eperm); 
		break; 
 
1990/0227    
	case Qctl: 
	case Qnote: 
1993/1018    
	case Qnoteid: 
1991/1110    
	case Qmem: 
1991/1112    
	case Qstatus: 
1993/0309    
	case Qwait: 
1993/0818    
	case Qregs: 
	case Qfpregs: 
1990/0227    
		break; 
1990/1110    
 
1993/0501    
	case Qns: 
1993/0818    
		if(omode != OREAD) 
			error(Eperm); 
1993/0501    
		c->aux = malloc(sizeof(Mntwalk)); 
		break; 
 
1990/1110    
	case Qnotepg: 
1992/0824    
		if(omode!=OWRITE || pg->pgrpid == 1) 
1990/11211    
			error(Eperm); 
1992/0824    
		c->pgrpid.path = pg->pgrpid+1; 
1992/0428    
		c->pgrpid.vers = p->noteid; 
1990/1110    
		break; 
1992/0824    
 
1990/0227    
	default: 
1992/0114    
		pprint("procopen %lux\n", c->qid); 
1990/11211    
		error(Egreg); 
1990/0227    
	} 
1991/1110    
 
	/* Affix pid to qid */ 
1990/0227    
	if(p->state != Dead) 
1990/11211    
		c->qid.vers = p->pid; 
1991/1112    
 
	return devopen(c, omode, 0, 0, procgen); 
1990/0227    
} 
 
void 
proccreate(Chan *c, char *name, int omode, ulong perm) 
{ 
1991/1115    
	USED(c, name, omode, perm); 
1990/11211    
	error(Eperm); 
1990/0227    
} 
 
void 
procremove(Chan *c) 
{ 
1991/1115    
	USED(c); 
1990/11211    
	error(Eperm); 
1990/0227    
} 
 
void 
procwstat(Chan *c, char *db) 
{ 
1991/1109    
	Proc *p; 
	Dir d; 
 
1991/1112    
	if(c->qid.path&CHDIR) 
		error(Eperm); 
 
1991/1109    
	p = proctab(SLOT(c->qid)); 
	if(p->pid != PID(c->qid)) 
		error(Eprocdied); 
 
1993/0501    
	if(strcmp(up->user, p->user) != 0 && strcmp(up->user, eve) != 0) 
1991/1109    
		error(Eperm); 
 
1993/1013    
	convM2D(db, &d); 
1991/1109    
	p->procmode = d.mode&0777; 
1990/0227    
} 
 
void 
procclose(Chan * c) 
{ 
1993/1013    
	if(QID(c->qid) == Qns && c->aux != 0) 
1993/0501    
		free(c->aux); 
1990/0227    
} 
 
long 
1991/0411    
procread(Chan *c, void *va, long n, ulong offset) 
1990/0227    
{ 
1993/0501    
	long l; 
1990/0227    
	Proc *p; 
1993/0309    
	Waitq *wq; 
1993/0818    
	Ureg kur; 
	uchar *rptr; 
1993/0501    
	Mntwalk *mw; 
1993/0818    
	int i, j, rsize; 
1993/0501    
	Segment *sg, *s; 
	char *a = va, *sps; 
	char statbuf[NSEG*32]; 
1990/0227    
 
1990/11211    
	if(c->qid.path & CHDIR) 
1990/0227    
		return devdirread(c, a, n, 0, 0, procgen); 
 
	p = proctab(SLOT(c->qid)); 
1990/11211    
	if(p->pid != PID(c->qid)) 
		error(Eprocdied); 
1990/0227    
 
	switch(QID(c->qid)){ 
	case Qmem: 
1993/0818    
		if(offset < KZERO) 
			return procctlmemio(p, offset, n, va, 1); 
1992/0824    
 
1993/0818    
		/* Protect crypt key memory */ 
		if(offset >= palloc.cmembase&&offset < palloc.cmemtop) 
			error(Eperm); 
 
		/* validate physical kernel addresses */ 
		if(offset < (ulong)end) { 
			if(offset+n > (ulong)end) 
				n = (ulong)end - offset; 
			memmove(a, (char*)offset, n); 
1993/0908    
			return n; 
1990/0227    
		} 
1993/0818    
		if(offset >= conf.base0 && offset < conf.npage0){ 
			if(offset+n > conf.npage0) 
				n = conf.npage0 - offset; 
			memmove(a, (char*)offset, n); 
1993/0908    
			return n; 
1993/0818    
		} 
		if(offset >= conf.base1 && offset < conf.npage1){ 
			if(offset+n > conf.npage1) 
				n = conf.npage1 - offset; 
			memmove(a, (char*)offset, n); 
1993/0908    
			return n; 
1993/0818    
		} 
		error(Ebadarg); 
1991/1109    
 
1990/0227    
	case Qnote: 
1991/1216    
		qlock(&p->debug); 
1990/0227    
		if(waserror()){ 
1991/1216    
			qunlock(&p->debug); 
1990/0227    
			nexterror(); 
		} 
1990/11211    
		if(p->pid != PID(c->qid)) 
			error(Eprocdied); 
1990/0227    
		if(n < ERRLEN) 
1990/11211    
			error(Etoosmall); 
1993/0501    
		if(p->nnote == 0) 
1990/0227    
			n = 0; 
1993/0501    
		else { 
			memmove(va, p->note[0].msg, ERRLEN); 
			p->nnote--; 
			memmove(p->note, p->note+1, p->nnote*sizeof(Note)); 
1990/0227    
			n = ERRLEN; 
		} 
1993/0501    
		if(p->nnote == 0) 
1991/1111    
			p->notepending = 0; 
1991/0614    
		poperror(); 
1991/1216    
		qunlock(&p->debug); 
1990/0227    
		return n; 
1993/0828    
 
	case Qproc: 
 
		return readnum(offset, va, n, (ulong)p, NUMSIZE); 
1990/0227    
 
1993/0818    
	case Qregs: 
		rptr = (uchar*)p->dbgreg; 
		rsize = sizeof(Ureg); 
		goto regread; 
 
	case Qkregs: 
		memset(&kur, 0, sizeof(Ureg)); 
		kur.pc = p->sched.pc; 
		kur.sp = p->sched.sp; 
1993/0908    
		kur.r31 = (ulong)sched; 
1993/0818    
		rptr = (uchar*)&kur; 
		rsize = sizeof(Ureg); 
		goto regread; 
 
	case Qfpregs: 
		rptr = (uchar*)&p->fpsave; 
		rsize = sizeof(FPsave); 
	regread: 
		if(offset >= rsize) 
1990/0227    
			return 0; 
1993/0818    
		if(offset+n > rsize) 
			n = rsize - offset; 
		memmove(a, rptr+offset, n); 
1990/0227    
		return n; 
 
	case Qstatus: 
1991/0712    
		if(offset >= STATSIZE) 
1990/0227    
			return 0; 
1991/0712    
		if(offset+n > STATSIZE) 
			n = STATSIZE - offset; 
1992/0423    
 
1992/0907    
		sps = p->psstate; 
		if(sps == 0) 
			sps = statename[p->state]; 
1992/1103    
		memset(statbuf, ' ', sizeof statbuf); 
		memmove(statbuf+0*NAMELEN, p->text, strlen(p->text)); 
		memmove(statbuf+1*NAMELEN, p->user, strlen(p->user)); 
		memmove(statbuf+2*NAMELEN, sps, strlen(sps)); 
		j = 2*NAMELEN + 12; 
1992/0907    
 
		for(i = 0; i < 6; i++) { 
1990/0227    
			l = p->time[i]; 
			if(i == TReal) 
				l = MACHP(0)->ticks - l; 
1990/0614    
			l = TK2MS(l); 
1991/0712    
			readnum(0, statbuf+j+NUMSIZE*i, NUMSIZE, l, NUMSIZE); 
1990/0227    
		} 
1992/0814    
		/* ignore stack, which is mostly non-existent */ 
		l = 0; 
		for(i=1; i<NSEG; i++){ 
			s = p->seg[i]; 
			if(s) 
				l += s->top - s->base; 
		} 
		readnum(0, statbuf+j+NUMSIZE*6, NUMSIZE, l>>10, NUMSIZE); 
1991/0411    
		memmove(a, statbuf+offset, n); 
1990/0227    
		return n; 
1991/1110    
 
1991/0705    
	case Qsegment: 
		j = 0; 
1993/0818    
		for(i = 0; i < NSEG; i++) { 
			sg = p->seg[i]; 
			if(sg == 0) 
				continue; 
			j += sprint(&statbuf[j], "%-6s %c %.8lux %.8lux %4d\n", 
				sname[sg->type&SG_TYPE], 
				sg->type&SG_RONLY ? 'R' : ' ', 
1991/0705    
				sg->base, sg->top, sg->ref); 
1993/0818    
		} 
1991/0705    
		if(offset >= j) 
			return 0; 
		if(offset+n > j) 
			n = j-offset; 
1991/1112    
		if(n == 0 && offset == 0) 
1992/0114    
			exhausted("segments"); 
1991/0705    
		memmove(a, &statbuf[offset], n); 
		return n; 
1993/0309    
 
	case Qwait: 
		if(n < sizeof(Waitmsg)) 
			error(Etoosmall); 
 
		if(!canqlock(&p->qwaitr)) 
			error(Einuse); 
 
		if(waserror()) { 
			qunlock(&p->qwaitr); 
			nexterror(); 
		} 
 
		lock(&p->exl); 
1993/0501    
		if(up == p && p->nchild == 0 && p->waitq == 0) { 
1993/0311    
			unlock(&p->exl); 
			error(Enochild); 
		} 
1993/0309    
		while(p->waitq == 0) { 
			unlock(&p->exl); 
			sleep(&p->waitr, haswaitq, p); 
			lock(&p->exl); 
		} 
		wq = p->waitq; 
		p->waitq = wq->next; 
		p->nwait--; 
		unlock(&p->exl); 
 
		qunlock(&p->qwaitr); 
		poperror(); 
		memmove(a, &wq->w, sizeof(Waitmsg)); 
		free(wq); 
		return sizeof(Waitmsg); 
1993/0501    
 
	case Qns: 
		mw = c->aux; 
		mntscan(mw); 
		if(mw->mh == 0) 
			return 0; 
		if(n < NAMELEN+11) 
			error(Etoosmall); 
		i = sprint(a, "%s %d ", mw->cm->spec, mw->cm->flag); 
		n -= i; 
		a += i; 
		i = ptpath(mw->mh->from->path, a, n); 
		n -= i; 
		a += i; 
		if(n > 0) { 
			*a++ = ' '; 
			n--; 
		} 
		a += ptpath(mw->cm->to->path, a, n); 
		return a - (char*)va; 
1993/1018    
	case Qnoteid: 
		return readnum(offset, va, n, p->noteid, NUMSIZE); 
1990/0227    
	} 
1990/11211    
	error(Egreg); 
1992/0520    
	return 0;		/* not reached */ 
1990/0227    
} 
 
1993/0501    
void 
mntscan(Mntwalk *mw) 
{ 
	Pgrp *pg; 
	Mount *t; 
	int nxt; 
	ulong last, bestmid; 
	Mhead **h, **he, *f; 
1990/0227    
 
1993/0501    
	pg = up->pgrp; 
	rlock(&pg->ns); 
 
	nxt = 0; 
	last = 0; 
	bestmid = ~0; 
	if(mw->mh) 
		last = mw->cm->mountid; 
 
	he = &pg->mnthash[MNTHASH]; 
	for(h = pg->mnthash; h < he; h++) { 
		for(f = *h; f; f = f->hash) { 
			for(t = f->mount; t; t = t->next) { 
				if(mw->mh == 0 || 
				  (t->mountid > last && t->mountid < bestmid)) { 
					mw->cm = t; 
					mw->mh = f; 
					bestmid = mw->cm->mountid; 
					nxt = 1; 
				} 
			} 
		} 
	} 
	if(nxt == 0) 
		mw->mh = 0; 
 
	runlock(&pg->ns); 
} 
 
1990/0227    
long 
1991/0411    
procwrite(Chan *c, void *va, long n, ulong offset) 
1990/0227    
{ 
	Proc *p; 
1993/1018    
	int id; 
	Proc *p, *t, *et; 
1990/0227    
	char buf[ERRLEN]; 
 
1990/11211    
	if(c->qid.path & CHDIR) 
		error(Eisdir); 
1990/1110    
 
1990/1126    
	p = proctab(SLOT(c->qid)); 
1991/1109    
 
1993/0501    
	/* Use the remembered noteid in the channel rather 
	 * than the process pgrpid 
	 */ 
1992/0428    
	if(QID(c->qid) == Qnotepg) { 
		pgrpnote(NOTEID(c->pgrpid), va, n, NUser); 
1990/1110    
		return n; 
	} 
 
1991/1216    
	qlock(&p->debug); 
1990/0227    
	if(waserror()){ 
1991/1216    
		qunlock(&p->debug); 
1990/0227    
		nexterror(); 
	} 
1990/11211    
	if(p->pid != PID(c->qid)) 
		error(Eprocdied); 
1990/0227    
 
	switch(QID(c->qid)){ 
1991/1109    
	case Qmem: 
1991/1110    
		if(p->state != Stopped) 
1992/0114    
			error(Ebadctl); 
1991/1110    
 
1993/0501    
		n = procctlmemio(p, offset, n, va, 0); 
1993/0818    
		break; 
 
	case Qregs: 
		if(offset >= sizeof(Ureg)) 
			return 0; 
		if(offset+n > sizeof(Ureg)) 
			n = sizeof(Ureg) - offset; 
		setregisters(p->dbgreg, (char*)(p->dbgreg)+offset, va, n); 
		break; 
 
	case Qfpregs: 
		if(offset >= sizeof(FPsave)) 
			return 0; 
		if(offset+n > sizeof(FPsave)) 
			n = sizeof(FPsave) - offset; 
		memmove((uchar*)&p->fpsave+offset, va, n); 
1991/1110    
		break; 
 
1990/0227    
	case Qctl: 
1991/1109    
		procctlreq(p, va, n); 
1991/1110    
		break; 
 
1990/0227    
	case Qnote: 
1991/1112    
		if(p->kp) 
1992/0114    
			error(Eperm); 
1990/0227    
		if(n >= ERRLEN-1) 
1990/11211    
			error(Etoobig); 
1991/0318    
		memmove(buf, va, n); 
1990/0227    
		buf[n] = 0; 
		if(!postnote(p, 0, buf, NUser)) 
1992/0527    
			error("note not posted"); 
1990/0227    
		break; 
1991/1110    
                 
1993/1018    
	case Qnoteid: 
		id = atoi((char*)va); 
		if(id == p->pid) { 
			p->noteid = id; 
			break; 
		} 
		t = proctab(0); 
		for(et = t+conf.nproc; t < et; t++) { 
			if(id == t->noteid) { 
				if(strcmp(p->user, t->user) != 0) 
					error(Eperm); 
				p->noteid = id; 
				break; 
			} 
		} 
		if(p->noteid != id) 
			error(Ebadarg); 
		break; 
1990/0227    
	default: 
		pprint("unknown qid in procwrite\n"); 
1990/11211    
		error(Egreg); 
1990/0227    
	} 
1991/0614    
	poperror(); 
1991/1216    
	qunlock(&p->debug); 
1991/1109    
	return n; 
} 
 
Chan * 
1991/1110    
proctext(Chan *c, Proc *p) 
{ 
	Chan *tc; 
	Image *i; 
	Segment *s; 
 
	s = p->seg[TSEG]; 
1991/1112    
	if(s == 0) 
1992/0114    
		error(Enonexist); 
1991/1112    
	if(p->state==Dead) 
1991/1110    
		error(Eprocdied); 
 
	lock(s); 
	i = s->image; 
	if(i == 0) { 
		unlock(s); 
		error(Eprocdied); 
	} 
	unlock(s); 
 
	lock(i); 
	if(waserror()) { 
		unlock(i); 
		nexterror(); 
	} 
 
	tc = i->c; 
	if(tc == 0) 
		error(Eprocdied); 
 
	if(incref(tc) == 1 || (tc->flag&COPEN) == 0 || tc->mode!=OREAD) { 
		close(tc); 
		error(Eprocdied); 
	} 
 
	if(p->pid != PID(c->qid)) 
		error(Eprocdied); 
 
	unlock(i); 
	poperror(); 
 
	return tc; 
1991/1109    
} 
 
void 
1991/1110    
procstopwait(Proc *p, int ctl) 
{ 
	int pid; 
 
	if(p->pdbg) 
1992/0114    
		error(Einuse); 
1991/1110    
	if(procstopped(p)) 
		return; 
 
	if(ctl != 0) 
		p->procctl = ctl; 
1993/0501    
	p->pdbg = up; 
1991/1110    
	pid = p->pid; 
1991/1216    
	qunlock(&p->debug); 
1993/0501    
	up->psstate = "Stopwait"; 
1991/1110    
	if(waserror()) { 
		p->pdbg = 0; 
1991/1216    
		qlock(&p->debug); 
1991/1110    
		nexterror(); 
	} 
1993/0501    
	sleep(&up->sleep, procstopped, p); 
1991/1110    
	poperror(); 
1991/1216    
	qlock(&p->debug); 
1991/1110    
	if(p->pid != pid) 
		error(Eprocdied); 
} 
 
void 
1991/1109    
procctlreq(Proc *p, char *va, int n) 
{ 
1991/1112    
	char buf[NAMELEN]; 
1991/1109    
 
1991/1112    
	if(n > NAMELEN) 
		n = NAMELEN; 
	strncpy(buf, va, n); 
 
1991/1117    
	if(strncmp(buf, "stop", 4) == 0) 
1991/1112    
		procstopwait(p, Proc_stopme); 
1993/0501    
	else 
	if(strncmp(buf, "kill", 4) == 0) { 
1992/1206    
		switch(p->state) { 
		case Broken: 
			unbreak(p); 
			break; 
		case Stopped: 
			postnote(p, 0, "sys: killed", NExit); 
			p->procctl = Proc_exitme; 
1991/1112    
			ready(p); 
1992/1206    
			break; 
		default: 
1991/1117    
			postnote(p, 0, "sys: killed", NExit); 
			p->procctl = Proc_exitme; 
		} 
1991/1112    
	} 
1993/0501    
	else 
	if(strncmp(buf, "hang", 4) == 0) 
1991/1112    
		p->hang = 1; 
1993/0501    
	else 
	if(strncmp(buf, "nohang", 6) == 0) 
1993/0318    
		p->hang = 0; 
1993/0501    
	else 
	if(strncmp(buf, "waitstop", 8) == 0) 
1991/1112    
		procstopwait(p, 0); 
1993/0501    
	else 
	if(strncmp(buf, "startstop", 9) == 0) { 
1991/1110    
		if(p->state != Stopped) 
1992/0114    
			error(Ebadctl); 
1991/1110    
		p->procctl = Proc_traceme; 
		ready(p); 
		procstopwait(p, Proc_traceme); 
	} 
1993/0501    
	else 
	if(strncmp(buf, "start", 5) == 0) { 
1991/1109    
		if(p->state != Stopped) 
1992/0114    
			error(Ebadctl); 
1991/1109    
		ready(p); 
	} 
1991/1112    
	else 
		error(Ebadctl); 
1991/1109    
} 
 
int 
1991/1110    
procstopped(void *a) 
{ 
	Proc *p = a; 
	return p->state == Stopped; 
} 
 
int 
1991/1109    
procctlmemio(Proc *p, ulong offset, int n, void *va, int read) 
{ 
1992/0824    
	KMap *k; 
1991/1113    
	Pte *pte; 
1991/1109    
	Page *pg; 
1991/1110    
	Segment *s; 
1992/0423    
	ulong soff, l; 
1991/1109    
	char *a = va, *b; 
 
1991/1113    
	for(;;) { 
		s = seg(p, offset, 1); 
		if(s == 0) 
1992/0114    
			error(Ebadarg); 
1991/1109    
 
1991/1113    
		if(offset+n >= s->top) 
			n = s->top-offset; 
1991/1109    
 
1993/0501    
		if((s->type&SG_TYPE) == SG_TEXT) 
1991/1113    
			s = txt2data(p, s); 
1991/1109    
 
1991/1113    
		s->steal++; 
		soff = offset-s->base; 
1991/1109    
		if(waserror()) { 
			s->steal--; 
			nexterror(); 
		} 
1991/1113    
		if(fixfault(s, offset, read, 0) == 0) 
			break; 
1991/1109    
		poperror(); 
1991/1113    
		s->steal--; 
1991/1109    
	} 
1991/1113    
	poperror(); 
	pte = s->map[soff/PTEMAPMEM]; 
	if(pte == 0) 
		panic("procctlmemio");  
	pg = pte->pages[(soff&(PTEMAPMEM-1))/BY2PG]; 
	if(pagedout(pg)) 
		panic("procctlmemio1");  
1992/0423    
 
	l = BY2PG - (offset&(BY2PG-1)); 
	if(n > l) 
		n = l; 
 
1991/1109    
	k = kmap(pg); 
	b = (char*)VA(k); 
1991/1110    
	if(read == 1) 
		memmove(a, b+(offset&(BY2PG-1)), n); 
	else 
		memmove(b+(offset&(BY2PG-1)), a, n); 
 
1991/1109    
	kunmap(k); 
 
	s->steal--; 
	qunlock(&s->lk); 
1991/1110    
 
	if(read == 0) 
		p->newtlb = 1; 
 
1990/0227    
	return n; 
1991/1110    
} 
 
1992/1104    
Segment* 
1991/1110    
txt2data(Proc *p, Segment *s) 
{ 
	int i; 
1992/0824    
	Segment *ps; 
1991/1110    
 
	ps = newseg(SG_DATA, s->base, s->size); 
	ps->image = s->image; 
	incref(ps->image); 
	ps->fstart = s->fstart; 
	ps->flen = s->flen; 
	ps->flushme = 1; 
 
	for(i = 0; i < NSEG; i++) 
		if(p->seg[i] == s) 
			break; 
	if(p->seg[i] != s) 
		panic("segment gone"); 
 
	qunlock(&s->lk); 
	putseg(s); 
	qlock(&ps->lk); 
	p->seg[i] = ps; 
1992/1104    
 
	return ps; 
} 
 
Segment* 
data2txt(Segment *s) 
{ 
	Segment *ps; 
 
	ps = newseg(SG_TEXT, s->base, s->size); 
	ps->image = s->image; 
	incref(ps->image); 
	ps->fstart = s->fstart; 
	ps->flen = s->flen; 
	ps->flushme = 1; 
1991/1110    
 
	return ps; 
1990/0227    
} 


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