Beispiel #1
0
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);
}
Beispiel #2
0
//等待子进程调用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);
		}
	}
}
Beispiel #3
0
/* 在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;
}
Beispiel #4
0
/* 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 ();
}
Beispiel #5
0
/* 关闭文件描述符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;
}
Beispiel #6
0
/* 根据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;
}
Beispiel #7
0
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!!!");
}
Beispiel #8
0
/* 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;
}
Beispiel #9
0
/* 关闭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);
}
Beispiel #10
0
/* 将全局描述符下标安装到进程或线程自己的文件描述符数组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;
}
Beispiel #11
0
//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;
}
Beispiel #12
0
//子进程用来结束自己时调用
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);
}
Beispiel #13
0
/* 将文件描述符转化为文件表的下标 */
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;
} 
Beispiel #14
0
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);
}
Beispiel #15
0
/* 返回当前任务的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;
}