⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 manager.c

📁 Newlib 嵌入式 C库 标准实现代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	      new_thread->p_eventbuf.eventnum = TD_CREATE;	      __pthread_last_event = new_thread;	      /* We have to set the PID here since the callback function		 in the debug library will need it and we cannot guarantee		 the child got scheduled before the debugger.  */	      new_thread->p_pid = pid;	      /* Now call the function which signals the event.  */	      __linuxthreads_create_event ();	      /* Now restart the thread.  */	      __pthread_unlock(new_thread->p_lock);	    }	}    }  if (pid == 0)    {#ifdef NEED_SEPARATE_REGISTER_STACK      pid = __clone2(pthread_start_thread,		     (void **)new_thread_bottom,                     (char *)new_thread - new_thread_bottom,		     CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |		     __pthread_sig_cancel, new_thread);#elif _STACK_GROWS_UP      pid = __clone(pthread_start_thread, (void **) new_thread_bottom,		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |		    __pthread_sig_cancel, new_thread);#else      pid = __clone(pthread_start_thread, (void **) new_thread,		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |		    __pthread_sig_cancel, new_thread);#endif /* !NEED_SEPARATE_REGISTER_STACK */    }  /* Check if cloning succeeded */  if (pid == -1) {    /* Free the stack if we allocated it */    if (attr == NULL || !attr->__stackaddr_set)      {#ifdef NEED_SEPARATE_REGISTER_STACK	size_t stacksize = ((char *)(new_thread->p_guardaddr)			    - new_thread_bottom);	munmap((caddr_t)new_thread_bottom,	       2 * stacksize + new_thread->p_guardsize);#elif _STACK_GROWS_UP	size_t stacksize = guardaddr - (char *)new_thread;	munmap(new_thread, stacksize + guardsize);#else	size_t stacksize = (char *)(new_thread+1) - new_thread_bottom;	munmap(new_thread_bottom - guardsize, guardsize + stacksize);#endif      }    __pthread_handles[sseg].h_descr = NULL;    __pthread_handles[sseg].h_bottom = NULL;    __pthread_handles_num--;    return errno;  }  /* Insert new thread in doubly linked list of active threads */  new_thread->p_prevlive = __pthread_main_thread;  new_thread->p_nextlive = __pthread_main_thread->p_nextlive;  __pthread_main_thread->p_nextlive->p_prevlive = new_thread;  __pthread_main_thread->p_nextlive = new_thread;  /* Set pid field of the new thread, in case we get there before the     child starts. */  new_thread->p_pid = pid;  return 0;}/* Try to free the resources of a thread when requested by pthread_join   or pthread_detach on a terminated thread. */static void pthread_free(pthread_descr th){  pthread_handle handle;  pthread_readlock_info *iter, *next;  ASSERT(th->p_exited);  /* Make the handle invalid */  handle =  thread_handle(th->p_tid);  __pthread_lock(&handle->h_lock, NULL);  handle->h_descr = NULL;  handle->h_bottom = (char *)(-1L);  __pthread_unlock(&handle->h_lock);#ifdef FREE_THREAD  FREE_THREAD(th, th->p_nr);#endif  /* One fewer threads in __pthread_handles */  __pthread_handles_num--;  /* Destroy read lock list, and list of free read lock structures.     If the former is not empty, it means the thread exited while     holding read locks! */  for (iter = th->p_readlock_list; iter != NULL; iter = next)    {      next = iter->pr_next;      free(iter);    }  for (iter = th->p_readlock_free; iter != NULL; iter = next)    {      next = iter->pr_next;      free(iter);    }  /* If initial thread, nothing to free */  if (!th->p_userstack)    {      size_t guardsize = th->p_guardsize;      /* Free the stack and thread descriptor area */      char *guardaddr = th->p_guardaddr;#ifdef _STACK_GROWS_UP      size_t stacksize = guardaddr - (char *)th;      guardaddr = (char *)th;#else      /* Guardaddr is always set, even if guardsize is 0.  This allows	 us to compute everything else.  */      size_t stacksize = (char *)(th+1) - guardaddr - guardsize;#ifdef NEED_SEPARATE_REGISTER_STACK      /* Take account of the register stack, which is below guardaddr.  */      guardaddr -= stacksize;      stacksize *= 2;#endif#endif      /* Unmap the stack.  */      munmap(guardaddr, stacksize + guardsize);    }}/* Handle threads that have exited */static void pthread_exited(pid_t pid){  pthread_descr th;  int detached;  /* Find thread with that pid */  for (th = __pthread_main_thread->p_nextlive;       th != __pthread_main_thread;       th = th->p_nextlive) {    if (th->p_pid == pid) {      /* Remove thread from list of active threads */      th->p_nextlive->p_prevlive = th->p_prevlive;      th->p_prevlive->p_nextlive = th->p_nextlive;      /* Mark thread as exited, and if detached, free its resources */      __pthread_lock(th->p_lock, NULL);      th->p_exited = 1;      /* If we have to signal this event do it now.  */      if (th->p_report_events)	{	  /* See whether TD_REAP is in any of the mask.  */	  int idx = __td_eventword (TD_REAP);	  uint32_t mask = __td_eventmask (TD_REAP);	  if ((mask & (__pthread_threads_events.event_bits[idx]		       | th->p_eventbuf.eventmask.event_bits[idx])) != 0)	    {	      /* Yep, we have to signal the reapage.  */	      th->p_eventbuf.eventnum = TD_REAP;	      th->p_eventbuf.eventdata = th;	      __pthread_last_event = th;	      /* Now call the function to signal the event.  */	      __linuxthreads_reap_event();	    }	}      detached = th->p_detached;      __pthread_unlock(th->p_lock);      if (detached)	pthread_free(th);      break;    }  }  /* If all threads have exited and the main thread is pending on a     pthread_exit, wake up the main thread and terminate ourselves. */  if (main_thread_exiting &&      __pthread_main_thread->p_nextlive == __pthread_main_thread) {    restart(__pthread_main_thread);    /* Same logic as REQ_MAIN_THREAD_EXIT. */  }}static void pthread_reap_children(void){  pid_t pid;  int status;  while ((pid = __libc___waitpid(-1, &status, WNOHANG | __WCLONE)) > 0) {    pthread_exited(pid);    if (WIFSIGNALED(status)) {      /* If a thread died due to a signal, send the same signal to         all other threads, including the main thread. */      pthread_kill_all_threads(WTERMSIG(status), 1);      _exit(0);    }  }}/* Try to free the resources of a thread when requested by pthread_join   or pthread_detach on a terminated thread. */static void pthread_handle_free(pthread_t th_id){  pthread_handle handle = thread_handle(th_id);  pthread_descr th;  __pthread_lock(&handle->h_lock, NULL);  if (nonexisting_handle(handle, th_id)) {    /* pthread_reap_children has deallocated the thread already,       nothing needs to be done */    __pthread_unlock(&handle->h_lock);    return;  }  th = handle->h_descr;  if (th->p_exited) {    __pthread_unlock(&handle->h_lock);    pthread_free(th);  } else {    /* The Unix process of the thread is still running.       Mark the thread as detached so that the thread manager will       deallocate its resources when the Unix process exits. */    th->p_detached = 1;    __pthread_unlock(&handle->h_lock);  }}/* Send a signal to all running threads */static void pthread_kill_all_threads(int sig, int main_thread_also){  pthread_descr th;  for (th = __pthread_main_thread->p_nextlive;       th != __pthread_main_thread;       th = th->p_nextlive) {    kill(th->p_pid, sig);  }  if (main_thread_also) {    kill(__pthread_main_thread->p_pid, sig);  }}static void pthread_for_each_thread(void *arg,     void (*fn)(void *, pthread_descr)){  pthread_descr th;  for (th = __pthread_main_thread->p_nextlive;       th != __pthread_main_thread;       th = th->p_nextlive) {    fn(arg, th);  }  fn(arg, __pthread_main_thread);}/* Process-wide exit() */static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode){  pthread_descr th;  __pthread_exit_requested = 1;  __pthread_exit_code = exitcode;  /* A forced asynchronous cancellation follows.  Make sure we won't     get stuck later in the main thread with a system lock being held     by one of the cancelled threads.  Ideally one would use the same     code as in pthread_atfork(), but we can't distinguish system and     user handlers there.  */  __flockfilelist();  /* Send the CANCEL signal to all running threads, including the main     thread, but excluding the thread from which the exit request originated     (that thread must complete the exit, e.g. calling atexit functions     and flushing stdio buffers). */  for (th = issuing_thread->p_nextlive;       th != issuing_thread;       th = th->p_nextlive) {    kill(th->p_pid, __pthread_sig_cancel);  }  /* Now, wait for all these threads, so that they don't become zombies     and their times are properly added to the thread manager's times. */  for (th = issuing_thread->p_nextlive;       th != issuing_thread;       th = th->p_nextlive) {    __waitpid(th->p_pid, NULL, __WCLONE);  }  __fresetlockfiles();  restart(issuing_thread);  _exit(0);}/* Handler for __pthread_sig_cancel in thread manager thread */void __pthread_manager_sighandler(int sig){  int kick_manager = terminated_children == 0 && main_thread_exiting;  terminated_children = 1;  /* If the main thread is terminating, kick the thread manager loop     each time some threads terminate. This eliminates a two second     shutdown delay caused by the thread manager sleeping in the     call to __poll(). Instead, the thread manager is kicked into     action, reaps the outstanding threads and resumes the main thread     so that it can complete the shutdown. */  if (kick_manager) {    struct pthread_request request;    request.req_thread = 0;    request.req_kind = REQ_KICK;    TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request,				    (char *) &request, sizeof(request)));  }}/* Adjust priority of thread manager so that it always run at a priority   higher than all threads */void __pthread_manager_adjust_prio(int thread_prio){  struct sched_param param;  if (thread_prio <= __pthread_manager_thread.p_priority) return;  param.sched_priority =    thread_prio < __sched_get_priority_max(SCHED_FIFO)    ? thread_prio + 1 : thread_prio;  __sched_setscheduler(__pthread_manager_thread.p_pid, SCHED_FIFO, &param);  __pthread_manager_thread.p_priority = thread_prio;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -