Beispiel #1
0
static Thread*
runthread(Proc *p)
{
	Thread *t;
	Tqueue *q;

	if(p->nthreads==0)
		return nil;
	q = &p->ready;
	lock(&p->readylock);
	if(q->head == nil){
		q->asleep = 1;
		_threaddebug(DBGSCHED, "sleeping for more work");
		unlock(&p->readylock);
		while(rendezvous(q, 0) == (void*)~0){
			if(_threadexitsallstatus)
				exits(_threadexitsallstatus);
		}
		/* lock picked up from _threadready */
	}
	t = q->head;
	q->head = t->next;
	unlock(&p->readylock);
	return t;
}
Beispiel #2
0
void
_threadready(Thread *t)
{
	Tqueue *q;

	assert(t->state == Ready);
	_threaddebug(DBGSCHED, "readying %d.%d", t->proc->pid, t->id);
	q = &t->proc->ready;
	lock(&t->proc->readylock);
	t->next = nil;
	if(q->head==nil)
		q->head = t;
	else
		*q->tail = t;
	q->tail = &t->next;
	if(q->asleep){
		q->asleep = 0;
		/* lock passes to runthread */
		_threaddebug(DBGSCHED, "waking process %d", t->proc->pid);
		while(rendezvous(q, 0) == (void*)~0){
			if(_threadexitsallstatus)
				exits(_threadexitsallstatus);
		}
	}else
		unlock(&t->proc->readylock);
}
Beispiel #3
0
void
sayhi(void *v)
{
	USED(v);

	print("hello from subproc\n");
	print("rendez got %lu from main\n", rendezvous(0x1234, 1234));
	exits(0);
}
Beispiel #4
0
int
main(int argc, char **argv)
{
	print("hello from main\n");
	ffork(RFMEM|RFPROC, sayhi, nil);

	print("rendez got %lu from subproc\n", rendezvous(0x1234, 0));
	exits(0);
}
Beispiel #5
0
int main(int argc, char *argv[])
{
	int C;

	scanf("%d", &C);
	while (C--)
		rendezvous();

	return 0;
}
Beispiel #6
0
static void
postproc(void *v)
{
	Srv *s;

	s = v;
	if(!s->leavefdsopen){
		rfork(RFNOTEG);
		rendezvous(0, 0);
		close(s->srvfd);
	}
	srv(s);
}
Beispiel #7
0
static void
sysrendezvous(void)
{
	u32int tag, value;
	
	tag = arg(0);
	value = arg(1);
	if(systrace)
		fprint(2, "rendezvous(%#ux, %#ux)\n", tag, value);
	P->R[0] = (u32int) (uintptr)rendezvous((void *) tag, (void *) value);
	if(P->R[0] == ~0)
		noteerr(0, 1);
}
Beispiel #8
0
void
_postmountsrv(Srv *s, char *name, char *mtpt, int flag)
{
	int fd[2];

	if(!s->nopipe){
		if(pipe(fd) < 0)
			sysfatal("pipe: %r");
		s->infd = s->outfd = fd[1];
		s->srvfd = fd[0];
	}
	if(name)
		if(postfd(name, s->srvfd) < 0)
			sysfatal("postfd %s: %r", name);

	if(_forker == nil)
		sysfatal("no forker");
	_forker(postproc, s, RFNAMEG);

	/*
	 * Normally the server is posting as the last thing it does
	 * before exiting, so the correct thing to do is drop into
	 * a different fd space and close the 9P server half of the
	 * pipe before trying to mount the kernel half.  This way,
	 * if the file server dies, we don't have a ref to the 9P server
	 * half of the pipe.  Then killing the other procs will drop
	 * all the refs on the 9P server half, and the mount will fail.
	 * Otherwise the mount hangs forever.
	 *
	 * Libthread in general and acme win in particular make
	 * it hard to make this fd bookkeeping work out properly,
	 * so leaveinfdopen is a flag that win sets to opt out of this
	 * safety net.
	 */
	if(!s->leavefdsopen){
		rfork(RFFDG);
		rendezvous(0, 0);
		close(s->infd);
		if(s->infd != s->outfd)
			close(s->outfd);
	}

	if(mtpt){
		if(amount(s->srvfd, mtpt, flag, "") == -1)
			sysfatal("mount %s: %r", mtpt);
	}else
		close(s->srvfd);
}
Beispiel #9
0
/*
 * replace the fd with a pipe and start a process to
 * accept calls in.  this is all to make select work.
 */
static int
listenproc(Rock *r, int fd)
{
	Rock *nr;
	char *net;
	int cfd, nfd, dfd;
	int pfd[2];
	struct stat d;
	char *p;
	char listen[Ctlsize];
	char name[Ctlsize];

	switch(r->stype){
	case SOCK_DGRAM:
		net = "udp";
		break;
	case SOCK_STREAM:
		net = "tcp";
		break;
	default:
		net = "gok";
		break;
	}

	strcpy(listen, r->ctl);
	p = strrchr(listen, '/');
	if(p == 0)
		return -1;
	strcpy(p+1, "listen");

	if(pipe(pfd) < 0)
		return -1;

	/* replace fd with a pipe */
	nfd = dup(fd);
	dup2(pfd[0], fd);
	close(pfd[0]);
	fstat(fd, &d);
	r->inode = d.st_ino;
	r->dev = d.st_dev;

	/* start listening process */
	switch(fork()){
	case -1:
		close(pfd[1]);
		close(nfd);
		return -1;
	case 0:
		if(_muxsid == -1) {
			rfork(RFNOTEG);
			_muxsid = getpgrp();
		} else
			setpgid(getpid(), _muxsid);
		rendezvous(2, _muxsid);
		break;
	default:
		atexit(_killmuxsid);
		_muxsid = rendezvous(2, 0);
		close(pfd[1]);
		close(nfd);
		return 0;
	}

/*	for(fd = 0; fd < 30; fd++)
		if(fd != nfd && fd != pfd[1])
			close(fd); */

	for(;;){
		cfd = open(listen, O_RDWR);
		if(cfd < 0)
			break;

		dfd = _sock_data(cfd, net, r->domain, r->stype, r->protocol, &nr);
		if(dfd < 0)
			break;

		if(write(pfd[1], nr->ctl, strlen(nr->ctl)) < 0)
			break;
		if(read(pfd[1], name, sizeof(name)) <= 0)
			break;

		close(dfd);
	}
	exit(0);
	return 0;
}
Beispiel #10
0
void
startcmd(Conn *c, char *cmd, int *kidpid, int *kidin)
{
	int i, pid, kpid;
	int pfd[3][2];
	char *dir;
	char *sysname, *tz;
	Msg *m;
	Waitmsg *w;

	for(i=0; i<3; i++)
		if(pipe(pfd[i]) < 0)
			sysfatal("pipe: %r");

	sysname = getenv("sysname");
	tz = getenv("timezone");

	switch(pid = rfork(RFPROC|RFMEM|RFNOWAIT)){
	case -1:
		sysfatal("fork: %r");
	case 0:
		switch(kpid = rfork(RFPROC|RFNOTEG|RFENVG|RFFDG)){
		case -1:
			sysfatal("fork: %r");
		case 0:
			for(i=0; i<3; i++){
				if(dup(pfd[i][1], i) < 0)
					sysfatal("dup: %r");
				close(pfd[i][0]);
				close(pfd[i][1]);
			}
			putenv("user", c->user);
			if(sysname)
				putenv("sysname", sysname);
			if(tz)
				putenv("tz", tz);
	
			dir = smprint("/usr/%s", c->user);
			if(dir == nil || chdir(dir) < 0)
				chdir("/");
			if(cmd){
				putenv("service", "rx");
				execl("/bin/rc", "rc", "-lc", cmd, nil);
				sysfatal("cannot exec /bin/rc: %r");
			}else{
				putenv("service", "con");
				execl("/bin/ip/telnetd", "telnetd", "-tn", nil);
				sysfatal("cannot exec /bin/ip/telnetd: %r");
			}
		default:
			*kidpid = kpid;
			rendezvous(kidpid, 0);
			for(;;){
				if((w = wait()) == nil)
					sysfatal("wait: %r");
				if(w->pid == kpid)
					break;
				free(w);
			}
			if(w->msg[0]){
				m = allocmsg(c, SSH_MSG_DISCONNECT, 4+strlen(w->msg));
				putstring(m, w->msg);
				sendmsg(m);
			}else{
				m = allocmsg(c, SSH_SMSG_EXITSTATUS, 4);
				putlong(m, 0);
				sendmsg(m);
			}
			for(i=0; i<3; i++)
				close(pfd[i][0]);
			free(w);
			exits(nil);	
			break;
		}
	default:
		atexitkill(pid);
		rendezvous(kidpid, 0);
		break;
	}

	for(i=0; i<3; i++)
		close(pfd[i][1]);

	copyout(c, pfd[1][0], SSH_SMSG_STDOUT_DATA);
	copyout(c, pfd[2][0], SSH_SMSG_STDERR_DATA);
	*kidin = pfd[0][0];
}
Beispiel #11
0
void
main(int argc, char *argv[])
{
	int fd, cfd, pid, ofd, i;
	char file[128], *f;
	char *dev, *devctl, *out;
	long tot, nr;
	int sz;

	sz = 8;
	dev = "/dev/ptrace";
	out = nil;
	ARGBEGIN{
	case 'f':
		dev = EARGF(usage());
		break;
	case 'o':
		out = EARGF(usage());
		break;
	case 's':
		sz = strtoul(EARGF(usage()), 0, 0);
		break;
	case 'p':
		if(npids > nelem(pids))
			sysfatal("too many pids");
		pids[npids++] = strtoul(EARGF(usage()), 0, 0);
		break;
	default:
		usage();
	}ARGEND
	if(argc == 0)
		usage();

	sz *= 1024;
	if(sz < 1024)
		sz = 1024;
	if(sz > 64*1024)	/* perhaps we shouldn't limit it */
		sz = 64*1024;

	devctl = smprint("%sctl", dev);
	if(devctl == nil)
		sysfatal("no memory");

	if(access(argv[0], AEXIST) < 0){
		seprint(file, file+sizeof file, "/bin/%s", argv[0]);
		f = file;
	}else
		f = argv[0];
	if(access(f, AEXIST) < 0)
		sysfatal("%s: %r", argv[0]);


	/* prepage; don't want interference while tracing */
	for(i = 0; i < sizeof buf; i += 4096)
		buf[i] = 0;

	rfork(RFREND);
	pid = 0;

	/* play a dance with the traced command so it starts when we want,
	 * or issue the trace command for the traced pids.
	 */
	cfd = open(devctl, OWRITE);
	if(cfd < 0)
		sysfatal("can't trace: %r");
	if(npids == 0){
		pid = rfork(RFPROC|RFFDG);
		switch(pid){
		case -1:
			sysfatal("fork: %r");
		case 0:
			/* wait until traced */
			if(rendezvous(usage, 0) == 0)
				exits("no trace");
			rfork(RFREND);
			exec(f, argv);
			sysfatal("exec: %r");
		}
		if(fprint(cfd, "size %d\n", sz) < 0 || fprint(cfd, "trace %d 1\n", pid) < 0){
			rendezvous(usage, 0);
			sysfatal("can't trace");
		}
	
		if(out == nil){
			rendezvous(usage, usage);
			waitpid();
			exits(nil);
		}
	}else{
		for(i = 0; i < npids; i++)
			if(fprint(cfd, "trace %d 1\n", pids[i]) < 0)
				fprint(2, "%s: trace %d: %r\n", argv0, pids[i]);
	}
	close(cfd);

	/* ready: open the trace and collect what we can. */
	fd = open(dev, OREAD);
	ofd = create(out, OWRITE, 0664);
	if(fd < 0 || ofd < 0){
		if(npids == 0)
			rendezvous(usage, 0);
		sysfatal("can't trace: %r");
	}

	done = 0;
	switch(rfork(RFPROC|RFMEM)){
	case -1:
		sysfatal("fork");
	default:
		if(npids == 0){
			/* let the traced go! */
			rendezvous(usage, usage);
		}

		while(waitpid() != pid)
			;
		done = 1;
		exits(nil);
	case 0:
		/* The damn device won't block us. We must insist upon eof.
		 * Besides, when done, we must give time for the events to
		 * arrive.
		 */
		for(;;){
			for(tot = 0; tot < sizeof buf - 128; tot += nr){
				nr = read(fd, buf+tot, sizeof buf - tot);
				if(nr < 0)
					sysfatal("read: %r");
				if(nr == 0){
					sleep(100);
					if(done)
						break;
				}
			}
			if(tot > 0 && write(ofd, buf, tot) != tot)
				sysfatal("write: %r");
			/* try to read more if we were done; but just once. */
			if(done && tot == 0 && done++ == 2)
				break;
		}
		close(fd);
		close(ofd);
		rendezvous(main, nil);
		exits(nil);
	}
}
Beispiel #12
0
inline
std::tuple< hipStream_t, hipError_t > waitfor_all( hipStream_t st) {
    detail::single_stream_rendezvous rendezvous( st);
    return rendezvous.wait();
}
Beispiel #13
0
static void
threadWakeup(Thread *t)
{
	if(rendezvous(t, (void*)0x44391f14) != (void*)0x22bbdfd6)
		sysfatal("threadWakeup: rendezvous failed: %r");
}