void notmain ( void ) { PUT32(TRISECLR,0x1); PUT32(PORTESET,0x1); //insure PBDIV is 1:1 PUT32(SYSKEY,0xAA996655); PUT32(SYSKEY,0x556699AA); PUT32(OSCCONCLR,0x180000); PUT32(SYSKEY,0x33333333); //use timer1 and set to divide by 1 PUT32(T1CON,0x0000); PUT32(TMR1,0x0000); PUT32(PR1,0xFFFF); PUT32(T1CON,0x8000); while(1) { PUT32(PORTECLR,0x1); dowait(); PUT32(PORTESET,0x1); dowait(); } }
/* * wait * allows the user to "foreground" a process by waiting on it. without ps to * know the pids, this is a little tough to use with an arg, but without an * arg it will wait for all the background jobs. */ static int cmd_wait(int ac, char *av[]) { int i; pid_t pid; if (ac == 2) { pid = atoi(av[1]); dowait(pid); for (i = 0; i < MAXBG; i++) { if (bgpids[i]==pid) { bgpids[i] = 0; } } return 0; } else if (ac == 1) { for (i=0; i < MAXBG; i++) { if (bgpids[i] != 0) { dowait(bgpids[i]); bgpids[i] = 0; } } return 0; } printf("Usage: wait [pid]\n"); return 1; }
//------------------------------------------------------------------------ void notmain ( void ) { //unsigned int ra; switch_to_80Mhz(); uart_init(); hexstring(0x87654321); hexstring(0x12345678); //Cortex-M4 systick timer init PUT32(STCTRL,0x00000004); PUT32(STRELOAD,1000000-1); PUT32(STCURRENT,0); //value is a dont care PUT32(STCTRL,0x00000005); while(1) { uart_send(0x55); dowait(); uart_send(0x56); dowait(); } }
int main() { int pid0, pid1, pid2; pid0 = dofork(); putchar('0'); check(); putchar('a'); pid1 = dofork(); putchar('1'); check(); putchar('b'); pid2 = dofork(); putchar('2'); check(); //putchar('c'); dowait(pid2); dowait(pid1); dowait(pid0); putchar('\n'); return 0; }
int waitcmd(int argc, char **argv) { struct job *job; int status, retval; struct job *jp; nextopt(""); if (!*argptr) { /* wait for all jobs */ jp = jobtab; if (jobs_invalid) return 0; for (;;) { if (jp >= jobtab + njobs) { /* no running procs */ return 0; } if (!jp->used || jp->state != JOBRUNNING) { jp++; continue; } if (dowait(WBLOCK, NULL) == -1) return 128 + SIGINT; jp = jobtab; } } retval = 127; /* XXXGCC: -Wuninitialized */ for (; *argptr; argptr++) { job = getjob(*argptr, 1); if (!job) { retval = 127; continue; } /* loop until process terminated or stopped */ while (job->state == JOBRUNNING) { if (dowait(WBLOCK|WNOFREE, job) == -1) return 128 + SIGINT; } status = job->ps[job->nprocs ? job->nprocs - 1 : 0].status; if (WIFEXITED(status)) retval = WEXITSTATUS(status); #if JOBS else if (WIFSTOPPED(status)) retval = WSTOPSIG(status) + 128; #endif else { /* XXX: limits number of signals */ retval = WTERMSIG(status) + 128; } if (!iflag) freejob(job); } return retval; }
void notmain ( void ) { PUT32(0x50008000,GET32(0x50008000)|0x80); while(1) { PUT32(0x50000200,0x00000000); dowait(); PUT32(0x50000200,0xFFFFFFFF); dowait(); } }
/* * Allocate and then fork, in case fork doesn't preserve the heap. */ static void test13(void) { pid_t pid; void *p; printf("Allocating a page...\n"); p = dosbrk(PAGE_SIZE); markpage(p, 0); if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt before forking"); } printf("Forking...\n"); pid = dofork(); if (pid == 0) { /* child */ if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt in child"); } exit(0); } if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt in parent"); } dowait(pid); printf("Passed sbrk test 13.\n"); }
static void doforkall(const char *phasename, void (*func)(void)) { int i, bad = 0; pid_t pids[numprocs]; for (i=0; i<numprocs; i++) { pids[i] = dofork(); if (pids[i] < 0) { bad = 1; } else if (pids[i] == 0) { /* child */ me = i; func(); exit(0); } } for (i=0; i<numprocs; i++) { if (pids[i] > 0 && dowait(i, pids[i])) { bad = 1; } } if (bad) { complainx("%s failed.", phasename); exit(1); } }
/* * Allocate, then fork, then free the allocated page in the child. */ static void test14(void) { pid_t pid; void *p; tprintf("Allocating a page...\n"); p = dosbrk(PAGE_SIZE); markpage(p, 0); if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt before forking"); } tprintf("Forking...\n"); pid = dofork(); if (pid == 0) { /* child */ if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt in child"); } tprintf("Child freeing a page...\n"); dosbrk(-PAGE_SIZE); exit(0); } dowait(pid); if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt in parent after child ran"); } tprintf("Passed sbrk test 14.\n"); success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest"); }
void quint(const char *prog) { pid_t pids[5]; int i, failures = 0; char *args[2]; /* set up the argv */ args[0]=(char *)prog; args[1]=NULL; warnx("Starting: running five copies of %s...", prog); for (i=0; i<5; i++) { pids[i]=spawnv(args[0], args); } for (i=0; i<5; i++) { failures += dowait(i, pids[i]); } if (failures > 0) { warnx("%d failures", failures); } else { warnx("Congratulations! You passed."); } }
/* * Fork and then allocate in both the parent and the child, in case * fork messes up the heap. Note: this is not intended to test the * parent and child running concurrently -- that should probably be * its own test program. */ static void test12(void) { pid_t pid; void *p; tprintf("Forking...\n"); pid = dofork(); if (pid == 0) { /* child */ say("Child allocating a page...\n"); p = dosbrk(PAGE_SIZE); markpage(p, 0); if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt in child"); } say("Child done.\n"); exit(0); } /* parent */ say("Parent allocating a page...\n"); p = dosbrk(PAGE_SIZE); markpage(p, 0); if (checkpage(p, 0, false)) { errx(1, "FAILED: data corrupt in parent"); } say("Parent done.\n"); dowait(pid); tprintf("Passed sbrk test 12.\n"); success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest"); }
static void basetest(void) { unsigned i; struct usem gosems[NUMJOBS], waitsems[NUMJOBS]; pid_t pids[NUMJOBS]; for (i=0; i<NUMJOBS; i++) { usem_init(&gosems[i], "g", i); usem_init(&waitsems[i], "w", i); } for (i=0; i<NUMJOBS; i++) { pids[i] = fork(); if (pids[i] < 0) { err(1, "fork"); } if (pids[i] == 0) { child_with_own_fd(&gosems[i], &waitsems[i], i); _exit(0); } } baseparent(gosems, waitsems); for (i=0; i<NUMJOBS; i++) { dowait(pids[i], i); } for (i=0; i<NUMJOBS; i++) { usem_cleanup(&gosems[i]); usem_cleanup(&waitsems[i]); } }
int main() { pid_p = getpid(); //printf("value of pid_p after getpid is %d \n", pid_p); putchar('w'); pid_c = dofork(); //printf("value of pid_c after getpid is %d \n", pid_c); if (getpid() == pid_p) { check(); dowait(pid_c); } else { putchar('e'); _exit(0); } putchar('k'); if (getpid() == pid_p) putchar('p'); else printf("wrong %d\n", getpid()); putchar('\n'); return 0; }
static void concur(void) { int i, fd; int r1, r2, w1; printf("Spawning 2 readers, 1 writer.\n"); fd = open(FNAME, O_WRONLY|O_CREAT|O_TRUNC, 0664); if (fd < 0) { err(1, "[CONCUR]: %s: open", FNAME); } printf("Initializing test file: "); for (i = 0; i < SECTOR_SIZE + 1; i++) { cbuffer[i] = READCHAR; } for (i = 0; i < TMULT; i++) { write(fd, cbuffer, SECTOR_SIZE + 1); } close(fd); printf("Done initializing. Starting processes...\n"); r1 = forkoff(subproc_read); w1 = forkoff(subproc_write); r2 = forkoff(subproc_read); printf("Waiting for processes.\n"); dowait(r1); dowait(r2); dowait(w1); if (remove(FNAME)) { err(1, "[CONCUR]: %s: remove", FNAME); } printf("[CONCUR] Done!\n"); }
void showjobs(struct output *out, int mode) { int jobno; struct job *jp; int silent = 0, gotpid; TRACE(("showjobs(%x) called\n", mode)); /* If not even one one job changed, there is nothing to do */ gotpid = dowait(0, NULL); while (dowait(0, NULL) > 0) continue; #ifdef JOBS /* * Check if we are not in our foreground group, and if not * put us in it. */ if (mflag && gotpid != -1 && tcgetpgrp(ttyfd) != getpid()) { if (tcsetpgrp(ttyfd, getpid()) == -1) error("Cannot set tty process group (%s) at %d", strerror(errno), __LINE__); TRACE(("repaired tty process group\n")); silent = 1; } #endif if (jobs_invalid) return; for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) { if (!jp->used) continue; if (jp->nprocs == 0) { freejob(jp); continue; } if ((mode & SHOW_CHANGED) && !jp->changed) continue; if (silent && jp->changed) { jp->changed = 0; continue; } showjob(out, jp, mode); } }
void notmain ( void ) { unsigned int ra; ra=GET32(RCGCGPIO); ra|=1<<12; //GPION PUT32(RCGCGPIO,ra); while(1) { if(GET32(PRGPIO)&(1<<12)) break; } //LEDs on PN0 and PN1 ra=GET32(GPIONDIR); ra|=(1<<1)|(1<<0); PUT32(GPIONDIR,ra); //should already be 0 ra=GET32(GPIONAFSEL); ra&=~((1<<1)|(1<<0)); PUT32(GPIONAFSEL,ra); ra=GET32(GPIONODR); ra&=~((1<<1)|(1<<0)); PUT32(GPIONODR,ra); ra=GET32(GPIONDEN); ra|=(1<<1)|(1<<0); PUT32(GPIONDEN,ra); for(ra=0;ra<10;ra++) //while(1) { PUT32(GPIONDATA|(((1<<1)|(1<<0))<<2),0xFF); dowait(); PUT32(GPIONDATA|(((1<<1)|(1<<0))<<2),0x00); dowait(); } }
int waitforjob(struct job *jp) { #if JOBS int mypgrp = getpgrp(); #endif int status; int st; INTOFF; TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1)); while (jp->state == JOBRUNNING) { dowait(WBLOCK, jp); } #if JOBS if (jp->jobctl) { if (tcsetpgrp(ttyfd, mypgrp) == -1) error("Cannot set tty process group (%s) at %d", strerror(errno), __LINE__); } if (jp->state == JOBSTOPPED && curjob != jp - jobtab) set_curjob(jp, 2); #endif status = jp->ps[jp->nprocs - 1].status; /* convert to 8 bits */ if (WIFEXITED(status)) st = WEXITSTATUS(status); #if JOBS else if (WIFSTOPPED(status)) st = WSTOPSIG(status) + 128; #endif else st = WTERMSIG(status) + 128; TRACE(("waitforjob: job %d, nproc %d, status %x, st %x\n", jp - jobtab + 1, jp->nprocs, status, st )); #if JOBS if (jp->jobctl) { /* * This is truly gross. * If we're doing job control, then we did a TIOCSPGRP which * caused us (the shell) to no longer be in the controlling * session -- so we wouldn't have seen any ^C/SIGINT. So, we * intuit from the subprocess exit status whether a SIGINT * occurred, and if so interrupt ourselves. Yuck. - mycroft */ if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT) raise(SIGINT); } #endif if (! JOBS || jp->state == JOBDONE) freejob(jp); INTON; return st; }
//// // gender_one // // // void gender_one (char *exec, int id, int *line, int mutex, int depends, int group, int reproducing, int raising) { int one = 0; // hide misleading index number int gathered; // shared variable FILE *fp; // file pointer for gathered shared variable file // print entering waiting state printf ("alien %d of gender 1 beginning to wait in line\n", id); // begin sleeping for random time dowait (1); // semdown (line[one]); // line_1.down() semdown (group); // group.down() semdown (mutex); // mutex.down() // get the shared gathered variable from "aliengathvar" fp = fopen ("aliengathvar", "r"); // print error if could not open file successfully if (fp < 0 || fp == NULL) { fprintf (stderr, "%s: %s: failed to open aliengathvar\n", exec, "ERROR"); exit (-1); } fscanf (fp, "%d", &gathered); // scan shared variable fclose (fp); // close read file // increment gathered gathered += 1; // check if the last of three gender residents necessary to reproduce if (gathered == 3) { gathered = 0; // attained group size so reset semdown (reproducing); // one of two groups to begin reproducing // all three have "reached" barrier semup (depends); semup (depends); semup (depends); } // write the shared variable gathered to "aliengathvar" fp = fopen ("aliengathvar", "w"); if (fp < 0 || fp == NULL) { fprintf (stderr, "%s: %s: failed to open aliengathvar\n", exec, "ERROR"); exit (-1); } fprintf (fp, "%d\n", gathered); // write shared variable fclose (fp); // close write file // semup (mutex); // mutex.up() semdown (depends); // depends.down() semup (group); // group.up() // print entering reproducing state printf ("alien %d of gender 1 beginning to reproduce\n", id); // hit sleeping barrier semdown (raising); // raising.down() printf ("%s %d of gender 1: leaving nursery\n", "alien", id); // leaving nursery }
int waitcmd(int argc, char **argv) { struct job *job; int status, retval; struct job *jp; if (argc > 1) { job = getjob(argv[1]); } else { job = NULL; } /* * Loop until a process is terminated or stopped, or a SIGINT is * received. */ in_waitcmd++; do { if (job != NULL) { if (job->state) { status = job->ps[job->nprocs - 1].status; if (WIFEXITED(status)) retval = WEXITSTATUS(status); #if JOBS else if (WIFSTOPPED(status)) retval = WSTOPSIG(status) + 128; #endif else retval = WTERMSIG(status) + 128; if (! iflag) freejob(job); in_waitcmd--; return retval; } } else { for (jp = jobtab ; ; jp++) { if (jp >= jobtab + njobs) { /* no running procs */ in_waitcmd--; return 0; } if (jp->used && jp->state == 0) break; } } } while (dowait(1, (struct job *)NULL) != -1); in_waitcmd--; return 0; }
void notmain ( void ) { unsigned int ra,rb,rc,rd,re,rf; clock_init(); ra=GET32(GPIO_DIR1); ra|=1<<8; ra|=1<<9; ra|=1<<10; ra|=1<<11; PUT32(GPIO_DIR1,ra); PUT32(STCTRL,0x00000004); //disabled, no ints, use cpu clock PUT32(STRELOAD,12000000-1); PUT32(STCTRL,0x00000005); //enabled, no ints, use cpu clock ra=GPIO_SET1; rb=GPIO_CLR1; rc=1<<8; rd=1<<9; re=1<<10; rf=1<<11; while(1) { PUT32(ra,rc); PUT32(rb,rd); PUT32(rb,re); PUT32(rb,rf); dowait(); PUT32(rb,rc); PUT32(ra,rd); PUT32(rb,re); PUT32(rb,rf); dowait(); PUT32(rb,rc); PUT32(rb,rd); PUT32(ra,re); PUT32(rb,rf); dowait(); PUT32(rb,rc); PUT32(rb,rd); PUT32(rb,re); PUT32(ra,rf); dowait(); PUT32(rb,rc); PUT32(rb,rd); PUT32(ra,re); PUT32(rb,rf); dowait(); PUT32(rb,rc); PUT32(ra,rd); PUT32(rb,re); PUT32(rb,rf); dowait(); } }
/* * Do a task group: fork the processes, then wait for them. */ static void runtaskgroup(unsigned count, void (*prep)(unsigned, unsigned), void (*task)(unsigned, unsigned), void (*cleanup)(unsigned, unsigned), unsigned groupid) { pid_t mypids[count]; unsigned i; unsigned failures = 0; time_t secs; unsigned long nsecs; prep(groupid, count); for (i=0; i<count; i++) { mypids[i] = fork(); if (mypids[i] < 0) { err(1, "fork"); } if (mypids[i] == 0) { /* child (of second fork) */ task(groupid, i); exit(0); } /* parent (of second fork) - continue */ } /* * now wait for the task to finish */ for (i=0; i<count; i++) { failures += dowait(mypids[i]); } /* * Store the end time. */ __time(&secs, &nsecs); openresultsfile(O_WRONLY); putresult(groupid, secs, nsecs); closeresultsfile(); cleanup(groupid, count); exit(failures ? 1 : 0); }
/* * Wait for the task group directors to exit. */ static void waitall(pid_t *pids, unsigned numpids) { unsigned failures = 0; unsigned i; for (i=0; i<numpids; i++) { failures += dowait(pids[i]); } if (failures) { errx(1, "TEST FAILURE: one or more subprocesses broke"); } }
/* * Actually run the test. */ static void test(int nowait) { int pid0, pid1, pid2, pid3; /* * Caution: This generates processes geometrically. * * It is unrolled to encourage gcc to registerize the pids, * to prevent wait/exit problems if fork corrupts memory. */ pid0 = dofork(); putchar('0'); check(); pid1 = dofork(); putchar('1'); check(); pid2 = dofork(); putchar('2'); check(); pid3 = dofork(); putchar('3'); check(); /* * These must be called in reverse order to avoid waiting * improperly. */ dowait(nowait, pid3); dowait(nowait, pid2); dowait(nowait, pid1); dowait(nowait, pid0); putchar('\n'); }
void RWLTaskProcessor::run() { while (true) { switch (state_) { case START: printf("status: START\n"); dostart(); break; case WAIT: printf("status: WAIT\n"); dowait(); break; case GMCW: printf("status: GMCW\n"); dogmcw(); break; case RWCWXZ: printf("status: RWCWXZ\n"); dorwcwxz(); break; case RWWPXZ: printf("status: RWWPXZ\n"); dorwwpxz(); break; case SHOPPING: printf("status: SHOPPING\n"); doshopping(); break; case STOP: printf("status: STOP\n"); return; } Sleep(5000); } }
static void dotest(void) { unsigned i, me; pid_t pids[BRANCHES]; int t; me = 0; for (i=0; i<BRANCHES; i++) { pids[i] = dofork(); if (pids[i] == 0) { me += 1U<<i; } grind(); t = trace(); if (t == right[i]) { tsay("Stage %u #%u done: %d\n", i, me, trace()); } else { tsay("Stage %u #%u FAILED: got %d, expected %d\n", i, me, t, right[i]); success(TEST161_FAIL, SECRET, "/testbin/bigfork"); failures++; } TEST161_TPROGRESS(0); } for (i=BRANCHES; i-- > 0; ) { dowait(pids[i]); } if (failures > 0) { tprintf("%u failures.\n", failures); success(TEST161_FAIL, SECRET, "/testbin/bigfork"); } else { tprintf("Done.\n"); success(TEST161_SUCCESS, SECRET, "/testbin/bigfork"); } }
static void conctest(void) { unsigned i; struct usem gosems[NUMJOBS], waitsems[NUMJOBS]; pid_t pids[NUMJOBS]; say("Shoot...\n"); for (i=0; i<NUMJOBS; i++) { usem_init(&gosems[i], "g", i); usem_init(&waitsems[i], "w", i); usem_open(&gosems[i]); usem_open(&waitsems[i]); } for (i=0; i<NUMJOBS; i++) { pids[i] = fork(); if (pids[i] < 0) { err(1, "fork"); } if (pids[i] == 0) { child_plain(&gosems[i], &waitsems[i], i); _exit(0); } } concparent(gosems, waitsems); for (i=0; i<NUMJOBS; i++) { dowait(pids[i], i); } for (i=0; i<NUMJOBS; i++) { usem_close(&gosems[i]); usem_close(&waitsems[i]); usem_cleanup(&gosems[i]); usem_cleanup(&waitsems[i]); } }
void showjobs(int change, int sformat, int lformat) { int jobno; struct job *jp; TRACE(("showjobs(%d) called\n", change)); while (dowait(0, (struct job *)NULL) > 0); for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) { if (! jp->used) continue; if (jp->nprocs == 0) { freejob(jp); continue; } if (change && ! jp->changed) continue; showjob(jp, 0, sformat, lformat); jp->changed = 0; if (jp->state == JOBDONE) { freejob(jp); } } }
/* * Performs the exec argument processing, all of the child forking and * execing, and child cleanup. * Sets exitcode to non-zero if any errors occurred. */ void do_mounts(void) { int i, isave, cnt; vfsent_t *vp, *vpprev, **vl; char *newargv[ARGV_MAX]; pid_t child; /* * create the arg list once; the only differences among * the calls are the options, special and mountp fields. */ i = 2; if (cflg) newargv[i++] = "-c"; if (gflg) newargv[i++] = "-g"; if (mflg) newargv[i++] = "-m"; if (Oflg) newargv[i++] = "-O"; if (qflg) newargv[i++] = "-q"; if (rflg) newargv[i++] = "-r"; if (dashflg) newargv[i++] = "--"; if (oflg) { newargv[i++] = "-o"; newargv[i++] = specific_opts; } isave = i; /* * Main loop for the mount processes */ vl = vfsarray; cnt = vfsarraysize; for (vpprev = *vl; vp = *vl; vpprev = vp, vl++, cnt--) { /* * Check to see if we cross a mount level: e.g., * /a/b -> /a/b/c. If so, we need to wait for all current * mounts to finish, rerun realpath on the remaining mount * points, and resort the list. * * Also, we mount serially as long as there are lofs's * to mount to avoid improper mount ordering. */ if (vp->mlevel > vpprev->mlevel || lofscnt > 0) { vfsent_t **vlp; while (nrun > 0 && (dowait() != -1)) ; /* * Gads! It's possible for real path mounts points to * change after mounts are done at a lower mount * level. * Thus, we need to recalculate mount levels and * resort the list from this point. */ for (vlp = vl; *vlp; vlp++) (void) setrpath(*vlp); /* * Sort the remaining entries based on their newly * resolved path names. * Do not sort if we still have lofs's to mount. */ if (lofscnt == 0) { qsort((void *)vl, cnt, sizeof (vfsent_t *), mlevelcmp); vp = *vl; } } if (vp->flag & VRPFAILED) { fprintf(stderr, gettext( "%s: Nonexistent mount point: %s\n"), myname, vp->v.vfs_mountp); vp->flag |= VNOTMOUNTED; exitcode = 1; continue; } /* * If mount options were not specified on the command * line, then use the ones found in the vfstab entry, * if any. */ i = isave; if (!oflg && vp->v.vfs_mntopts) { newargv[i++] = "-o"; newargv[i++] = vp->v.vfs_mntopts; } newargv[i++] = vp->v.vfs_special; newargv[i++] = vp->rpath; newargv[i] = NULL; /* * This should never really fail. */ while (setup_iopipe(vp) == -1 && (dowait() != -1)) ; while (nrun >= maxrun && (dowait() != -1)) /* throttle */ ; if ((child = fork()) == -1) { perror("fork"); cleanup(-1); /* not reached */ } if (child == 0) { /* child */ signal(SIGHUP, SIG_IGN); signal(SIGQUIT, SIG_IGN); signal(SIGINT, SIG_IGN); setup_output(vp); doexec(vp->v.vfs_fstype, newargv); perror("exec"); exit(1); } /* parent */ (void) close(vp->sopipe[WRPIPE]); (void) close(vp->sepipe[WRPIPE]); vp->pid = child; nrun++; } /* * Mostly done by now - wait and clean up the stragglers. */ cleanup(0); }
/* Return 0 if all processes are terminated, -1 on error, -2 on timeout. */ int process_wait(process_info_t* vec, int n, int timeout) { int i; process_info_t* p; dowait_args args; args.vec = vec; args.n = n; args.pipe[0] = -1; args.pipe[1] = -1; /* The simple case is where there is no timeout */ if (timeout == -1) { dowait(&args); return 0; } /* Hard case. Do the wait with a timeout. * * Assumption: we are the only ones making this call right now. Otherwise * we'd need to lock vec. */ pthread_t tid; int retval; int r = pipe((int*)&(args.pipe)); if (r) { perror("pipe()"); return -1; } r = pthread_create(&tid, NULL, dowait, &args); if (r) { perror("pthread_create()"); retval = -1; goto terminate; } struct timeval tv; tv.tv_sec = timeout / 1000; tv.tv_usec = 0; fd_set fds; FD_ZERO(&fds); FD_SET(args.pipe[0], &fds); r = select(args.pipe[0] + 1, &fds, NULL, NULL, &tv); if (r == -1) { perror("select()"); retval = -1; } else if (r) { /* The thread completed successfully. */ retval = 0; } else { /* Timeout. Kill all the children. */ for (i = 0; i < n; i++) { p = (process_info_t*)(vec + i * sizeof(process_info_t)); kill(p->pid, SIGTERM); } retval = -2; /* Wait for thread to finish. */ r = pthread_join(tid, NULL); if (r) { perror("pthread_join"); retval = -1; } } terminate: close(args.pipe[0]); close(args.pipe[1]); return retval; }
/* * Allocate and free in both the parent and the child, and do more * than one page. */ static void test15(void) { unsigned num = 12; pid_t pid; unsigned i; void *p; tprintf("Allocating %u pages...\n", num); p = dosbrk(PAGE_SIZE * num); for (i=0; i<num; i++) { markpage(p, i); } for (i=0; i<num; i++) { if (checkpage(p, i, false)) { errx(1, "FAILED: data corrupt before forking"); } } tprintf("Freeing one page...\n"); (void)dosbrk(-PAGE_SIZE); num--; for (i=0; i<num; i++) { if (checkpage(p, i, false)) { errx(1, "FAILED: data corrupt before forking (2)"); } } tprintf("Allocating two pages...\n"); (void)dosbrk(PAGE_SIZE * 2); markpage(p, num++); markpage(p, num++); for (i=0; i<num; i++) { if (checkpage(p, i, false)) { errx(1, "FAILED: data corrupt before forking (3)"); } } tprintf("Forking...\n"); pid = dofork(); if (pid == 0) { /* child */ for (i=0; i<num; i++) { if (checkpage(p, i, false)) { errx(1, "FAILED: data corrupt in child"); } } say("Child: freeing three pages\n"); dosbrk(-PAGE_SIZE * 3); num -= 3; for (i=0; i<num; i++) { if (checkpage(p, i, false)) { errx(1, "FAILED: data corrupt in child (2)"); } } say("Child: allocating two pages\n"); dosbrk(PAGE_SIZE * 2); markpage(p, num++); markpage(p, num++); for (i=0; i<num; i++) { if (checkpage(p, i, false)) { errx(1, "FAILED: data corrupt in child (3)"); } } say("Child: freeing all\n"); dosbrk(-PAGE_SIZE * num); exit(0); } say("Parent: allocating four pages\n"); dosbrk(PAGE_SIZE * 4); for (i=0; i<4; i++) { markpage(p, num++); } for (i=0; i<num; i++) { if (checkpage(p, i, false)) { errx(1, "FAILED: data corrupt in parent"); } } say("Parent: waiting\n"); dowait(pid); for (i=0; i<num; i++) { if (checkpage(p, i, false)) { errx(1, "FAILED: data corrupt after waiting"); } } (void)dosbrk(-PAGE_SIZE * num); tprintf("Passed sbrk test 15.\n"); success(TEST161_SUCCESS, SECRET, "/testbin/sbrktest"); }