Beispiel #1
0
/*
 * 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;
}
Beispiel #2
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;
}
Beispiel #3
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;
}
Beispiel #5
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;
}
Beispiel #6
0
/*
 * 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;
}
Beispiel #7
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;
}
Beispiel #8
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");
}
Beispiel #9
0
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;



}
Beispiel #10
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;
}
Beispiel #11
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;
}
Beispiel #14
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;
}
Beispiel #15
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;
}
Beispiel #17
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;
}
Beispiel #19
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;
}
Beispiel #20
0
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;
}
Beispiel #21
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;
}
Beispiel #22
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;
}
Beispiel #23
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;
}
Beispiel #25
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;
}
Beispiel #26
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;
}
Beispiel #27
0
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;
}