/*
 * Run multiple pairs of threads, each running make_dir_thread or rm_dir_thread
 * with a different parameter.  One will be creating a directory full of files,
 * and the other will be deleting them.  They do not move in lock step, so for
 * a few threads, say 4 or 5, the system is likely to run out of i-nodes.
 *
 * The calling format (from the kshell) is
 * directory_test <num>, where num is an integer.  The number is parsed into an
 * int and pairs of threads with parameter 0..num are created.  This code then
 * waits for them and prints each exit value.
 */
int faber_directory_test(kshell_t *ksh, int argc, char **argv) {
        KASSERT(NULL != ksh);

        proc_t *p = NULL;	/* A process to run in */
        kthread_t *thr = NULL;	/* A thread to run in it */
	char tname[TESTBUFLEN];	/* A thread name */
	int pid = 0;		/* Process ID from do_waitpid (who exited?) */
	int lim = 1;		/* Number of processes to run */
	int rv = 0;		/* Return values */
	int i = 0;		/* Scratch */

        KASSERT(NULL != ksh);
	if ( argc > 1) {
	    /* Oh, barf */
	    if ( sscanf(argv[1], "%d", &lim) != 1)
		lim = 1;
	    /* A little bounds checking */
	    if ( lim < 1 || lim > 255 )
		lim = 1;
	}

	/*  Start pairs of processes */
	for ( i = 0; i< lim; i++) {

	    /* The maker process */
	    snprintf(tname, TESTBUFLEN, "thread%03d", i);
	    p = proc_create(tname);
	    KASSERT(NULL != p);
	    thr = kthread_create(p, make_dir_thread, i, NULL);
	    KASSERT(NULL != thr);

	    sched_make_runnable(thr);

	    /* The deleter process */
	    snprintf(tname, TESTBUFLEN, "rmthread%03d", i);
	    p = proc_create(tname);
	    KASSERT(NULL != p);
	    thr = kthread_create(p, rm_dir_thread, i, NULL);
	    KASSERT(NULL != thr);

	    sched_make_runnable(thr);
	}

	/* Wait for children and report their error codes */
	while ( ( pid = do_waitpid(-1, 0 , &rv) ) != -ECHILD) 
	    if ( rv < 0 ) 
		kprintf(ksh, "Child %d: %d %s\n", pid, rv, strerror(-rv));
	    else
		kprintf(ksh, "Child %d: %d\n", pid, rv);

	return rv;
}
Esempio n. 2
0
void *
sunghan_test(int arg1, void *arg2)
{
	int status;
	int proc_count = 0;
	pid_t proc_pid[3];

	int i;

	dbg(DBG_TEST, ">>> Start running sunghan_test()...\n");

	mynode.length = 0;
	kmutex_init(&mynode.my_mutex);
	sched_queue_init(&mynode.my_queue);

	proc_t *p1 = proc_create("add_node");
        KASSERT(NULL != p1);
	kthread_t *thr1 = kthread_create(p1, add_my_node, 0, NULL);
        KASSERT(NULL != thr1);
	sched_make_runnable(thr1);
	proc_pid[proc_count++] = p1->p_pid;

	proc_t *p2 = proc_create("remove_node");
        KASSERT(NULL != p2);
	kthread_t *thr2 = kthread_create(p2, remove_my_node, 0, NULL);
        KASSERT(NULL != thr2);
	sched_make_runnable(thr2);
	proc_pid[proc_count++] = p2->p_pid;
	
	proc_t *p3 = proc_create("watch_dog");
       	KASSERT(NULL != p3);
	kthread_t *thr3 = kthread_create(p3, watch_dog, 0, NULL);
       	KASSERT(NULL != thr3);
	sched_make_runnable(thr3);
	proc_pid[proc_count++] = p3->p_pid;
	
	for (i=0; i<2; ++i) {
		do_waitpid(proc_pid[i], 0, &status);
	}
	sched_broadcast_on(&mynode.my_queue);
	do_waitpid(proc_pid[2], 0, &status);

	while (!do_waitpid(p2->p_pid, 0, &status));

	dbg(DBG_TEST, "sunghan_test() terminated\n");

        return NULL;
}
Esempio n. 3
0
static void test_locking_and_cancelling(){
    dbg(DBG_TEST, "testing kmutex behavior with cancellation\n");

    kmutex_t m;
    kmutex_init(&m);

    proc_t *kmutex_proc = proc_create("kmutex_sleep_test_proc");
    kthread_t *kmutex_thread =  kthread_create(kmutex_proc, 
                                        cancellable_lock_kmutex,
                                        NULL, 
                                        (void *) &m);

    sched_make_runnable(kmutex_thread);

    kmutex_lock(&m);

    /* let kmutex_proc attempt to lock the mutex */
    yield();

    kthread_cancel(kmutex_thread, 0);

    kmutex_unlock(&m);

    int status;
    do_waitpid(kmutex_proc->p_pid, 0, &status);

    dbg(DBG_TESTPASS, "kmutex cancellation tests passed!\n");
}
Esempio n. 4
0
/*
 * Should be called from the init proc 
 */
static void test_proc_create(){
    dbg(DBG_TEST, "testing proc_create\n");

    proc_t *myproc = proc_create("myproc");

    KASSERT(list_empty(&myproc->p_threads));
    KASSERT(list_empty(&myproc->p_children));

    KASSERT(sched_queue_empty(&myproc->p_wait));

    KASSERT(myproc->p_pproc->p_pid == 1 && "created proc's parent isn't the init proc\n");
    KASSERT(myproc->p_state == PROC_RUNNING);

    /* make sure it's in the proc list */
    KASSERT(proc_lookup(myproc->p_pid) == myproc && "created proc not in proc list\n");

    /* make sure it's in it's parent's child list */
    KASSERT(in_child_list(myproc));

    /* clean everything up */
    kthread_t *mythread = kthread_create(myproc, simple_function, NULL, NULL);
    sched_make_runnable(mythread);

    int status;
    do_waitpid(myproc->p_pid, 0, &status);
    
    dbg(DBG_TESTPASS, "all proc_create tests passed!\n");
}
Esempio n. 5
0
static void test_normal_locking(){
    dbg(DBG_TEST, "testing normal mutex behavior\n");

    kmutex_t m;
    kmutex_init(&m);

    proc_t *kmutex_proc = proc_create("kmutex_test_proc");
    kthread_t *kmutex_thread = kthread_create(kmutex_proc, lock_kmutex_func,
                                          NULL, (void *) &m);

    sched_make_runnable(kmutex_thread);

    kmutex_lock(&m);
    
    /* let kmutex_proc attempt to lock the mutex */
    yield();

    kmutex_unlock(&m);

    /* lock and unlock the mutex with nobody on it's wait queue */
    kmutex_lock(&m);
    kmutex_unlock(&m);

    int status;
    do_waitpid(kmutex_proc->p_pid, 0, &status);

    dbg(DBG_TESTPASS, "normal kmutex tests passed!\n");
}
Esempio n. 6
0
static void test_proc_kill_all(){
    dbg(DBG_TEST, "testing proc_kill_all when called from init proc\n");
    test_proc_kill_all_func(NULL, NULL);

    dbg(DBG_TEST, "testing proc_kill_all when called from a different proc\n");

    proc_t *test_proc = proc_create("proc_kill_all_func caller");
    kthread_t *test_thread = kthread_create(test_proc, test_proc_kill_all_func, 
                                       NULL, NULL);

    sched_make_runnable(test_thread);

    int status;
    pid_t retpid = do_waitpid(test_proc->p_pid, 0, &status);
    KASSERT(retpid == test_proc->p_pid);

    int i;
    for (i = 0; i < NUM_PROCS; i++){
        pid_t retval = do_waitpid(-1, 0, &status);
        
        /* make sure we actually were able to wait on this pid,
         * meaning that it was properly killed in proc_kill_all
         */
        KASSERT(retval > 0);
    }

    dbg(DBG_TESTPASS, "all proc_kill_all tests passed!\n");
}
Esempio n. 7
0
static void simple_read(rw_args_t read_args){
    proc_t *rp = proc_create("ata_read_proc");
    kthread_t *rt = kthread_create(rp, read_func, 0, (void *) &read_args);
    sched_make_runnable(rt);

    int status2;
    do_waitpid(rp->p_pid, 0, &status2);
}
Esempio n. 8
0
static void simple_write(rw_args_t write_args){
    proc_t *wp = proc_create("ata_write_proc");
    kthread_t *wt = kthread_create(wp, write_func, 0, (void *) &write_args);
    sched_make_runnable(wt);

    int status;
    do_waitpid(wp->p_pid, 0, &status);
}
Esempio n. 9
0
void *init_child9(int arg1,void *arg2) 
{
if(curtest == TEST_3){
 while(curthr->kt_cancelled != 1){
 sched_make_runnable(curthr);
 sched_switch(); }}
return NULL;
}
Esempio n. 10
0
/*
 * A Thread function that exhibits a race condition on the race global.  It
 * loads increments and stores race, context switching between each line of C.
 */
void *racer_test(int arg1, void *arg2) {
    int local;

    sched_make_runnable(curthr);
    sched_switch();
    local = race;
    sched_make_runnable(curthr);
    sched_switch();
    local++;
    sched_make_runnable(curthr);
    sched_switch();
    race = local;
    sched_make_runnable(curthr);
    sched_switch();
    do_exit(race);
    return NULL;
}
Esempio n. 11
0
/**
 * Once we're inside of idleproc_run(), we are executing in the context of the
 * first process-- a real context, so we can finally begin running
 * meaningful code.
 *
 * This is the body of process 0. It should initialize all that we didn't
 * already initialize in kmain(), launch the init process (initproc_run),
 * wait for the init process to exit, then halt the machine.
 *
 * @param arg1 the first argument (unused)
 * @param arg2 the second argument (unused)
 */
static void *
idleproc_run(int arg1, void *arg2)
{
        int status;
        pid_t child;
        dbg_print("Made it to idleproc_run\n");

        /* create init proc */
        kthread_t *initthr = initproc_create();

        init_call_all();
        GDB_CALL_HOOK(initialized);

        /* Create other kernel threads (in order) */

#ifdef __VFS__
        /* Once you have VFS remember to set the current working directory
         * of the idle and init processes */

        /* Here you need to make the null, zero, and tty devices using mknod */
        /* You can't do this until you have VFS, check the include/drivers/dev.h
         * file for macros with the device ID's you will need to pass to mknod */
#endif

        /* Finally, enable interrupts (we want to make sure interrupts
         * are enabled AFTER all drivers are initialized) */
        intr_enable();

        /* Run initproc */
        sched_make_runnable(initthr);
        /* Now wait for it */
        child = do_waitpid(-1, 0, &status);
        KASSERT(PID_INIT == child);

#ifdef __MTP__
        kthread_reapd_shutdown();
#endif


#ifdef __VFS__
        /* Shutdown the vfs: */
        dbg_print("weenix: vfs shutdown...\n");
        vput(curproc->p_cwd);
        if (vfs_shutdown())
                panic("vfs shutdown FAILED!!\n");

#endif

        /* Shutdown the pframe system */
#ifdef __S5FS__
        pframe_shutdown();
#endif

        dbg_print("\nweenix: halted cleanly!\n");
        GDB_CALL_HOOK(shutdown);
        hard_shutdown();
        return NULL;
}
Esempio n. 12
0
kthread_t *
sched_wakeup_on(ktqueue_t *q)
{
	kthread_t *t = NULL;
	
	t = ktqueue_dequeue(q);
	sched_make_runnable(t);
	return t;
}
Esempio n. 13
0
void
sched_broadcast_on(ktqueue_t *q)
{
        //NOT_YET_IMPLEMENTED("PROCS: sched_broadcast_on");
        while (!sched_queue_empty(q)) {
                kthread_t *thr = ktqueue_dequeue(q);
                sched_make_runnable(thr);
        }
}
Esempio n. 14
0
void
sched_broadcast_on(ktqueue_t *q)
{ 
	kthread_t *t;
	while (!sched_queue_empty(q)) {
		t = ktqueue_dequeue(q);
		sched_make_runnable(t);
	}
}
Esempio n. 15
0
/*
 * Create a process and a thread with the given name and calling teh given
 * function. Arg1 is passed to the function (arg2 is always NULL).  The thread
 * is immediately placed on the run queue.  A proc_thread_t is returned, giving
 * the caller a pointer to the new process and thread to coordinate tests.  NB,
 * the proc_thread_t is returned by value, so there are no stack problems.
 */
static proc_thread_t start_proc(char *name, kthread_func_t f, int arg1) {
    proc_thread_t pt;

    pt.p = proc_create(name);
    pt.t = kthread_create(pt.p, f, arg1, NULL);
    KASSERT(pt.p && pt.t && "Cannot create thread or process");
    sched_make_runnable(pt.t);
    return pt;
}
Esempio n. 16
0
/*
 * A Thread function that exhibits a race condition on the race global being
 * removed by a mutex.  It loads increments and stores race, context switching
 * between each line of C after acquiring mutex.  The mutex acquire cannot
 * be cancelled.
 */
void *mutex_uncancellable_test(int arg1, void *arg2) {
    int local;

    kmutex_lock(&mutex); 
    sched_make_runnable(curthr);
    sched_switch();
    local = race;
    sched_make_runnable(curthr);
    sched_switch();
    local++;
    sched_make_runnable(curthr);
    sched_switch();
    race = local;
    sched_make_runnable(curthr);
    sched_switch();
    kmutex_unlock(&mutex);
    do_exit(race);
    return NULL;
}
Esempio n. 17
0
/*
 * If the thread's sleep is cancellable, we set the kt_cancelled
 * flag and remove it from the queue. Otherwise, we just set the
 * kt_cancelled flag and leave the thread on the queue.
 *
 * Remember, unless the thread is in the KT_NO_STATE or KT_EXITED
 * state, it should be on some queue. Otherwise, it will never be run
 * again.
 */
void
sched_cancel(struct kthread *kthr)
{
        //NOT_YET_IMPLEMENTED("PROCS: sched_cancel");
        kthr->kt_cancelled = 1;
        if (kthr->kt_state == KT_SLEEP_CANCELLABLE) {
                ktqueue_remove(kthr->kt_wchan, kthr);
                sched_make_runnable(kthr);
        }
}
Esempio n. 18
0
int selftest(kshell_t *kshell, int argc, char **argv)
{

         proc_t* selftest_proc = proc_create("self_test");
         kthread_t *thread = kthread_create(selftest_proc,selftest_proc_run, 0, NULL);
         sched_make_runnable(thread);
         KASSERT(kshell != NULL);
         dbg(DBG_PRINT, "(GRADING2C)(kmain.c)(self_test_proc) self_test_proc() is invoked");
         return 0;
}
Esempio n. 19
0
/*
 * Create a process and a thread with the given name and calling teh given
 * function. Arg1 is passed to the function (arg2 is always NULL).  The thread
 * is immediately placed on the run queue.  A proc_thread_t is returned, giving
 * the caller a pointer to the new process and thread to coordinate tests.  NB,
 * the proc_thread_t is returned by value, so there are no stack problems.
 */
static void start_proc(proc_thread_t *ppt, char *name, kthread_func_t f, int arg1) {
    proc_thread_t pt;

    pt.p = proc_create(name);
    pt.t = kthread_create(pt.p, f, arg1, NULL);
    KASSERT(pt.p && pt.t && "Cannot create thread or process");
    sched_make_runnable(pt.t);
    if (ppt != NULL) {
        memcpy(ppt, &pt, sizeof(proc_thread_t));
    }
}
Esempio n. 20
0
kthread_t *
sched_wakeup_on(ktqueue_t *q)
{
        //NOT_YET_IMPLEMENTED("PROCS: sched_wakeup_on");
        if (sched_queue_empty(q)) {
                return NULL;
        }
        kthread_t *thr = ktqueue_dequeue(q);
        sched_make_runnable(thr);
        return thr;
}
Esempio n. 21
0
    int faber(kshell_t *kshell, int argc,char **argv)
      {
        int status;
        proc_t *faberproc = proc_create("faber");
        kthread_t *faberthread = kthread_create(faberproc,faber_thread_test,0,NULL);

        sched_make_runnable(faberthread);
        KASSERT(kshell != NULL);
        dbg(DBG_INIT,"(GRADING1C: Faber test is invoked)\n");
        while(do_waitpid(-1,0,&status)!=-ECHILD);
        return 0;
      }
Esempio n. 22
0
      int sunghan_deadlock(kshell_t *kshell, int argc,char **argv)
        {
          int status;
          proc_t *sunghan_deadlock_testproc = proc_create("sunghan_deadlock");
          kthread_t *sunghan_deadlock_testthread = kthread_create(sunghan_deadlock_testproc,sunghan_deadlock_test,0,NULL);

          sched_make_runnable(sunghan_deadlock_testthread);
          KASSERT(kshell != NULL);
          dbg(DBG_INIT,"(GRADING1D)\n");
          while(do_waitpid(-1,0,&status)!=-ECHILD);
          return 0;
        }
Esempio n. 23
0
void
sched_broadcast_on(ktqueue_t *q)
{
        /* Dequeue all from wait queue and make runnable */
        while (!sched_queue_empty(q)) {
          kthread_t *wake_thr = ktqueue_dequeue(q);
          wake_thr->kt_wchan = NULL;
          sched_make_runnable(wake_thr);
        }

        /* NOT_YET_IMPLEMENTED("PROCS: sched_broadcast_on"); */
}
Esempio n. 24
0
/*
 * A Thread function that exhibits a race condition on the race global being
 * removed by a mutex.  It loads increments and stores race, context switching
 * between each line of C after acquiring mutex.  The mutex acquire can
 * be cancelled, but will print an error message if the mutex acquire succeeds
 * - it expects to be cancelled.
 */
void *mutex_test_cancelme(int arg1, void *arg2) {
    int local;

    if ( kmutex_lock_cancellable(&mutex) ) 
	do_exit(0);
    dbg_print("Mutex not cancelled? %d", curproc->p_pid);
    sched_make_runnable(curthr);
    sched_switch();
    local = race;
    sched_make_runnable(curthr);
    sched_switch();
    local++;
    sched_make_runnable(curthr);
    sched_switch();
    race = local;
    sched_make_runnable(curthr);
    sched_switch();
    kmutex_unlock(&mutex);
    do_exit(race);
    return NULL;
}
Esempio n. 25
0
int sunghandeadlocktest(kshell_t *kshell, int argc, char **argv)
{
    int status;
    proc_t *temp_proc;
    kthread_t *temp_thread;
    temp_proc = proc_create("sunghan deadlock test");
    dbg(DBG_PRINT, "(GRADING1D 2): sunghan_deadlock_test() is invoked\n");
    temp_thread = kthread_create(temp_proc,sunghan_deadlock_test,0,NULL);
    sched_make_runnable(temp_thread); /*Make the thread runnable*/
    do_waitpid(temp_proc->p_pid,0,&status); /*waiting for the test to end*/
    return 0;
}
Esempio n. 26
0
  int do_deadlock(kshell_t *kshell, int argc, char **argv)
 {
     KASSERT(kshell != NULL);
     dbg(DBG_PRINT, "sunghan_deadlock_test() is invoked.\n");
     /*
      * Shouldn't call a test function directly.
      * It's best to invoke it in a separate kernel process.  
      */
     proc_t *newproc = proc_create("deadlock test");
     kthread_t *newthr = kthread_create(newproc, sunghan_deadlock_test, 0, NULL);
     sched_make_runnable(newthr);
     return 0;
 }
Esempio n. 27
0
void *
sunghan_deadlock_test(int arg1, void *arg2)
{
	int status;
	int proc_count = 0;
	pid_t proc_pid[3];

	int i;

	dbg(DBG_TEST, ">>> Start running sunghan_deadlock_test()...\n");

	mynode.length = 0;
	kmutex_init(&mynode.my_mutex);
	sched_queue_init(&mynode.my_queue);

	proc_t *p1 = proc_create("add_node");
        KASSERT(NULL != p1);
	kthread_t *thr1 = kthread_create(p1, add_my_node, 0, NULL);
        KASSERT(NULL != thr1);
	sched_make_runnable(thr1);
	proc_pid[proc_count++] = p1->p_pid;

	proc_t *p2 = proc_create("remove_node");
        KASSERT(NULL != p2);
	kthread_t *thr2 = kthread_create(p2, remove_my_node, 0, NULL);
        KASSERT(NULL != thr2);
	sched_make_runnable(thr2);
	proc_pid[proc_count++] = p2->p_pid;
	
	for (i=0; i<2; ++i) {
		do_waitpid(proc_pid[i], 0, &status);
	}
	sched_broadcast_on(&mynode.my_queue);

	dbg(DBG_TEST, "Shouldn't have gotten here in sunghan_deadlock_test().  Did NOT deadlock.\n");

        return NULL;
}
Esempio n. 28
0
/*
 * If the thread's sleep is cancellable, we set the kt_cancelled
 * flag and remove it from the queue. Otherwise, we just set the
 * kt_cancelled flag and leave the thread on the queue.
 *
 * Remember, unless the thread is in the KT_NO_STATE or KT_EXITED
 * state, it should be on some queue. Otherwise, it will never be run
 * again.
 */
void
sched_cancel(struct kthread *kthr)
{
        kthr->kt_cancelled = 1;

        /* If cancellable sleep, wake from queue it's waiting on */
        if (kthr->kt_state == KT_SLEEP_CANCELLABLE) {
          ktqueue_remove(kthr->kt_wchan, kthr);
          kthr->kt_wchan = NULL;
          sched_make_runnable(kthr);
        }

        /* NOT_YET_IMPLEMENTED("PROCS: sched_cancel"); */
}
Esempio n. 29
0
static void test_do_waitpid(waitpid_type_t type){
    proc_t *test_procs[NUM_PROCS];
    kthread_t *test_threads[NUM_PROCS];

    int i;
    for (i = 0; i < NUM_PROCS; i++){
        test_procs[i] = proc_create("test proc");
        test_threads[i] = kthread_create(test_procs[i], simple_function, i, NULL);
        sched_make_runnable(test_threads[i]);
    }

    int j;

    for (j = 0; j < NUM_PROCS; j++){

        if (type == ANY){
            int status;
            do_waitpid(-1, 0, &status);
        } else {
            int status;
            pid_t proc_pid = test_procs[j]->p_pid;

            pid_t waitpid_pid = do_waitpid(proc_pid, 0, &status);

            KASSERT(waitpid_pid == proc_pid);
        }
    }

    int k;
    for (k = 0; k < NUM_PROCS; k++){
        proc_t *p = test_procs[k];

        KASSERT(proc_lookup(p->p_pid) == NULL);

        /* make sure all children have been reparented */
        KASSERT(list_empty(&p->p_children));

        /* make sure that it is no longer in it's parent's
         * child list
         */
        KASSERT(!in_child_list(p));

        /* make sure it exited with the correct status */
        KASSERT(p->p_status == 0);

        KASSERT(p->p_state == PROC_DEAD);

        KASSERT(sched_queue_empty(&p->p_wait));
    }
}
Esempio n. 30
0
kthread_t *
sched_wakeup_on(ktqueue_t *q)
{
	/*----Kernel1:PROCS:sched_wakeup_on:Begins---*/
	KASSERT(q != NULL);
	kthread_t *thr = ktqueue_dequeue(q);
	if (thr != NULL)
	{
		KASSERT((thr->kt_state == KT_SLEEP) || (thr->kt_state == KT_SLEEP_CANCELLABLE));
		sched_make_runnable(thr);
	}
        return thr;
	/*----Ends----*/
}