void another_user(void){ fm_printf("This is thread %04d begin!\r\n", running_thread()->tid); int i = 0; for(; i < TEST_TASK_NUM - 1; ++i){ fm_thread_wake(&thread[i]); } fm_printf("This is thread %04d end!\r\n", running_thread()->tid); }
//等待子进程调用exit,将子进程的退出状态保存到status指向的变量 //成功则返回子进程的pid,失败返回-1 pid_t sys_wait(int32_t* status){ struct task_struct* parent_thread = running_thread(); while(1){ //优先处理已经是挂起状态的任务 struct list_elem* child_elem = list_traversal(&thread_all_list,find_hanging_child,parent_thread->pid); //若有挂起的任务 if(child_elem != NULL){ struct task_struct* child_thread = elem2entry(struct task_struct,all_list_tag,child_elem); *status = child_thread->exit_status; //thread_exit之后,pcb会被回收,因此提前获取pid uint16_t child_pid = child_thread->pid; //从就绪队列和全部队列中删除进程表项 thread_exit(child_thread,false); //传入false,使thread_exit调用后回到此处 //进程表项是进程或线程的最后保留的资源,至此该进程彻底消失了 return child_pid; } //判断是否有子进程 child_elem = list_traversal(&thread_all_list,find_child,parent_thread->pid); if(child_elem == NULL){ //若没有子进程则出错返回 return -1; }else{ //若子进程还未运行完,即还未调用exit,则将自己挂起,直到子进程在执行exit时将自己唤醒 thread_block(TASK_WAITING); } } }
/* 在pf表示的虚拟内存池中申请pg_cnt个虚拟页, * 成功则返回虚拟页的起始地址, 失败则返回NULL */ static void* vaddr_get(enum pool_flags pf, uint32_t pg_cnt) { int vaddr_start = 0, bit_idx_start = -1; uint32_t cnt = 0; if (pf == PF_KERNEL) { // 内核内存池 bit_idx_start = bitmap_scan(&kernel_vaddr.vaddr_bitmap, pg_cnt); if (bit_idx_start == -1) { return NULL; } while(cnt < pg_cnt) { bitmap_set(&kernel_vaddr.vaddr_bitmap, bit_idx_start + cnt++, 1); } vaddr_start = kernel_vaddr.vaddr_start + bit_idx_start * PG_SIZE; } else { // 用户内存池 struct task_struct* cur = running_thread(); bit_idx_start = bitmap_scan(&cur->userprog_vaddr.vaddr_bitmap, pg_cnt); if (bit_idx_start == -1) { return NULL; } while(cnt < pg_cnt) { bitmap_set(&cur->userprog_vaddr.vaddr_bitmap, bit_idx_start + cnt++, 1); } vaddr_start = cur->userprog_vaddr.vaddr_start + bit_idx_start * PG_SIZE; /* (0xc0000000 - PG_SIZE)做为用户3级栈已经在start_process被分配 */ ASSERT((uint32_t)vaddr_start < (0xc0000000 - PG_SIZE)); } return (void*)vaddr_start; }
/* Initializes the threading system by transforming the code that's currently running into a thread. This can't work in general and it is possible in this case only because loader.S was careful to put the bottom of the stack at a page boundary. Also initializes the run queue and the tid lock. After calling this function, be sure to initialize the page allocator before trying to create any threads with thread_create(). It is not safe to call thread_current() until this function finishes. */ void thread_init (void) { ASSERT (intr_get_level () == INTR_OFF); lock_init (&tid_lock); if(thread_mlfqs) { load_avg = 0; f = 1 << q; int i; for(i=0;i<PRI_MAX+1;i++) list_init (&ready_mlfqs[i]); } else { list_init (&ready_list); } list_init (&all_list); list_init (&waiting_list); /* Set up a thread structure for the running thread. */ initial_thread = running_thread (); init_thread (initial_thread, "main", PRI_DEFAULT); initial_thread->status = THREAD_RUNNING; initial_thread->tid = allocate_tid (); }
/* 关闭文件描述符fd指向的文件,成功返回0,否则返回-1 */ int32_t sys_close(int32_t fd) { int32_t ret = -1; // 返回值默认为-1,即失败 if (fd > 2) { uint32_t _fd = fd_local2global(fd); ret = file_close(&file_table[_fd]); running_thread()->fd_table[fd] = -1; // 使该文件描述符位可用 } return ret; }
/* 根据i结点号返回相应的i结点 */ struct inode* inode_open(struct partition* part, uint32_t inode_no) { /* 先在已打开inode链表中找inode,此链表是为提速创建的缓冲区 */ struct list_elem* elem = part->open_inodes.head.next; struct inode* inode_found; while (elem != &part->open_inodes.tail) { inode_found = elem2entry(struct inode, inode_tag, elem); if (inode_found->i_no == inode_no) { inode_found->i_open_cnts++; return inode_found; } elem = elem->next; } /*由于open_inodes链表中找不到,下面从硬盘上读入此inode并加入到此链表 */ struct inode_position inode_pos; /* inode位置信息会存入inode_pos, 包括inode所在扇区地址和扇区内的字节偏移量 */ inode_locate(part, inode_no, &inode_pos); /* 为使通过sys_malloc创建的新inode被所有任务共享, * 需要将inode置于内核空间,故需要临时 * 将cur_pbc->pgdir置为NULL */ struct task_struct* cur = running_thread(); uint32_t* cur_pagedir_bak = cur->pgdir; cur->pgdir = NULL; /* 以上三行代码完成后下面分配的内存将位于内核区 */ inode_found = (struct inode*)sys_malloc(sizeof(struct inode)); /* 恢复pgdir */ cur->pgdir = cur_pagedir_bak; char* inode_buf; if (inode_pos.two_sec) { // 考虑跨扇区的情况 inode_buf = (char*)sys_malloc(1024); /* i结点表是被partition_format函数连续写入扇区的, * 所以下面可以连续读出来 */ ide_read(part->my_disk, inode_pos.sec_lba, inode_buf, 2); } else { // 否则,所查找的inode未跨扇区,一个扇区大小的缓冲区足够 inode_buf = (char*)sys_malloc(512); ide_read(part->my_disk, inode_pos.sec_lba, inode_buf, 1); } memcpy(inode_found, inode_buf + inode_pos.off_size, sizeof(struct inode)); /* 因为一会很可能要用到此inode,故将其插入到队首便于提前检索到 */ list_push(&part->open_inodes, &inode_found->inode_tag); inode_found->i_open_cnts = 1; sys_free(inode_buf); return inode_found; }
void task_4(void){ int k = 4000, i = 100000; fm_mutex_lock(&mutex); fm_assert(test_point++ == 0, "TP0 ERROR\r\n"); while(k--){ i = 10000; while(i--){ __asm("NOP"); } } fm_assert(running_thread()->priority == 0, "PRIORITY ERROR(!=0)\r\n"); fm_mutex_unlock(&mutex); fm_assert(running_thread()->priority == 3, "PRIORITY ERROR(!=3)\r\n"); fm_sem_release(&sem); fm_sem_release(&sem); fm_sem_release(&sem); fm_sem_release(&sem); fm_sem_release(&sem); fm_sem_release(&sem); fm_assert(sem->sem.count == sem->sem.max_count, "CNT ERROR\r\n"); fm_thread_resume(&thread[0]); fm_puts("Test finish!!!"); }
/* Returns the running thread. This is running_thread() plus a couple of sanity checks. See the big comment at the top of thread.h for details. */ struct thread * thread_current (void) { struct thread *t = running_thread (); /* Make sure T is really a thread. If either of these assertions fire, then your thread may have overflowed its stack. Each thread has less than 4 kB of stack, so a few big automatic arrays or moderate recursion can cause stack overflow. */ ASSERT (is_thread (t)); ASSERT (t->status == THREAD_RUNNING); return t; }
/* 关闭inode或减少inode的打开数 */ void inode_close(struct inode* inode) { /* 若没有进程再打开此文件,将此inode去掉并释放空间 */ enum intr_status old_status = intr_disable(); if (--inode->i_open_cnts == 0) { list_remove(&inode->inode_tag); // 将I结点从part->open_inodes中去掉 /* inode_open时为实现inode被所有进程共享,已经在sys_malloc为inode分配了内核空间 */ struct task_struct* cur = running_thread(); uint32_t* cur_pagedir_bak = cur->pgdir; cur->pgdir = NULL; sys_free(inode); // 释放inode的内核空间 cur->pgdir = cur_pagedir_bak; } intr_set_status(old_status); }
/* 将全局描述符下标安装到进程或线程自己的文件描述符数组fd_table中, * 成功返回下标,失败返回-1 */ int32_t pcb_fd_install(int32_t globa_fd_idx) { struct task_struct* cur = running_thread(); uint8_t local_fd_idx = 3; // 跨过stdin,stdout,stderr while (local_fd_idx < MAX_FILES_OPEN_PER_PROC) { if (cur->fd_table[local_fd_idx] == -1) { // -1表示free_slot,可用 cur->fd_table[local_fd_idx] = globa_fd_idx; break; } local_fd_idx++; } if (local_fd_idx == MAX_FILES_OPEN_PER_PROC) { printk("exceed max open files_per_proc\n"); return -1; } return local_fd_idx; }
//fork子进程,内核线程不可直接调用 pid_t sys_fork(void){ struct task_struct* parent_thread = running_thread(); struct task_struct* child_thread = get_kernel_pages(1); //为子进程创建pcb(task_struct结构) if(child_thread == NULL){ return -1; } ASSERT(INTR_OFF == intr_get_status() && parent_thread->pgdir != NULL); if(copy_process(child_thread,parent_thread) == -1){ return -1; } //添加到就绪线程队列和所有线程队列,子进程由调度器安排运行 ASSERT(!elem_find(&thread_ready_list,&child_thread->general_tag)); list_append(&thread_ready_list,&child_thread->general_tag); ASSERT(!elem_find(&thread_all_list,&child_thread->all_list_tag)); list_append(&thread_all_list,&child_thread->all_list_tag); return child_thread->pid; }
//子进程用来结束自己时调用 void sys_exit(int32_t status){ struct task_struct* child_thread = running_thread(); child_thread->exit_status = status; if(child_thread->parent_pid == -1){ PANIC("sys_exit: child_thread->parent_pid is -1\n"); } //将进程child_thread的所有子进程都过继给init list_traversal(&thread_all_list,init_adopt_a_child,child_thread->pid); //回收进程child_thread的资源 release_prog_resource(child_thread); //如果父进程正在等待子进程退出,将父进程唤醒 struct task_struct* parent_thread = pid2thread(child_thread->parent_pid); if(parent_thread->status == TASK_WAITING){ thread_unblock(parent_thread); } //将自己挂起,等待父进程获取其status,并回收其pcb thread_block(TASK_HANGING); }
/* 将文件描述符转化为文件表的下标 */ static uint32_t fd_local2global(uint32_t local_fd) { struct task_struct* cur = running_thread(); int32_t global_fd = cur->fd_table[local_fd]; ASSERT(global_fd >= 0 && global_fd < MAX_FILE_OPEN); return (uint32_t)global_fd; }
void user(void){ fm_printf("This is thread %04d begin!\r\n", running_thread()->tid); fm_printf("This is thread %04d end!\r\n", running_thread()->tid); }
/* 返回当前任务的pid */ uint32_t sys_getpid(void) { return running_thread()->pid; }
int main(int, char*[]) { dummy_async_handler async_handler; #define ASYNC_SERVER_TEST_CONFIG \ options.address("127.0.0.1").port("8007").reuse_address(true) #define ASYNC_SERVER_SLEEP_TIME std::chrono::milliseconds(100) // stop from main thread { BOOST_NETWORK_MESSAGE("TEST: stop without running"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); server_instance.stop(); } // run-stop from main thread { BOOST_NETWORK_MESSAGE("TEST: stop from main thread"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); std::thread running_thread([&server_instance] () { server_instance.run(); }); std::this_thread::sleep_for(ASYNC_SERVER_SLEEP_TIME); server_instance.stop(); running_thread.join(); } // run-stop from another thread { BOOST_NETWORK_MESSAGE("TEST: stop from another thread"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); std::thread running_thread([&server_instance] () { server_instance.run(); }); std::this_thread::sleep_for(ASYNC_SERVER_SLEEP_TIME); std::thread stopping_thread([&server_instance] () { server_instance.stop(); }); std::this_thread::sleep_for(ASYNC_SERVER_SLEEP_TIME); stopping_thread.join(); running_thread.join(); } // run-stop-run-stop from another thread { BOOST_NETWORK_MESSAGE("TEST: run-stop-run-stop from another thread"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); std::thread running_thread([&server_instance] () { server_instance.run(); }); std::this_thread::sleep_for(ASYNC_SERVER_SLEEP_TIME); std::thread stopping_thread([&server_instance] () { server_instance.stop(); }); std::this_thread::sleep_for(ASYNC_SERVER_SLEEP_TIME); std::thread second_running_thread([&server_instance] () { server_instance.run(); }); std::this_thread::sleep_for(ASYNC_SERVER_SLEEP_TIME); std::thread second_stopping_thread([&server_instance] () { server_instance.stop(); }); std::this_thread::sleep_for(ASYNC_SERVER_SLEEP_TIME); stopping_thread.join(); running_thread.join(); second_stopping_thread.join(); second_running_thread.join(); } // run-run-stop from another thread { BOOST_NETWORK_MESSAGE("TEST: run-run-stop from another thread"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); std::thread running_thread([&server_instance] () { server_instance.run(); }); std::this_thread::sleep_for(ASYNC_SERVER_SLEEP_TIME); std::thread second_running_thread([&server_instance] () { server_instance.run(); }); std::this_thread::sleep_for(ASYNC_SERVER_SLEEP_TIME); std::thread stopping_thread([&server_instance] () { server_instance.stop(); }); std::this_thread::sleep_for(ASYNC_SERVER_SLEEP_TIME); stopping_thread.join(); running_thread.join(); second_running_thread.join(); } // run-stop-stop from another thread { BOOST_NETWORK_MESSAGE("TEST: run-stop-stop from another thread"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); std::thread running_thread([&server_instance] () { server_instance.run(); }); std::this_thread::sleep_for(ASYNC_SERVER_SLEEP_TIME); std::thread stopping_thread([&server_instance] () { server_instance.stop(); }); std::this_thread::sleep_for(ASYNC_SERVER_SLEEP_TIME); std::thread second_stopping_thread([&server_instance] () { server_instance.stop(); }); std::this_thread::sleep_for(ASYNC_SERVER_SLEEP_TIME); stopping_thread.join(); second_stopping_thread.join(); running_thread.join(); } #undef ASYNC_SERVER_TEST_CONFIG return 0; }
int main(int argc, char * argv[]) { dummy_async_handler async_handler; #define ASYNC_SERVER_TEST_CONFIG \ options.address("127.0.0.1") \ .port("8007") \ .reuse_address(true) #define ASYNC_SERVER_SLEEP_TIME \ boost::posix_time::milliseconds(100) // stop from main thread { BOOST_NETWORK_MESSAGE("TEST: stop without running"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); server_instance.stop(); } // run-stop from main thread { BOOST_NETWORK_MESSAGE("TEST: stop from main thread"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); server_instance.stop(); running_thread.join(); } // run-stop from another thread { BOOST_NETWORK_MESSAGE("TEST: stop from another thread"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); stopping_thread.join(); running_thread.join(); } // run-stop-run-stop from another thread { BOOST_NETWORK_MESSAGE("TEST: run-stop-run-stop from another thread"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); boost::thread second_running_thread(boost::bind(&async_server::run, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); boost::thread second_stopping_thread(boost::bind(&async_server::stop, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); stopping_thread.join(); running_thread.join(); second_stopping_thread.join(); second_running_thread.join(); } // run-run-stop from another thread { BOOST_NETWORK_MESSAGE("TEST: run-run-stop from another thread"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); boost::thread second_running_thread(boost::bind(&async_server::run, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); stopping_thread.join(); running_thread.join(); second_running_thread.join(); } // run-stop-stop from another thread { BOOST_NETWORK_MESSAGE("TEST: run-stop-stop from another thread"); async_server::options options(async_handler); async_server server_instance(ASYNC_SERVER_TEST_CONFIG); boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); boost::thread second_stopping_thread(boost::bind(&async_server::stop, &server_instance)); boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); stopping_thread.join(); second_stopping_thread.join(); running_thread.join(); } #undef ASYNC_SERVER_TEST_CONFIG return 0; }