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; }
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); }
void sayhi(void *v) { USED(v); print("hello from subproc\n"); print("rendez got %lu from main\n", rendezvous(0x1234, 1234)); exits(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); }
int main(int argc, char *argv[]) { int C; scanf("%d", &C); while (C--) rendezvous(); return 0; }
static void postproc(void *v) { Srv *s; s = v; if(!s->leavefdsopen){ rfork(RFNOTEG); rendezvous(0, 0); close(s->srvfd); } srv(s); }
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); }
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); }
/* * 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; }
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]; }
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); } }
inline std::tuple< hipStream_t, hipError_t > waitfor_all( hipStream_t st) { detail::single_stream_rendezvous rendezvous( st); return rendezvous.wait(); }
static void threadWakeup(Thread *t) { if(rendezvous(t, (void*)0x44391f14) != (void*)0x22bbdfd6) sysfatal("threadWakeup: rendezvous failed: %r"); }