static void readerthread(void *junk, unsigned long num) { (void)junk; if(num < 80) { //kprintf_n("Thread %lu trying to acquire read lock\n", num); random_yielder(4); rwlock_acquire_read(testrwlock); random_yielder(4); kprintf_n("Thread %lu: Reader val:%lu\n", num, testval1); for(int i=0; i<40000; i++); random_yielder(4); rwlock_release_read(testrwlock); random_yielder(4); //kprintf_n("Thread %lu released read lock\n", num); V(donesem); } else { //kprintf_n("Thread %lu trying to acquire write lock\n", num); random_yielder(4); rwlock_acquire_write(testrwlock); random_yielder(4); testval1++; kprintf_n("Thread %lu: Writer val:%lu\n", num, testval1); for(int i=0; i<40000; i++); random_yielder(4); rwlock_release_write(testrwlock); random_yielder(4); //kprintf_n("Thread %lu released write lock\n", num); V(donesem); } return; }
int rwtest5(int nargs, char **args) { (void)nargs; (void)args; kprintf_n("rwt5 unimplemented\n"); success(TEST161_FAIL, SECRET, "rwt5"); return 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; int status; int retval; unsigned tc; /* Create a process for the new program to run in. */ proc = proc_create_runprogram(args[0] /* name */); if (proc == NULL) { return ENOMEM; } tc = thread_count; 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; } result = sys_waitpid(proc->pid, &status, 0 , &retval); if (result ) { kprintf_n("sys_waitpid done with result %d for pid %d \n",result,proc->pid ); //return 0; } /* * The new process will be destroyed when the program exits... * once you write the code for handling that. */ // Wait for all threads to finish cleanup, otherwise khu be a bit behind, // especially once swapping is enabled. thread_wait_for_count(tc); 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; }
/* * Load program "progname" and start running it in usermode. * Does not return except on error. * * Calls vfs_open on progname and thus may destroy it. */ int runprogram(char *progname) { struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; int result; /** Initialize the file descriptors for console**/ if (curthread->t_fdtable[0] == NULL) { result = init_file_descriptor(); if (result ) { // file descriptors not initialized kprintf_n("init_file_descriptor failed"); return result; } } /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new process. */ KASSERT(proc_getas() == NULL); /* Create a new address space. */ as = as_create(); if (as == NULL) { vfs_close(v); return ENOMEM; } /* Switch to it and activate it. */ proc_setas(as); as_activate(); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* p_addrspace will go away when curproc is destroyed */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(as, &stackptr); if (result) { /* p_addrspace will go away when curproc is destroyed */ return result; } /* Warp to user mode. */ enter_new_process(0 /*argc*/, NULL /*userspace addr of argv*/, NULL /*userspace addr of environment*/, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }