/* * Common code for cmd_prog and cmd_shell. * * Note that this does not wait for the subprogram to finish, but * returns immediately to the menu. This is usually not what you want, * so you should have it call your system-calls-assignment waitpid * code after forking. * * Also note that because the subprogram's thread uses the "args" * array and strings, until you do this a race condition exists * between that code and the menu input code. */ static int common_prog(int nargs, char **args) { int result; #if OPT_SYNCHPROBS kprintf("Warning: this probably won't work with a " "synchronization-problems kernel.\n"); #endif result = thread_fork(args[0] /* thread name */, cmd_progthread /* thread function */, args /* thread arg */, nargs /* thread arg */, NULL); if (result) { kprintf("thread_fork failed: %s\n", strerror(result)); return result; } return 0; }
static int common_prog(int nargs, char **args) { struct proc *proc; int result; #if OPT_SYNCHPROBS kprintf("Warning: this probably won't work with a " "synchronization-problems kernel.\n"); #endif /* Create a process for the new program to run in. */ proc = proc_create_runprogram(args[0] /* name */); if (proc == NULL) { return ENOMEM; } result = thread_fork(args[0] /* thread name */, proc /* new process */, cmd_progthread /* thread function */, args /* thread arg */, nargs /* thread arg */); if (result) { kprintf("thread_fork failed: %s\n", strerror(result)); proc_destroy(proc); return result; } /* * The new process will be destroyed when the program exits... * once you write the code for handling that. */ int *status = kmalloc(sizeof(int)); sys_waitpid(proc->p_pid, status, 0); return 0; }
int sys_fork(struct trapframe *tf, int * retval) {/*This function is implementation to fork the thread*/ struct fork_info info; /* Create fork_info */ info.sem = sem_create("fork synch", 0); if (info.sem == NULL) { *retval = -1; return ENOMEM; } info.parent = curthread; info.tf = tf; /* fork the thread; child does all the work using fork_info */ int result; result = thread_fork("forked", &info, 0, md_forkentry, NULL); if (result) { sem_destroy(info.sem); *retval = -1; return ENOMEM; } P(info.sem); // wait until the child is ready (has a pid) *retval = info.child_pid; sem_destroy(info.sem); // Checks for errors denoted by the child_pid generated by chork if (info.child_pid == 0) { *retval = -1; return EAGAIN; } else if (info.child_pid < 0) { *retval = -1; return ENOMEM; } else { return 0; } }
int locktest(int nargs, char **args) { // =============================== // DEBUG: Timeout // =============================== //char *tname[32] = {"t00", "t01", "t02", "t03", "t04", "t05", "t06", "t07", "t08", "t09", "t10", "t11", "t12", "t13", "t14", "t15", "t16", "t17", "t18", "t19", "t20", "t21", "t22", "t23", "t24", "t25", "t26", "t27", "t28", "t29", "t30", "t31"}; // =============================== int i, result; (void)nargs; (void)args; inititems(); kprintf("Starting lock test...\n"); for (i=0; i<NTHREADS; i++) { // ======================================== // DEBUG: Timeout // ======================================== result = thread_fork("synchtest", NULL, i, locktestthread, NULL); //result = thread_fork(tname[i], NULL, i, locktestthread, NULL); // ======================================== if (result) { panic("locktest: thread_fork failed: %s\n", strerror(result)); } } for (i=0; i<NTHREADS; i++) { P(donesem); } kprintf("Lock test done.\n"); return 0; }
int sys_fork(struct trapframe *tf,struct addrspace *parent_addr_space){ //kprintf("\n in sys_fork"); struct thread *child_thread=NULL; struct thread *test; struct addrspace *parent_addr_space_copy; //create a new address space //kprintf("\n in sys_fork:creating new addr space"); parent_addr_space_copy=as_create(); if(parent_addr_space_copy==NULL) return ENOMEM; //make a copy of the parent's address space //kprintf("\n in sys_fork:copying to the addr space %x",parent_addr_space); as_copy(parent_addr_space,&parent_addr_space_copy); //kprintf("\n in sys_fork:copying to the addr space %x",*(parent_addr_space_copy)); //make a copy of the parent`s trapframe on kernel heap //kprintf("\n in sys_fork:copying trap frame"); struct trapframe *tf_temp=kmalloc(sizeof(struct trapframe)); if(tf_temp==NULL){ kfree(tf_temp); return ENOMEM; } memcpy(tf_temp,tf,sizeof(struct trapframe)); //call thread_fork //pass the trapframe and the address space of the parent to the child`s thread_fork //kprintf("\n in sys_fork:forking"); thread_fork("child thread",tf_temp,(unsigned long)parent_addr_space_copy,md_forkentry,&child_thread); //kprintf("\nchild_thread::%x",*(child_thread)); //copy other required stuff and return with child`s pid //test=(child_thread); return child_thread->pid; }
/* * Common code for cmd_prog and cmd_shell. * * Note that this does not wait for the subprogram to finish, but * returns immediately to the menu. This is usually not what you want, * so you should have it call your system-calls-assignment waitpid * code after forking. * * Also note that because the subprogram's thread uses the "args" * array and strings, until you do this a race condition exists * between that code and the menu input code. */ static int common_prog(int nargs, char **args) { struct proc *proc; int result; #if OPT_SYNCHPROBS kprintf("Warning: this probably won't work with a " "synchronization-problems kernel.\n"); #endif /* Create a process for the new program to run in. */ proc = proc_create_runprogram(args[0] /* name */); if (proc == NULL) { return ENOMEM; } result = thread_fork(args[0] /* thread name */, proc /* new process */, cmd_progthread /* thread function */, args /* thread arg */, nargs /* thread arg */); if (result) { kprintf("thread_fork failed: %s\n", strerror(result)); proc_destroy(proc); return result; } #ifdef UW /* wait until the process we have just launched - and any others that it may fork - is finished before proceeding */ P(no_proc_sem); #endif // UW return 0; }
int semtest(int nargs, char **args) { int i, result; (void)nargs; (void)args; inititems(); kprintf("Starting semaphore test...\n"); kprintf("If this hangs, it's broken: "); P(testsem); P(testsem); kprintf("ok\n"); for (i=0; i<NTHREADS; i++) { result = thread_fork("semtest", NULL, i, semtestthread, NULL); if (result) { panic("semtest: thread_fork failed: %s\n", strerror(result)); } } for (i=0; i<NTHREADS; i++) { V(testsem); P(donesem); } /* so we can run it again */ V(testsem); V(testsem); cleanupitems(); kprintf("Semaphore test done.\n"); return 0; }
static void dowritestress(const char *filesys) { int i, err; init_threadsem(); kprintf("*** Starting fs write stress test on %s:\n", filesys); for (i=0; i<NTHREADS; i++) { err = thread_fork("writestress", NULL, writestress_thread, (char *)filesys, i); if (err) { panic("thread_fork failed %s\n", strerror(err)); } } for (i=0; i<NTHREADS; i++) { P(threadsem); } kprintf("*** fs write stress test done\n"); }
int lab5test(int nargs, char **args) { init_first_sem(); kprintf("\nHello! Just printing to the console; nothing fancy. " ); kprintf("\n\nHere is the command you entered: "); for (int i = 0; i < nargs; i++) { kprintf(args[i]); kprintf(" "); } kprintf("\n"); thread_fork("print_message_thread", NULL, print_message, NULL, NULL); //This helps numbers print in order. P(first_sem); return 0; }
int sys_fork(struct trapframe *tf, pid_t *retval) { int result; char* name; (void) result; (void) tf; (void) retval; struct trapframe *temp_tf = kmalloc(sizeof(*temp_tf)); *temp_tf = *tf; struct proc *newproc = proc_create("forked_process"); // TODO: concurrency issue? as_copy(curproc->p_addrspace, &newproc->p_addrspace); newproc->p_filetable = kmalloc(sizeof(struct filetable)); newproc->p_filetable->filetable_lock = lock_create("filetable_lock"); filetable_copy(newproc->p_filetable); // copied from proc.c init p_cwd spinlock_acquire(&curproc->p_lock); if (curproc->p_cwd != NULL) { VOP_INCREF(curproc->p_cwd); newproc->p_cwd = curproc->p_cwd; } spinlock_release(&curproc->p_lock); newproc->parent_pid = curproc->pid; name = kstrdup(curproc->p_name); *retval = newproc->pid; thread_fork(name, newproc ,run_forked_proc, (void *)temp_tf, 0); return 0; }
/* * Load program and start running it in usermode * in a new thread. * This is essentially an amalgam of fork() and execv(). */ int runprogram(int nargs, char **args, struct process **created_proc) { if (nargs > ARGNUM_MAX) return E2BIG; struct vnode *v; int result; struct process *proc; // copy the string, since vfs_open() will modify it char *progname = kstrdup(args[0]); if (progname == NULL) return ENOMEM; /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } // We no longer need the duplicate program name kfree(progname); // set up new process structure proc = process_create(args[0]); if (proc == NULL) { vfs_close(v); return ENOMEM; } // Get a PID for the process. ENPROC is // the error code for "no more processes allowed // in the system." pid_t pid = process_identify(proc); if (pid == 0) { process_cleanup(proc); vfs_close(v); return ENPROC; } // Create a new file descriptor table proc->ps_fdt = fdt_create(); if (proc->ps_fdt == NULL) { process_destroy(pid); vfs_close(v); return ENOMEM; } // Open FDs for stdin, stdout, and stderr result = setup_inouterr(proc->ps_fdt); if (result) { process_destroy(pid); vfs_close(v); return result; } // Create a new address space proc->ps_addrspace = as_create(); if (proc->ps_addrspace==NULL) { process_destroy(pid); vfs_close(v); return ENOMEM; } struct new_process_context *ctxt = kmalloc(sizeof(struct new_process_context)); if (ctxt == NULL) { as_activate(NULL); process_destroy(pid); return ENOMEM; } ctxt->nargs = nargs; ctxt->args = args; ctxt->proc = proc; ctxt->executable = v; // Start a new thread to warp to user mode result = thread_fork("user process", run_process, ctxt, 0, NULL); if (result) { kfree(ctxt); as_activate(NULL); process_destroy(pid); return result; } // pass process to caller and return *created_proc = proc; return 0; }
int runpaintshop(int nargs, char **args) { int i, result; (void) nargs; /* avoid compiler warnings */ (void) args; /* this semaphore indicates everybody has gone home */ alldone = sem_create("alldone", 0); if (alldone==NULL) { panic("runpaintshop: out of memory\n"); } /* initialise the tint doses to 0 */ for (i =0 ; i < NCOLOURS; i++) { paint_tints[i].doses = 0; } /*********************************************************************** * call your routine that initialises the rest of the paintshop */ paintshop_open(); /* Start the paint shop staff */ for (i=0; i<NPAINTSHOPSTAFF; i++) { result = thread_fork("paint shop staff thread", NULL, i, paintshop_staff, NULL); if (result) { panic("runpaintshop: thread_fork failed: %s\n", strerror(result)); } } /* Start the customers */ for (i=0; i<NCUSTOMERS; i++) { result = thread_fork("customer thread", NULL, i, customer, NULL); if (result) { panic("runpaintshop: thread_fork failed: %s\n", strerror(result)); } } /* Wait for everybody to finish. */ for (i=0; i< NCUSTOMERS+NPAINTSHOPSTAFF; i++) { P(alldone); } for (i =0 ; i < NCOLOURS; i++) { kprintf("Tint %d used for %d doses\n", i+1, paint_tints[i].doses); } /*********************************************************************** * Call your paint shop clean up routine */ paintshop_close(); sem_destroy(alldone); kprintf("The paint shop is closed, bye!!!\n"); return 0; }
int catmouselock(int nargs, char ** args) { int index, error; /* * Avoid unused variable warnings. */ (void) nargs; (void) args; bowl1 = bowl_create(1); bowl2 = bowl_create(2); bowl_1 = lock_create("bowl_1"); bowl_2 = lock_create("bowl_2"); openbowl_lock = lock_create("openbowl_lock"); free_bowl = cv_create("free_bowl"); /* * Start NCATS catlock() threads. */ for (index = 0; index < NCATS; index++) { animal_create (index, CAT); error = thread_fork("catlock thread", NULL, index, catlock, NULL ); /* * panic() on error. */ if (error) { panic("catlock: thread_fork failed: %s\n", strerror(error) ); } } /* * Start NMICE mouselock() threads. */ for (index = 0; index < NMICE; index++) { animal_create (index, MOUSE); error = thread_fork("mouselock thread", NULL, index, mouselock, NULL ); /* * panic() on error. */ if (error) { panic("mouselock: thread_fork failed: %s\n", strerror(error) ); } } return 0; }
int catmouselock(int nargs, char ** args) { int index, error; /* * Avoid unused variable warnings. */ (void) nargs; (void) args; /* * Start NCATS catlock() threads. */ for (index = 0; index < NCATS; index++) { error = thread_fork("catlock thread", NULL, index, catlock, NULL ); /* * panic() on error. */ if (error) { panic("catlock: thread_fork failed: %s\n", strerror(error) ); } } /* * Start NMICE mouselock() threads. */ for (index = 0; index < NMICE; index++) { error = thread_fork("mouselock thread", NULL, index, mouselock, NULL ); /* * panic() on error. */ if (error) { panic("mouselock: thread_fork failed: %s\n", strerror(error) ); } } return 0; }
int sys_fork(struct trapframe* tf, pid_t* retval) { DEBUG(DB_EXEC,"sys_fork(): entering\n"); KASSERT(curproc != NULL); KASSERT(sizeof(struct trapframe)==(37*4)); char* child_name = kmalloc(sizeof(char)* NAME_MAX); strcpy(child_name, curproc->p_name); strcat(child_name, "_c"); // create PCB for child struct proc* child_proc = NULL; proc_fork(&child_proc); if (child_proc == NULL) { return ENOMEM; } strcpy(child_proc->p_name, child_name); KASSERT(child_proc->p_pid > 0); // copy address space and registers from this process to child struct addrspace* child_as = kmalloc(sizeof(struct addrspace)); if (child_as == NULL) { kfree(child_name); proc_destroy(child_proc); return ENOMEM; } struct trapframe* child_tf = kmalloc(sizeof(struct trapframe)); if (child_tf == NULL) { kfree(child_name); as_destroy(child_as); proc_destroy(child_proc); return ENOMEM; } DEBUG(DB_EXEC,"sys_fork(): copying address space...\n"); // copy the address space just created into the child process's // PCB structure int result = as_copy(curproc->p_addrspace, &child_as); if (result) { kfree(child_name); as_destroy(child_as); proc_destroy(child_proc); return result; } child_proc->p_addrspace = child_as; DEBUG(DB_EXEC,"sys_fork(): copying trapframe space...\n"); // copy this process's trapframe to the child process memcpy(child_tf, tf, sizeof(struct trapframe)); DEBUG(DB_EXEC, "sys_fork(): copying filetable...\n"); filetable_copy(curproc->p_filetable,&child_proc->p_filetable); DEBUG(DB_EXEC,"sys_fork(): assigning child process's parent as this process...\n"); // assign child processes parent as this process child_proc->p_parent = curproc; DEBUG(DB_EXEC,"sys_fork(): adding child to children procarray...\n"); result = procarray_add(&curproc->p_children, child_proc, NULL); if (result) { DEBUG(DB_EXEC, "sys_fork(): failed to add child process to proc_table...\n"); } DEBUG(DB_EXEC,"sys_fork(): allocating data...\n"); void **data = kmalloc(2*sizeof(void*)); data[0] = (void*)child_tf; data[1] = (void*)child_as; result = thread_fork(child_name, child_proc, &enter_forked_process, data, 0); if (result) { kfree(child_name); kfree(child_tf); as_destroy(child_as); proc_destroy(child_proc); return ENOMEM; } *retval = child_proc->p_pid; DEBUG(DB_EXEC, "sys_fork(): thread_fork returned: curproc=%u, child_proc=%u\n",curproc->p_pid,child_proc->p_pid); return 0; }
int catmouse(int nargs, char ** args) { int index, error, index2; /* * Avoid unused variable warnings. */ (void) nargs; (void) args; l = lock_create(lname); c = cv_create(cname); catsEating = 0; miceEating = 0; bowlOneUsed = 0; bowlTwoUsed = 0; /* * Start NMICE mouse() threads. */ for (index2 = 0; index2 < NMICE; index2++) { error = thread_fork("mouse thread", NULL, index2, mouse, NULL ); /* * panic() on error. */ if (error) { panic("mouse: thread_fork failed: %s\n", strerror(error) ); } } /* * Start NCATS cat() threads. */ for (index = 0; index < NCATS; index++) { error = thread_fork("cat thread", NULL, index, cat, NULL ); /* * panic() on error. */ if (error) { panic("cat: thread_fork failed: %s\n", strerror(error) ); } } //join threads with a CV if you have time, deallocate threads after join //cv_destroy(c); //lock_destroy(l); //we dont want the main thread to finish before the others clocksleep(10); return 0; }
int sysfork(int32_t *retval, struct trapframe *tf){ int s=splhigh(); DEBUG(1,"sysfork\n"); if(errsuperflag==1){ *retval=-1; splx(s); //thread_exit(); return ENOMEM; } int ret=0; struct thread *child_thread; struct trapframe *child_tf; int pid = my_get_pid(); if(pid==-1){ splx(s); //errno=11; *retval=-1; return 11; // EAGAIN too many processes exist }else{ *retval = pid; } parent_array[pid]=curthread->ppid; //initalize ur parent; DEBUG(1,"I am %d and my mommy is %d,I love her\n",pid,parent_array[pid]); child_tf = (struct trapframe *)kmalloc(sizeof(struct trapframe)); if(child_tf==NULL){ DEBUG(1,"tf messed %d\n",curthread->ppid); errsuperflag=1; splx(s); //thread_exit(); *retval=-1; return ENOMEM; } memcpy(child_tf,tf, sizeof(struct trapframe)); ret = thread_fork("child", child_tf, 0, forkentry, &child_thread); /*kprintf("copying stack\n"); kfree(child_thread->t_stack); int act; child_thread->t_stack = kmalloc(STACK_SIZE); //memcpy(child_thread->t_stack,curthread->t_stack,sizeof(curthread->t_stack)); copyoutstr(curthread->t_stack,(userptr_t)(child_thread->t_stack),sizeof(curthread->t_stack),&act);*/ child_thread->my_parent=curthread; (curthread->counter)++; if(ret!=0) { pid_array[pid]=NULL; DEBUG(1,"thread_fork messed %d\n",curthread->ppid); //int *temp; //sysexit(temp,child_tf); //kfree(child_thread); //errno = ret; child_thread->errflag=1; //as_activate(child_thread->t_vmspace); errsuperflag=1; *retval=-1; splx(s); //thread_exit(); return ret; } pid_array[pid] = child_thread; ret = as_copy((curthread->t_vmspace), &(child_thread->t_vmspace)); if(ret!=0){ DEBUG(1,"as_copy messed mommy: %d child: %d\n",curthread->ppid,pid); //int *temp; //sysexit(temp,child_tf); //kfree(child_thread); child_thread->errflag=1; as_activate(child_thread->t_vmspace); errsuperflag=1; *retval=-1; //as_destroy((child_thread->t_vmspace)); splx(s); //thread_exit(); return ret; } as_activate(child_thread->t_vmspace); ((child_thread))->ppid = pid; //DEBUG(1,"Pid Set %d\n", ((child_thread))->ppid); splx(s); return 0; }
/* static void writerthread(void *junk, unsigned long num) { (void)junk; rwlock_acquire_write(testrwlock); random_yielder(4); testval1++; kprintf_n("Thread %lu: Writer val:%lu\n", num, testval1); random_yielder(4); rwlock_release_write(testrwlock); V(donesem); return; }*/ int rwtest(int nargs, char **args) { (void)nargs; (void)args; int i, result; kprintf_n("Starting rwt1...\n"); for (i=0; i<CREATELOOPS; i++) { kprintf_t("."); testrwlock = rwlock_create("testreaderwriterlock"); if (testrwlock == NULL) { panic("rwt1: rwlock_create failed\n"); } donesem = sem_create("donesem", 0); if (donesem == NULL) { panic("rtw1: sem_create failed\n"); } if(i != CREATELOOPS -1) { rwlock_destroy(testrwlock); sem_destroy(donesem); } } spinlock_init(&status_lock); test_status = TEST161_SUCCESS; testval1 = 0; // create threads code for (i=0; i<NUMREADERS1; i++) { kprintf_t("."); result = thread_fork("rwlockstest", NULL, readerthread, NULL, i); if(result) { panic("rwt1: thread_fork failed: %s\n", strerror(result)); } } /* for (i=0; i<NUMWRITERS1; i++) { kprintf_t("."); result = thread_fork("rwlockstest", NULL, writerthread, NULL, i); if(result) { panic("rwt1: thread_fork failed: %s\n", strerror(result)); } */ kprintf("%d\n", i); int numthreads = NUMREADERS1; for(i=0; i<numthreads; i++) { kprintf_t("."); P(donesem); } rwlock_destroy(testrwlock); sem_destroy(donesem); testrwlock = NULL; donesem = NULL; kprintf_n("\n"); kprintf_n("\n"); success(TEST161_FAIL, SECRET, "rwt1"); return 0; }
pid_t sys_fork(const struct trapframe *parent_tf, int *err) { struct process *parent = curthread->t_proc; // set up new process structure struct process *child = process_create(parent->ps_name); if (child == NULL) { *err = ENOMEM; return -1; } // Get a PID for the child. ENPROC is // the error code for "no more processes allowed // in the system." pid_t child_pid = process_identify(child); if (child_pid == 0) { *err = ENPROC; process_cleanup(child); return -1; } // copy the file descriptor table of the parent child->ps_fdt = fdt_copy(parent->ps_fdt); if (child->ps_fdt == NULL) { *err = ENOMEM; process_destroy(child_pid); return -1; } // copy the address space of the parent *err = as_copy(parent->ps_addrspace, &child->ps_addrspace); if (*err) { process_destroy(child_pid); return -1; } // add PID to children now. That way, if we fail to // allocate memory, we have not yet forked a thread *err = pid_set_add(parent->ps_children, child_pid); if (*err) { process_destroy(child_pid); return -1; } // allocate space for child trapframe in the kernel heap struct trapframe *child_tf = kmalloc(sizeof(struct trapframe)); if (child_tf == NULL) { process_destroy(child_pid); pid_set_remove(parent->ps_children, child_pid); *err = ENOMEM; return -1; } // copy trapframe memcpy(child_tf, parent_tf, sizeof(struct trapframe)); // abuse child_tf->TF_RET (which will be set to 0) // to pass the process struct to the child thread // this cast and assignment will always work, // as pointers always fit in machine registers child_tf->TF_RET = (uintptr_t)child; // child thread sets up child return value // and ps_thread/t_proc *err = thread_fork("user process", enter_forked_process, child_tf, 0, NULL); if (*err) { process_destroy(child_pid); kfree(child_tf); pid_set_remove(parent->ps_children, child_pid); return -1; } return child_pid; }
int catmouse(int nargs, char ** args) { int index, error; int i; /* check and process command line arguments */ if (nargs != 5) { kprintf("Usage: <command> NUM_BOWLS NUM_CATS NUM_MICE NUM_LOOPS\n"); return 1; // return failure indication } /* check the problem parameters, and set the global variables */ NumBowls = atoi(args[1]); if (NumBowls <= 0) { kprintf("catmouse: invalid number of bowls: %d\n",NumBowls); return 1; } NumCats = atoi(args[2]); if (NumCats < 0) { kprintf("catmouse: invalid number of cats: %d\n",NumCats); return 1; } NumMice = atoi(args[3]); if (NumMice < 0) { kprintf("catmouse: invalid number of mice: %d\n",NumMice); return 1; } NumLoops = atoi(args[4]); if (NumLoops <= 0) { kprintf("catmouse: invalid number of loops: %d\n",NumLoops); return 1; } kprintf("Using %d bowls, %d cats, and %d mice. Looping %d times.\n", NumBowls,NumCats,NumMice,NumLoops); /* create the semaphore that is used to make the main thread wait for all of the cats and mice to finish */ CatMouseWait = sem_create("CatMouseWait",0); if (CatMouseWait == NULL) { panic("catmouse: could not create semaphore\n"); } /* * initialize the bowls */ if (initialize_bowls(NumBowls)) { panic("catmouse: error initializing bowls.\n"); } #if OPT_A1 // Create the kitchen k = kitchen_create(); #endif /* * Start NumCats cat_simulation() threads. */ for (index = 0; index < NumCats; index++) { error = thread_fork("cat_simulation thread",NULL,index,cat_simulation,NULL); if (error) { panic("cat_simulation: thread_fork failed: %s\n", strerror(error)); } } /* * Start NumMice mouse_simulation() threads. */ for (index = 0; index < NumMice; index++) { error = thread_fork("mouse_simulation thread",NULL,index,mouse_simulation,NULL); if (error) { panic("mouse_simulation: thread_fork failed: %s\n",strerror(error)); } } /* wait for all of the cats and mice to finish before terminating */ for(i=0;i<(NumCats+NumMice);i++) { P(CatMouseWait); } #if OPT_A1 // Cleanup the kitchen lol kitchen_destroy(k); #endif /* clean up the semaphore the we created */ sem_destroy(CatMouseWait); return 0; }
// Change this function as necessary int whalemating(int nargs, char **args) { int i, j, err=0; cv_male=cv_create("male"); cv_female=cv_create("female"); cv_mm=cv_create("mm"); lk_male=lock_create("male"); lk_female=lock_create("female"); lk_mm=lock_create("mm"); (void)nargs; (void)args; for (i = 0; i < 3; i++) { for (j = 0; j < NMATING; j++) { #ifdef UW switch(i) { case 0: err = thread_fork("Male Whale Thread", NULL, male, NULL, j); break; case 1: err = thread_fork("Female Whale Thread", NULL, female, NULL, j); break; case 2: err = thread_fork("Matchmaker Whale Thread", NULL, matchmaker, NULL, j); break; } #else switch(i) { case 0: err = thread_fork("Male Whale Thread", male, NULL, j, NULL); break; case 1: err = thread_fork("Female Whale Thread", female, NULL, j, NULL); break; case 2: err = thread_fork("Matchmaker Whale Thread", matchmaker, NULL, j, NULL); break; } #endif /* UW */ if (err) { panic("whalemating: thread_fork failed: %s)\n", strerror(err)); } } } return 0; }
int createcars(int nargs, char ** args) { int index, error; /* * Avoid unused variable warnings. */ (void) nargs; (void) args; NW_lock = lock_create("NW_lock"); NE_lock = lock_create("NE_lock"); SW_lock = lock_create("SW_lock"); SE_lock = lock_create("SE_lock"); // kprintf("before sem_create !\n"); from_north = sem_create("sem_north", 1); from_south = sem_create("sem_south", 1); from_east = sem_create("sem_east", 1); from_west = sem_create("sem_west", 1); // kprintf("we created sems\n"); join_sem = sem_create("join_sem", 0); /* * Start NCARS approachintersection() threads. */ for (index = 0; index < NCARS; index++) { error = thread_fork("approachintersection thread", NULL, index, approachintersection, NULL ); /* * panic() on error. */ if (error) { panic("approachintersection: thread_fork failed: %s\n", strerror(error) ); } } int i ; for (i = 0; i < NCARS; i++) { P(join_sem); } lock_destroy(NW_lock); lock_destroy(NE_lock); lock_destroy(SW_lock); lock_destroy(SE_lock); sem_destroy(from_north); sem_destroy(from_south); sem_destroy(from_east); sem_destroy(from_west); sem_destroy(join_sem); return 0; }
pid_t proc_fork(void) { /* * http://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html */ KERROR_DBG("%s(%u)\n", __func__, curproc->pid); struct proc_info * const old_proc = curproc; struct proc_info * new_proc; pid_t retval = 0; /* Check that the old process is in valid state. */ if (!old_proc || old_proc->state == PROC_STATE_INITIAL) return -EINVAL; new_proc = clone_proc_info(old_proc); if (!new_proc) return -ENOMEM; /* Clear some things required to be zeroed at this point */ new_proc->state = PROC_STATE_INITIAL; new_proc->files = NULL; new_proc->pgrp = NULL; /* Must be NULL so we don't free the old ref. */ memset(&new_proc->tms, 0, sizeof(new_proc->tms)); /* ..and then start to fix things. */ /* * Process group. */ PROC_LOCK(); proc_pgrp_insert(old_proc->pgrp, new_proc); PROC_UNLOCK(); /* * Initialize the mm struct. */ retval = vm_mm_init(&new_proc->mm, old_proc->mm.nr_regions); if (retval) goto out; /* * Clone the master page table. * This is probably something we would like to get rid of but we are * stuck with because it's the easiest way to keep some static kernel * mappings valid between processes. */ if (mmu_ptcpy(&new_proc->mm.mpt, &old_proc->mm.mpt)) { retval = -EAGAIN; goto out; } /* * Clone L2 page tables. */ if (vm_ptlist_clone(&new_proc->mm.ptlist_head, &new_proc->mm.mpt, &old_proc->mm.ptlist_head) < 0) { retval = -ENOMEM; goto out; } retval = clone_code_region(new_proc, old_proc); if (retval) goto out; /* * Clone stack region. */ retval = clone_stack(new_proc, old_proc); if (retval) { KERROR_DBG("Cloning stack region failed.\n"); goto out; } /* * Clone other regions. */ retval = clone_regions_from(new_proc, old_proc, MM_HEAP_REGION); if (retval) goto out; /* * Set break values. */ new_proc->brk_start = (void *)( (*new_proc->mm.regions)[MM_HEAP_REGION]->b_mmu.vaddr + (*new_proc->mm.regions)[MM_HEAP_REGION]->b_bcount); new_proc->brk_stop = (void *)( (*new_proc->mm.regions)[MM_HEAP_REGION]->b_mmu.vaddr + (*new_proc->mm.regions)[MM_HEAP_REGION]->b_bufsize); /* fork() signals */ ksignal_signals_fork_reinit(&new_proc->sigs); /* * Copy file descriptors. */ KERROR_DBG("Copy file descriptors\n"); int nofile_max = old_proc->rlim[RLIMIT_NOFILE].rlim_max; if (nofile_max < 0) { #if configRLIMIT_NOFILE < 0 #error configRLIMIT_NOFILE can't be negative. #endif nofile_max = configRLIMIT_NOFILE; } new_proc->files = fs_alloc_files(nofile_max, nofile_max); if (!new_proc->files) { KERROR_DBG( "\tENOMEM when tried to allocate memory for file descriptors\n"); retval = -ENOMEM; goto out; } /* Copy and ref old file descriptors */ for (int i = 0; i < old_proc->files->count; i++) { new_proc->files->fd[i] = old_proc->files->fd[i]; fs_fildes_ref(new_proc->files, i, 1); /* null pointer safe */ } KERROR_DBG("All file descriptors copied\n"); /* * Select PID. */ if (likely(nprocs != 1)) { /* Tecnically it would be good idea to have lock * on nprocs before reading it but I think this * should work fine... */ new_proc->pid = proc_get_random_pid(); } else { /* Proc is init */ KERROR_DBG("Assuming this process to be init\n"); new_proc->pid = 1; } if (new_proc->cwd) { KERROR_DBG("Increment refcount for the cwd\n"); vref(new_proc->cwd); /* Increment refcount for the cwd */ } /* Update inheritance attributes */ set_proc_inher(old_proc, new_proc); /* Insert the new process into the process array */ procarr_insert(new_proc); /* * A process shall be created with a single thread. If a multi-threaded * process calls fork(), the new process shall contain a replica of the * calling thread. * We left main_thread null if calling process has no main thread. */ KERROR_DBG("Handle main_thread\n"); if (old_proc->main_thread) { KERROR_DBG("Call thread_fork() to get a new main thread for the fork.\n"); if (!(new_proc->main_thread = thread_fork(new_proc->pid))) { KERROR_DBG("\tthread_fork() failed\n"); retval = -EAGAIN; goto out; } KERROR_DBG("\tthread_fork() fork OK\n"); /* * We set new proc's mpt as the current mpt because the new main thread * is going to return directly to the user space. */ new_proc->main_thread->curr_mpt = &new_proc->mm.mpt; } else { KERROR_DBG("No thread to fork.\n"); new_proc->main_thread = NULL; } retval = new_proc->pid; new_proc->state = PROC_STATE_READY; #ifdef configPROCFS procfs_mkentry(new_proc); #endif if (new_proc->main_thread) { KERROR_DBG("Set the new main_thread (%d) ready\n", new_proc->main_thread->id); thread_ready(new_proc->main_thread->id); } KERROR_DBG("Fork %d -> %d created.\n", old_proc->pid, new_proc->pid); out: if (unlikely(retval < 0)) { _proc_free(new_proc); } return retval; }
int catmouse(int nargs, char ** args) { int index, error; int i; /* check and process command line arguments */ if ((nargs != 9) && (nargs != 5)) { kprintf("Usage: <command> NUM_BOWLS NUM_CATS NUM_MICE NUM_LOOPS\n"); kprintf("or\n"); kprintf("Usage: <command> NUM_BOWLS NUM_CATS NUM_MICE NUM_LOOPS "); kprintf("CAT_EATING_TIME CAT_SLEEPING_TIME MOUSE_EATING_TIME MOUSE_SLEEPING_TIME\n"); return 1; // return failure indication } /* check the problem parameters, and set the global variables */ NumBowls = atoi(args[1]); bowlTaken = kmalloc(sizeof(bool)*NumBowls); for(int i = 0 ; i < NumBowls; i++){ bowlTaken[i] = false; } if (NumBowls <= 0) { kprintf("catmouse: invalid number of bowls: %d\n",NumBowls); return 1; } NumCats = atoi(args[2]); if (NumCats < 0) { kprintf("catmouse: invalid number of cats: %d\n",NumCats); return 1; } NumMice = atoi(args[3]); if (NumMice < 0) { kprintf("catmouse: invalid number of mice: %d\n",NumMice); return 1; } NumLoops = atoi(args[4]); if (NumLoops <= 0) { kprintf("catmouse: invalid number of loops: %d\n",NumLoops); return 1; } if (nargs == 9) { CatEatTime = atoi(args[5]); if (CatEatTime < 0) { kprintf("catmouse: invalid cat eating time: %d\n",CatEatTime); return 1; } CatSleepTime = atoi(args[6]); if (CatSleepTime < 0) { kprintf("catmouse: invalid cat sleeping time: %d\n",CatSleepTime); return 1; } MouseEatTime = atoi(args[7]); if (MouseEatTime < 0) { kprintf("catmouse: invalid mouse eating time: %d\n",MouseEatTime); return 1; } MouseSleepTime = atoi(args[8]); if (MouseSleepTime < 0) { kprintf("catmouse: invalid mouse sleeping time: %d\n",MouseSleepTime); return 1; } } kprintf("Using %d bowls, %d cats, and %d mice. Looping %d times.\n", NumBowls,NumCats,NumMice,NumLoops); kprintf("Using cat eating time %d, cat sleeping time %d\n", CatEatTime, CatSleepTime); kprintf("Using mouse eating time %d, mouse sleeping time %d\n", MouseEatTime, MouseSleepTime); /* create the semaphore that is used to make the main thread wait for all of the cats and mice to finish */ CatMouseWait = sem_create("CatMouseWait",0); if (CatMouseWait == NULL) { panic("catmouse: could not create semaphore\n"); } /* * initialize the bowls */ if (initialize_bowls(NumBowls)) { panic("catmouse: error initializing bowls.\n"); } /* * Start NumCats cat_simulation() threads. */ for (index = 0; index < NumCats; index++) { error = thread_fork("cat_simulation thread", NULL, cat_simulation, NULL, index); if (error) { panic("cat_simulation: thread_fork failed: %s\n", strerror(error)); } } /* * Start NumMice mouse_simulation() threads. */ for (index = 0; index < NumMice; index++) { error = thread_fork("mouse_simulation thread", NULL, mouse_simulation, NULL, index); if (error) { panic("mouse_simulation: thread_fork failed: %s\n",strerror(error)); } } /* wait for all of the cats and mice to finish before terminating */ for(i=0;i<(NumCats+NumMice);i++) { P(CatMouseWait); } /* clean up the semaphore that we created */ sem_destroy(CatMouseWait); /* clean up resources used for tracking bowl use */ cleanup_bowls(); return 0; }
int waittest(int nargs, char **args) { int i, spl, status, err; pid_t kid; pid_t kids2[NTHREADS]; int kids2_head = 0, kids2_tail = 0; (void)nargs; (void)args; init_sem(); kprintf("Starting wait test...\n"); /* * This first set should (hopefully) still be running when * wait is called (helped by the splhigh). */ kprintf("\n"); kprintf("Set 1 (wait should generally succeed)\n"); kprintf("-------------------------------------\n"); spl = splhigh(); for (i = 0; i < NTHREADS; i++) { err = thread_fork("wait test thread", waitfirstthread, NULL, i, &kid); if (err) { panic("waittest: thread_fork failed (%d)\n", err); } kprintf("Spawned pid %d\n", kid); kids2[kids2_tail] = kid; kids2_tail = (kids2_tail+1) % NTHREADS; } splx(spl); for (i = 0; i < NTHREADS; i++) { kid = kids2[kids2_head]; kids2_head = (kids2_head+1) % NTHREADS; kprintf("Waiting on pid %d...\n", kid); err = pid_join(kid, &status, 0); if (err) { kprintf("Pid %d waitpid error %d!\n", kid, err); } else { kprintf("Pid %d exit status: %d\n", kid, status); } } /* * This second set has to V their semaphore before the exit, * so when wait is called, they will have already exited, but * their parent is still alive. */ kprintf("\n"); kprintf("Set 2 (wait should always succeed)\n"); kprintf("----------------------------------\n"); for (i = 0; i < NTHREADS; i++) { err = thread_fork("wait test thread", exitfirstthread, NULL, i, &kid); if (err) { panic("waittest: thread_fork failed (%d)\n", err); } kprintf("Spawned pid %d\n", kid); kids2[kids2_tail] = kid; kids2_tail = (kids2_tail+1) % NTHREADS; if (err) { panic("waittest: q_addtail failed (%d)\n", err); } } for (i = 0; i < NTHREADS; i++) { kid = kids2[kids2_head]; kids2_head = (kids2_head+1) % NTHREADS; kprintf("Waiting for pid %d to V()...\n", kid); P(exitsems[i]); kprintf("Appears that pid %d P()'d\n", kid); kprintf("Waiting on pid %d...\n", kid); err = pid_join(kid, &status, 0); if (err) { kprintf("Pid %d waitpid error %d!\n", kid, err); } else { kprintf("Pid %d exit status: %d\n", kid, status); } } /* * This third set has to V their semaphore before the exit, so * when wait is called, they will have already exited, and * since we've gone through and disowned them all, their exit * statuses should have been disposed of already and our waits * should all fail. */ kprintf("\n"); kprintf("Set 3 (wait should never succeed)\n"); kprintf("---------------------------------\n"); for (i = 0; i < NTHREADS; i++) { err = thread_fork("wait test thread", exitfirstthread, NULL, i, &kid); if (err) { panic("waittest: thread_fork failed (%d)\n", err); } kprintf("Spawned pid %d\n", kid); pid_detach(kid); kids2[kids2_tail] = kid; kids2_tail = (kids2_tail+1) % NTHREADS; } for (i = 0; i < NTHREADS; i++) { kid = kids2[kids2_head]; kids2_head = (kids2_head+1) % NTHREADS; kprintf("Waiting for pid %d to V()...\n", kid); P(exitsems[i]); kprintf("Appears that pid %d P()'d\n", kid); kprintf("Waiting on pid %d...\n", kid); err = pid_join(kid, &status, 0); if (err) { kprintf("Pid %d waitpid error %d!\n", kid, err); } else { kprintf("Pid %d exit status: %d\n", kid, status); } } kprintf("\nWait test done.\n"); return 0; }
pid_t sys_fork(struct trapframe *tf) { if(procarray_num(procarr) == PID_MAX - PID_MIN) { errno = EMPROC; return 0; } struct proc *newproc = kmalloc(sizeof(*newproc)); // normal field newproc->p_name = kstrdup(curthread->t_proc->p_name); // name newproc->p_cwd = curproc->p_cwd; // vnode // synch field spinlock_init(&newproc->p_lock); newproc->p_cv = cv_create("proc cv"); newproc->p_lk = lock_create("proc lock"); newproc->open_num = 0; // files field newproc->fd_table = kmalloc(sizeof(struct fd *) * MAX_fd_table); for(unsigned i = 0 ; i < MAX_fd_table ; i++) { newproc->fd_table[i] = curproc->fd_table[i]; } // pid creation for(pid_t curid = PID_MIN ; curid <= PID_MAX ; curid++) { // loop through available pid range. if(find_proc(curid) == NULL) { // first available pid found. newproc->p_pid = curid; // set pid. break; // break loop. } } threadarray_init(&newproc->p_threads); spinlock_init(&newproc->p_lock); // copy threads // struct threadarray oldthreads = curproc->p_threads; pid_t result; procarray_add(procarr,newproc,NULL); struct exitc *c = kmalloc(sizeof(struct exitc)); c->exitcode = -1; c->pid = newproc->p_pid; exitcarray_add(codes,c,NULL); // fork thread // struct thread *t = threadarray_get(&oldthreads,0); // copy trapframe to heap. struct trapframe *ctf = kmalloc(sizeof(struct trapframe)); ctf->tf_vaddr = tf->tf_vaddr; ctf->tf_status = tf->tf_status; ctf->tf_cause = tf->tf_cause; ctf->tf_lo = tf->tf_lo; ctf->tf_hi = tf->tf_hi; ctf->tf_ra = tf->tf_ra; ctf->tf_at = tf->tf_at; ctf->tf_v0 = tf->tf_v0; ctf->tf_v1 = tf->tf_v1; ctf->tf_a0 = tf->tf_a0; ctf->tf_a1 = tf->tf_a1; ctf->tf_a2 = tf->tf_a2; ctf->tf_a3 = tf->tf_a3; ctf->tf_t0 = tf->tf_t0; ctf->tf_t1 = tf->tf_t1; ctf->tf_t2 = tf->tf_t2; ctf->tf_t3 = tf->tf_t3; ctf->tf_t4 = tf->tf_t4; ctf->tf_t5 = tf->tf_t5; ctf->tf_t6 = tf->tf_t6; ctf->tf_t7 = tf->tf_t7; ctf->tf_s0 = tf->tf_s0; ctf->tf_s1 = tf->tf_s1; ctf->tf_s2 = tf->tf_s2; ctf->tf_s3 = tf->tf_s3; ctf->tf_s4 = tf->tf_s4; ctf->tf_s5 = tf->tf_s5; ctf->tf_s6 = tf->tf_s6; ctf->tf_s7 = tf->tf_s7; ctf->tf_t8 = tf->tf_t8; ctf->tf_t9 = tf->tf_t9; ctf->tf_k0 = tf->tf_k0; ctf->tf_k1 = tf->tf_k1; ctf->tf_gp = tf->tf_gp; ctf->tf_sp = tf->tf_sp; ctf->tf_s8 = tf->tf_s8; ctf->tf_epc = tf->tf_epc; //int spl = splhigh(); result = thread_fork(curthread->t_proc->p_name, newproc, enter_forked_process, ctf, (unsigned long)curproc->p_addrspace ); // parent return. //splx(spl); return newproc->p_pid; }
int catmouse(int nargs, char ** args) { int catindex, mouseindex, error; int i; int mean_cat_wait_usecs, mean_mouse_wait_usecs; time_t before_sec, after_sec, wait_sec; uint32_t before_nsec, after_nsec, wait_nsec; int total_bowl_milliseconds, total_eating_milliseconds, utilization_percent; /* check and process command line arguments */ if ((nargs != 9) && (nargs != 5)) { kprintf("Usage: <command> NUM_BOWLS NUM_CATS NUM_MICE NUM_LOOPS\n"); kprintf("or\n"); kprintf("Usage: <command> NUM_BOWLS NUM_CATS NUM_MICE NUM_LOOPS "); kprintf("CAT_EATING_TIME CAT_SLEEPING_TIME MOUSE_EATING_TIME MOUSE_SLEEPING_TIME\n"); return 1; // return failure indication } /* check the problem parameters, and set the global variables */ NumBowls = atoi(args[1]); if (NumBowls <= 0) { kprintf("catmouse: invalid number of bowls: %d\n",NumBowls); return 1; } NumCats = atoi(args[2]); if (NumCats < 0) { kprintf("catmouse: invalid number of cats: %d\n",NumCats); return 1; } NumMice = atoi(args[3]); if (NumMice < 0) { kprintf("catmouse: invalid number of mice: %d\n",NumMice); return 1; } NumLoops = atoi(args[4]); if (NumLoops <= 0) { kprintf("catmouse: invalid number of loops: %d\n",NumLoops); return 1; } if (nargs == 9) { CatEatTime = atoi(args[5]); if (CatEatTime < 0) { kprintf("catmouse: invalid cat eating time: %d\n",CatEatTime); return 1; } CatSleepTime = atoi(args[6]); if (CatSleepTime < 0) { kprintf("catmouse: invalid cat sleeping time: %d\n",CatSleepTime); return 1; } MouseEatTime = atoi(args[7]); if (MouseEatTime < 0) { kprintf("catmouse: invalid mouse eating time: %d\n",MouseEatTime); return 1; } MouseSleepTime = atoi(args[8]); if (MouseSleepTime < 0) { kprintf("catmouse: invalid mouse sleeping time: %d\n",MouseSleepTime); return 1; } } if ((NumMice >= INVALID_ANIMAL_NUM) || (NumCats >= INVALID_ANIMAL_NUM)) { panic("Trying to use too many cats or mice: limit = %d\n", INVALID_ANIMAL_NUM); } kprintf("Using %d bowls, %d cats, and %d mice. Looping %d times.\n", NumBowls,NumCats,NumMice,NumLoops); kprintf("Using cat eating time %d, cat sleeping time %d\n", CatEatTime, CatSleepTime); kprintf("Using mouse eating time %d, mouse sleeping time %d\n", MouseEatTime, MouseSleepTime); /* create the semaphore that is used to make the main thread wait for all of the cats and mice to finish */ CatMouseWait = sem_create("CatMouseWait",0); if (CatMouseWait == NULL) { panic("catmouse: could not create semaphore\n"); } /* initialize our simulation state */ initialize_bowls(); /* initialize the synchronization functions */ catmouse_sync_init(NumBowls); /* get current time, for measuring total simulation time */ gettime(&before_sec,&before_nsec); /* * Start NumCats cat_simulation() threads and NumMice mouse_simulation() threads. * Alternate cat and mouse creation. */ for (catindex = 0; catindex < NumCats; catindex++) { error = thread_fork("cat_simulation thread", NULL, cat_simulation, NULL, catindex); if (error) { panic("cat_simulation: thread_fork failed: %s\n", strerror(error)); } if (catindex < NumMice) { error = thread_fork("mouse_simulation thread", NULL, mouse_simulation, NULL, catindex); if (error) { panic("mouse_simulation: thread_fork failed: %s\n",strerror(error)); } } } /* launch any remaining mice */ for(mouseindex = catindex; mouseindex < NumMice; mouseindex++) { error = thread_fork("mouse_simulation thread", NULL, mouse_simulation, NULL, mouseindex); if (error) { panic("mouse_simulation: thread_fork failed: %s\n",strerror(error)); } } /* wait for all of the cats and mice to finish before terminating */ for(i=0;i<(NumCats+NumMice);i++) { P(CatMouseWait); } /* get current time, for measuring total simulation time */ gettime(&after_sec,&after_nsec); /* compute total simulation time */ getinterval(before_sec,before_nsec,after_sec,after_nsec,&wait_sec,&wait_nsec); /* compute and report bowl utilization */ total_bowl_milliseconds = (wait_sec*1000 + wait_nsec/1000000)*NumBowls; total_eating_milliseconds = (NumCats*CatEatTime + NumMice*MouseEatTime)*NumLoops*1000; if (total_bowl_milliseconds > 0) { utilization_percent = total_eating_milliseconds*100/total_bowl_milliseconds; kprintf("STATS: Bowl utilization: %d%%\n",utilization_percent); } /* clean up the semaphore that we created */ sem_destroy(CatMouseWait); /* clean up the synchronization state */ catmouse_sync_cleanup(NumBowls); /* clean up resources used for tracking bowl use */ cleanup_bowls(); if (cat_wait_count > 0) { /* some rounding error here - not significant if cat_wait_count << 1000000 */ mean_cat_wait_usecs = (cat_total_wait_secs*1000000+cat_total_wait_nsecs/1000)/cat_wait_count; kprintf("STATS: Mean cat waiting time: %d.%d seconds\n", mean_cat_wait_usecs/1000000,mean_cat_wait_usecs%1000000); } if (mouse_wait_count > 0) { /* some rounding error here - not significant if mouse_wait_count << 1000000 */ mean_mouse_wait_usecs = (mouse_total_wait_secs*1000000+mouse_total_wait_nsecs/1000)/mouse_wait_count; kprintf("STATS: Mean mouse waiting time: %d.%d seconds\n", mean_mouse_wait_usecs/1000000,mean_mouse_wait_usecs%1000000); } return 0; }