⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sysproc.c

📁 在x86平台上运行不可信任代码的sandbox。
💻 C
📖 第 1 页 / 共 2 页
字号:
{	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;}intreturn0(void *v){	return 0;}longsyssleep(ulong *arg){	int n;	n = arg[0];	if(n <= 0) {		yield();		return 0;	}	if(n < TK2MS(1))		n = TK2MS(1);	tsleep(&up->sleep, return0, 0, n);	return 0;}longsysalarm(ulong *arg){	return procalarm(arg[0]);}longsysexits(ulong *arg){	char *status;	char *inval = "invalid exit string";	char buf[ERRMAX];	if(arg[0]){		if(waserror())			status = inval;		else{			status = uvalidaddr(arg[0], 1, 0);			if(vmemchr(status, 0, ERRMAX) == 0){				memmove(buf, status, ERRMAX);				buf[ERRMAX-1] = 0;				status = buf;			}			poperror();		}	}else		status = nil;	pexit(status, 1);	return 0;		/* not reached */}longsys_wait(ulong *arg){	int pid;	Waitmsg w;	OWaitmsg *ow;	if(arg[0] == 0)		return pwait(nil);	ow = uvalidaddr(arg[0], sizeof(OWaitmsg), 1);	evenaddr(arg[0]);	pid = pwait(&w);	if(pid >= 0){		readnum(0, ow->pid, NUMSIZE, w.pid, NUMSIZE);		readnum(0, ow->time+TUser*NUMSIZE, NUMSIZE, w.time[TUser], NUMSIZE);		readnum(0, ow->time+TSys*NUMSIZE, NUMSIZE, w.time[TSys], NUMSIZE);		readnum(0, ow->time+TReal*NUMSIZE, NUMSIZE, w.time[TReal], NUMSIZE);		strncpy(ow->msg, w.msg, sizeof(ow->msg));		ow->msg[sizeof(ow->msg)-1] = '\0';	}	return pid;}longsysawait(ulong *arg){	int i;	int pid;	Waitmsg w;	ulong n;	char *buf;	n = arg[1];	buf = uvalidaddr(arg[0], n, 1);	pid = pwait(&w);	if(pid < 0)		return -1;	i = snprint(buf, n, "%d %lud %lud %lud %q",		w.pid,		w.time[TUser], w.time[TSys], w.time[TReal],		w.msg);	return i;}voidwerrstr(char *fmt, ...){	va_list va;	if(up == nil)		return;	va_start(va, fmt);	vseprint(up->syserrstr, up->syserrstr+ERRMAX, fmt, va);	va_end(va);}static longgenerrstr(ulong addr, uint nbuf){	char tmp[ERRMAX];	char *buf;	if(nbuf == 0)		error(Ebadarg);	buf = uvalidaddr(addr, nbuf, 1);	if(nbuf > sizeof tmp)		nbuf = sizeof tmp;	memmove(tmp, buf, nbuf);	/* make sure it's NUL-terminated */	tmp[nbuf-1] = '\0';	memmove(buf, up->syserrstr, nbuf);	buf[nbuf-1] = '\0';	memmove(up->syserrstr, tmp, nbuf);	return 0;}longsyserrstr(ulong *arg){	return generrstr(arg[0], arg[1]);}/* compatibility for old binaries */longsys_errstr(ulong *arg){	return generrstr(arg[0], 64);}longsysnotify(ulong *arg){	if(arg[0] != 0)		uvalidaddr(arg[0], 1, 0);	up->notify = arg[0];	/* checked again when used */	return 0;}longsysnoted(ulong *arg){	if(arg[0]!=NRSTR && !up->notified)		error(Egreg);	return 0;}longsyssegbrk(ulong *arg){	int i;	ulong addr;	Segment *s;	addr = arg[0];	for(i = 0; i < NSEG; i++) {		s = up->seg[i];		if(s == 0 || addr < s->base || addr >= s->top)			continue;		switch(s->type&SG_TYPE) {		case SG_TEXT:		case SG_DATA:		case SG_STACK:			error(Ebadarg);		default:			return ibrk(arg[1], i);		}	}	error(Ebadarg);	return 0;		/* not reached */}longsyssegattach(ulong *arg){	return segattach(up, arg[0], uvalidaddr(arg[1], 1, 0), arg[2], arg[3]);}longsyssegdetach(ulong *arg){	int i;	ulong addr;	Segment *s;	qlock(&up->seglock);	if(waserror()){		qunlock(&up->seglock);		nexterror();	}	s = 0;	addr = arg[0];	for(i = 0; i < NSEG; i++)		if((s = up->seg[i])) {			qlock(&s->lk);			if((addr >= s->base && addr < s->top) ||			   (s->top == s->base && addr == s->base))				goto found;			qunlock(&s->lk);		}	error(Ebadarg);found:	/*	 * Check we are not detaching the initial stack segment.	 */	if(s == up->seg[SSEG]){		qunlock(&s->lk);		error(Ebadarg);	}	up->seg[i] = 0;	qunlock(&s->lk);	putseg(s);	qunlock(&up->seglock);	poperror();	/* Ensure we flush any entries from the lost segment */	flushmmu();	return 0;}longsyssegfree(ulong *arg){	Segment *s;	ulong from, to;	from = arg[0];	s = seg(up, from, 1);	if(s == nil)		error(Ebadarg);	to = (from + arg[1]) & ~(BY2PG-1);	from = PGROUND(from);	if(to > s->top) {		qunlock(&s->lk);		error(Ebadarg);	}	mfreeseg(s, from, (to - from) / BY2PG);	qunlock(&s->lk);	flushmmu();	return 0;}/* For binary compatibility */longsysbrk_(ulong *arg){	return ibrk(arg[0], BSEG);}longsysrendezvous(ulong *arg){	uintptr tag, val;	Proc *p, **l;	tag = arg[0];	l = &REND(up->rgrp, tag);	up->rendval = ~(uintptr)0;	lock(&up->rgrp->ref.lk);	for(p = *l; p; p = p->rendhash) {		if(p->rendtag == tag) {			*l = p->rendhash;			val = p->rendval;			p->rendval = arg[1];			while(p->mach != 0)				;			ready(p);			unlock(&up->rgrp->ref.lk);			return val;		}		l = &p->rendhash;	}	/* Going to sleep here */	up->rendtag = tag;	up->rendval = arg[1];	up->rendhash = *l;	*l = up;	up->state = Rendezvous;	unlock(&up->rgrp->ref.lk);	sched();	return up->rendval;}/* * The implementation of semaphores is complicated by needing * to avoid rescheduling in syssemrelease, so that it is safe * to call from real-time processes.  This means syssemrelease * cannot acquire any qlocks, only spin locks. *  * Semacquire and semrelease must both manipulate the semaphore * wait list.  Lock-free linked lists only exist in theory, not * in practice, so the wait list is protected by a spin lock. *  * The semaphore value *addr is stored in user memory, so it * cannot be read or written while holding spin locks. *  * Thus, we can access the list only when holding the lock, and * we can access the semaphore only when not holding the lock. * This makes things interesting.  Note that sleep's condition function * is called while holding two locks - r and up->rlock - so it cannot * access the semaphore value either. *  * An acquirer announces its intention to try for the semaphore * by putting a Sema structure onto the wait list and then * setting Sema.waiting.  After one last check of semaphore, * the acquirer sleeps until Sema.waiting==0.  A releaser of n * must wake up n acquirers who have Sema.waiting set.  It does * this by clearing Sema.waiting and then calling wakeup. *  * There are three interesting races here.    * The first is that in this particular sleep/wakeup usage, a single * wakeup can rouse a process from two consecutive sleeps!   * The ordering is: *  * 	(a) set Sema.waiting = 1 * 	(a) call sleep * 	(b) set Sema.waiting = 0 * 	(a) check Sema.waiting inside sleep, return w/o sleeping * 	(a) try for semaphore, fail * 	(a) set Sema.waiting = 1 * 	(a) call sleep * 	(b) call wakeup(a) * 	(a) wake up again *  * This is okay - semacquire will just go around the loop * again.  It does mean that at the top of the for(;;) loop in * semacquire, phore.waiting might already be set to 1. *  * The second is that a releaser might wake an acquirer who is * interrupted before he can acquire the lock.  Since * release(n) issues only n wakeup calls -- only n can be used * anyway -- if the interrupted process is not going to use his * wakeup call he must pass it on to another acquirer. *  * The third race is similar to the second but more subtle.  An * acquirer sets waiting=1 and then does a final canacquire() * before going to sleep.  The opposite order would result in * missing wakeups that happen between canacquire and * waiting=1.  (In fact, the whole point of Sema.waiting is to * avoid missing wakeups between canacquire() and sleep().) But * there can be spurious wakeups between a successful * canacquire() and the following semdequeue().  This wakeup is * not useful to the acquirer, since he has already acquired * the semaphore.  Like in the previous case, though, the * acquirer must pass the wakeup call along. *  * This is all rather subtle.  The code below has been verified * with the spin model /sys/src/9/port/semaphore.p.  The * original code anticipated the second race but not the first * or third, which were caught only with spin.  The first race * is mentioned in /sys/doc/sleep.ps, but I'd forgotten about it. * It was lucky that my abstract model of sleep/wakeup still managed * to preserve that behavior. * * I remain slightly concerned about memory coherence * outside of locks.  The spin model does not take  * queued processor writes into account so we have to * think hard.  The only variables accessed outside locks * are the semaphore value itself and the boolean flag * Sema.waiting.  The value is only accessed with cmpswap, * whose job description includes doing the right thing as * far as memory coherence across processors.  That leaves * Sema.waiting.  To handle it, we call coherence() before each * read and after each write.		- rsc *//* Add semaphore p with addr a to list in seg. */static voidsemqueue(Segment *s, long *a, Sema *p){	memset(p, 0, sizeof *p);	p->addr = a;	lock(&s->sema.rendez.lk);	/* uses s->sema.Rendez.Lock, but no one else is */	p->next = &s->sema;	p->prev = s->sema.prev;	p->next->prev = p;	p->prev->next = p;	unlock(&s->sema.rendez.lk);}/* Remove semaphore p from list in seg. */static voidsemdequeue(Segment *s, Sema *p){	lock(&s->sema.rendez.lk);	p->next->prev = p->prev;	p->prev->next = p->next;	unlock(&s->sema.rendez.lk);}/* Wake up n waiters with addr a on list in seg. */static voidsemwakeup(Segment *s, long *a, long n){	Sema *p;		lock(&s->sema.rendez.lk);	for(p=s->sema.next; p!=&s->sema && n>0; p=p->next){		if(p->addr == a && p->waiting){			p->waiting = 0;			coherence();			wakeup(&p->rendez);			n--;		}	}	unlock(&s->sema.rendez.lk);}/* Add delta to semaphore and wake up waiters as appropriate. */static longsemrelease(Segment *s, long *addr, long delta){	long value;	do		value = *addr;	while(!cmpswap(addr, value, value+delta));	semwakeup(s, addr, delta);	return value+delta;}/* Try to acquire semaphore using compare-and-swap */static intcanacquire(long *addr){	long value;		while((value=*addr) > 0)		if(cmpswap(addr, value, value-1))			return 1;	return 0;}		/* Should we wake up? */static intsemawoke(void *p){	coherence();	return !((Sema*)p)->waiting;}/* Acquire semaphore (subtract 1). */static intsemacquire(Segment *s, long *addr, int block){	int acquired;	Sema phore;	if(canacquire(addr))		return 1;	if(!block)		return 0;	acquired = 0;	semqueue(s, addr, &phore);	for(;;){		phore.waiting = 1;		coherence();		if(canacquire(addr)){			acquired = 1;			break;		}		if(waserror())			break;		sleep(&phore.rendez, semawoke, &phore);		poperror();	}	semdequeue(s, &phore);	coherence();	/* not strictly necessary due to lock in semdequeue */	if(!phore.waiting)		semwakeup(s, addr, 1);	if(!acquired)		nexterror();	return 1;}longsyssemacquire(ulong *arg){	int block;	long *addr;	Segment *s;	addr = uvalidaddr(arg[0], sizeof(long), 1);	evenaddr(arg[0]);	block = arg[1];		if((s = seg(up, arg[0], 0)) == nil)	/* this can't happen if validaddr succeeded, can it? */		error(Ebadarg);	if(*addr < 0)		error(Ebadarg);	return semacquire(s, addr, block);}longsyssemrelease(ulong *arg){	long *addr, delta;	Segment *s;	addr = uvalidaddr(arg[0], sizeof(long), 1);	evenaddr(arg[0]);	delta = arg[1];	if((s = seg(up, arg[0], 0)) == nil)	/* again, this can't happen! */		error(Ebadarg);	if(delta < 0 || *addr < 0)		error(Ebadarg);	return semrelease(s, addr, arg[1]);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -