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

📄 pthread.c

📁 Newlib 嵌入式 C库 标准实现代码
💻 C
📖 第 1 页 / 共 3 页
字号:
      mask with e.g. sigsetjmp before creating the first thread);   - a regular function called from pthread_create when needed. */static void pthread_initialize(void) __attribute__((constructor));#ifndef HAVE_Z_NODELETEextern void *__dso_handle __attribute__ ((weak));#endif/* Do some minimal initialization which has to be done during the   startup of the C library.  */void__pthread_initialize_minimal(void){  /* If we have special thread_self processing, initialize that for the     main thread now.  */#ifdef INIT_THREAD_SELF  INIT_THREAD_SELF(&__pthread_initial_thread, 0);#endif#if HP_TIMING_AVAIL  __pthread_initial_thread.p_cpuclock_offset = _dl_cpuclock_offset;#endif}void__pthread_init_max_stacksize(void){  struct rlimit limit;  size_t max_stack;  getrlimit(RLIMIT_STACK, &limit);#ifdef FLOATING_STACKS  if (limit.rlim_cur == RLIM_INFINITY)    limit.rlim_cur = ARCH_STACK_MAX_SIZE;# ifdef NEED_SEPARATE_REGISTER_STACK  max_stack = limit.rlim_cur / 2;# else  max_stack = limit.rlim_cur;# endif#else  /* Play with the stack size limit to make sure that no stack ever grows     beyond STACK_SIZE minus one page (to act as a guard page). */# ifdef NEED_SEPARATE_REGISTER_STACK  /* STACK_SIZE bytes hold both the main stack and register backing     store. The rlimit value applies to each individually.  */  max_stack = STACK_SIZE/2 - __getpagesize ();# else  max_stack = STACK_SIZE - __getpagesize();# endif  if (limit.rlim_cur > max_stack) {    limit.rlim_cur = max_stack;    __libc_setrlimit(RLIMIT_STACK, &limit);  }#endif  __pthread_max_stacksize = max_stack;}static void pthread_initialize(void){  struct sigaction sa;  sigset_t mask;  /* If already done (e.g. by a constructor called earlier!), bail out */  if (__pthread_initial_thread_bos != NULL) return;#ifdef TEST_FOR_COMPARE_AND_SWAP  /* Test if compare-and-swap is available */  __pthread_has_cas = compare_and_swap_is_available();#endif#ifdef FLOATING_STACKS  /* We don't need to know the bottom of the stack.  Give the pointer some     value to signal that initialization happened.  */  __pthread_initial_thread_bos = (void *) -1l;#else  /* Determine stack size limits .  */  __pthread_init_max_stacksize ();# ifdef _STACK_GROWS_UP  /* The initial thread already has all the stack it needs */  __pthread_initial_thread_bos = (char *)    ((long)CURRENT_STACK_FRAME &~ (STACK_SIZE - 1));# else  /* For the initial stack, reserve at least STACK_SIZE bytes of stack     below the current stack address, and align that on a     STACK_SIZE boundary. */  __pthread_initial_thread_bos =    (char *)(((long)CURRENT_STACK_FRAME - 2 * STACK_SIZE) & ~(STACK_SIZE - 1));# endif#endif  /* Update the descriptor for the initial thread. */  __pthread_initial_thread.p_pid = __getpid();  /* Likewise for the resolver state _res.  */  __pthread_initial_thread.p_resp = &_res;#ifdef __SIGRTMIN  /* Initialize real-time signals. */  init_rtsigs ();#endif  /* Setup signal handlers for the initial thread.     Since signal handlers are shared between threads, these settings     will be inherited by all other threads. */  sa.sa_handler = pthread_handle_sigrestart;  sigemptyset(&sa.sa_mask);  sa.sa_flags = 0;  __libc_sigaction(__pthread_sig_restart, &sa, NULL);  sa.sa_handler = pthread_handle_sigcancel;  // sa.sa_flags = 0;  __libc_sigaction(__pthread_sig_cancel, &sa, NULL);  if (__pthread_sig_debug > 0) {    sa.sa_handler = pthread_handle_sigdebug;    sigemptyset(&sa.sa_mask);    // sa.sa_flags = 0;    __libc_sigaction(__pthread_sig_debug, &sa, NULL);  }  /* Initially, block __pthread_sig_restart. Will be unblocked on demand. */  sigemptyset(&mask);  sigaddset(&mask, __pthread_sig_restart);  sigprocmask(SIG_BLOCK, &mask, NULL);  /* Register an exit function to kill all other threads. */  /* Do it early so that user-registered atexit functions are called     before pthread_*exit_process. */#ifndef HAVE_Z_NODELETE  if (__builtin_expect (&__dso_handle != NULL, 1))    __cxa_atexit ((void (*) (void *)) pthread_atexit_process, NULL,		  __dso_handle);  else#endif    on_exit (pthread_onexit_process, NULL);  /* How many processors.  */  __pthread_smp_kernel = is_smp_system ();}void __pthread_initialize(void){  pthread_initialize();}int __pthread_initialize_manager(void){  int manager_pipe[2];  int pid;  struct pthread_request request;#ifndef HAVE_Z_NODELETE  if (__builtin_expect (&__dso_handle != NULL, 1))    __cxa_atexit ((void (*) (void *)) pthread_atexit_retcode, NULL,		  __dso_handle);#endif  if (__pthread_max_stacksize == 0)    __pthread_init_max_stacksize ();  /* If basic initialization not done yet (e.g. we're called from a     constructor run before our constructor), do it now */  if (__pthread_initial_thread_bos == NULL) pthread_initialize();  /* Setup stack for thread manager */  __pthread_manager_thread_bos = malloc(THREAD_MANAGER_STACK_SIZE);  if (__pthread_manager_thread_bos == NULL) return -1;  __pthread_manager_thread_tos =    __pthread_manager_thread_bos + THREAD_MANAGER_STACK_SIZE;  /* Setup pipe to communicate with thread manager */  if (__libc_pipe(manager_pipe) == -1) {    free(__pthread_manager_thread_bos);    return -1;  }  /* Start the thread manager */  pid = 0;  if (__builtin_expect (__pthread_initial_thread.p_report_events, 0))    {      /* It's a bit more complicated.  We have to report the creation of	 the manager thread.  */      int idx = __td_eventword (TD_CREATE);      uint32_t mask = __td_eventmask (TD_CREATE);      if ((mask & (__pthread_threads_events.event_bits[idx]		   | __pthread_initial_thread.p_eventbuf.eventmask.event_bits[idx]))	  != 0)	{	  __pthread_lock(__pthread_manager_thread.p_lock, NULL);#ifdef NEED_SEPARATE_REGISTER_STACK	  pid = __clone2(__pthread_manager_event,			 (void **) __pthread_manager_thread_bos,			 THREAD_MANAGER_STACK_SIZE,			 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,			 (void *)(long)manager_pipe[0]);#elif _STACK_GROWS_UP	  pid = __clone(__pthread_manager_event,			(void **) __pthread_manager_thread_bos,			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,			(void *)(long)manager_pipe[0]);#else	  pid = __clone(__pthread_manager_event,			(void **) __pthread_manager_thread_tos,			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,			(void *)(long)manager_pipe[0]);#endif	  if (pid != -1)	    {	      /* Now fill in the information about the new thread in	         the newly created thread's data structure.  We cannot let	         the new thread do this since we don't know whether it was	         already scheduled when we send the event.  */	      __pthread_manager_thread.p_eventbuf.eventdata =		&__pthread_manager_thread;	      __pthread_manager_thread.p_eventbuf.eventnum = TD_CREATE;	      __pthread_last_event = &__pthread_manager_thread;	      __pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1;	      __pthread_manager_thread.p_pid = pid;	      /* Now call the function which signals the event.  */	      __linuxthreads_create_event ();	    }	  /* Now restart the thread.  */	  __pthread_unlock(__pthread_manager_thread.p_lock);	}    }  if (__builtin_expect (pid, 0) == 0)    {#ifdef NEED_SEPARATE_REGISTER_STACK      pid = __clone2(__pthread_manager, (void **) __pthread_manager_thread_bos,		     THREAD_MANAGER_STACK_SIZE,		     CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,		     (void *)(long)manager_pipe[0]);#elif _STACK_GROWS_UP      pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_bos,		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,		    (void *)(long)manager_pipe[0]);#else      pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_tos,		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,		    (void *)(long)manager_pipe[0]);#endif    }  if (__builtin_expect (pid, 0) == -1) {    free(__pthread_manager_thread_bos);    __libc_close(manager_pipe[0]);    __libc_close(manager_pipe[1]);    return -1;  }  __pthread_manager_request = manager_pipe[1]; /* writing end */  __pthread_manager_reader = manager_pipe[0]; /* reading end */  __pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1;  __pthread_manager_thread.p_pid = pid;  /* Make gdb aware of new thread manager */  if (__builtin_expect (__pthread_threads_debug, 0) && __pthread_sig_debug > 0)    {      raise(__pthread_sig_debug);      /* We suspend ourself and gdb will wake us up when it is	 ready to handle us. */      __pthread_wait_for_restart_signal(thread_self());    }  /* Synchronize debugging of the thread manager */  request.req_kind = REQ_DEBUG;  TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request,				  (char *) &request, sizeof(request)));  return 0;}/* Thread creation */int __pthread_create_2_1(pthread_t *thread, const pthread_attr_t *attr,			 void * (*start_routine)(void *), void *arg){  pthread_descr self = thread_self();  struct pthread_request request;  int retval;  if (__builtin_expect (__pthread_manager_request, 0) < 0) {    if (__pthread_initialize_manager() < 0) return EAGAIN;  }  request.req_thread = self;  request.req_kind = REQ_CREATE;  request.req_args.create.attr = attr;  request.req_args.create.fn = start_routine;  request.req_args.create.arg = arg;  sigprocmask(SIG_SETMASK, (const sigset_t *) NULL,              &request.req_args.create.mask);  TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request,				  (char *) &request, sizeof(request)));  suspend(self);  retval = THREAD_GETMEM(self, p_retcode);  if (__builtin_expect (retval, 0) == 0)    *thread = (pthread_t) THREAD_GETMEM(self, p_retval);  return retval;}versioned_symbol (libpthread, __pthread_create_2_1, pthread_create, GLIBC_2_1);#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)int __pthread_create_2_0(pthread_t *thread, const pthread_attr_t *attr,			 void * (*start_routine)(void *), void *arg){  /* The ATTR attribute is not really of type `pthread_attr_t *'.  It has     the old size and access to the new members might crash the program.     We convert the struct now.  */  pthread_attr_t new_attr;  if (attr != NULL)    {      size_t ps = __getpagesize ();      memcpy (&new_attr, attr,	      (size_t) &(((pthread_attr_t*)NULL)->__guardsize));      new_attr.__guardsize = ps;      new_attr.__stackaddr_set = 0;      new_attr.__stackaddr = NULL;      new_attr.__stacksize = STACK_SIZE - ps;      attr = &new_attr;    }  return __pthread_create_2_1 (thread, attr, start_routine, arg);}compat_symbol (libpthread, __pthread_create_2_0, pthread_create, GLIBC_2_0);#endif/* Simple operations on thread identifiers */pthread_t pthread_self(void){  pthread_descr self = thread_self();  return THREAD_GETMEM(self, p_tid);}int pthread_equal(pthread_t thread1, pthread_t thread2){  return thread1 == thread2;}/* Helper function for thread_self in the case of user-provided stacks */#ifndef THREAD_SELFpthread_descr __pthread_find_self(void){  char * sp = CURRENT_STACK_FRAME;  pthread_handle h;  /* __pthread_handles[0] is the initial thread, __pthread_handles[1] is     the manager threads handled specially in thread_self(), so start at 2 */  h = __pthread_handles + 2;  while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom)) h++;  return h->h_descr;}#elsestatic pthread_descr thread_self_stack(void){  char *sp = CURRENT_STACK_FRAME;  pthread_handle h;  if (sp >= __pthread_manager_thread_bos && sp < __pthread_manager_thread_tos)    return &__pthread_manager_thread;  h = __pthread_handles + 2;  while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom))    h++;  return h->h_descr;}#endif/* Thread scheduling */int pthread_setschedparam(pthread_t thread, int policy,                          const struct sched_param *param){  pthread_handle handle = thread_handle(thread);  pthread_descr th;  __pthread_lock(&handle->h_lock, NULL);  if (__builtin_expect (invalid_handle(handle, thread), 0)) {    __pthread_unlock(&handle->h_lock);    return ESRCH;  }  th = handle->h_descr;  if (__builtin_expect (__sched_setscheduler(th->p_pid, policy, param) == -1,			0)) {    __pthread_unlock(&handle->h_lock);    return errno;  }  th->p_priority = policy == SCHED_OTHER ? 0 : param->sched_priority;  __pthread_unlock(&handle->h_lock);  if (__pthread_manager_request >= 0)    __pthread_manager_adjust_prio(th->p_priority);  return 0;}int pthread_getschedparam(pthread_t thread, int *policy,                          struct sched_param *param){  pthread_handle handle = thread_handle(thread);  int pid, pol;  __pthread_lock(&handle->h_lock, NULL);  if (__builtin_expect (invalid_handle(handle, thread), 0)) {    __pthread_unlock(&handle->h_lock);    return ESRCH;  }  pid = handle->h_descr->p_pid;  __pthread_unlock(&handle->h_lock);  pol = __sched_getscheduler(pid);  if (__builtin_expect (pol, 0) == -1) return errno;  if (__sched_getparam(pid, param) == -1) return errno;  *policy = pol;  return 0;}int __pthread_yield (void){  /* For now this is equivalent with the POSIX call.  */  return sched_yield ();}weak_alias (__pthread_yield, pthread_yield)/* Process-wide exit() request */

⌨️ 快捷键说明

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