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

📄 pthread.c

📁 Axis 221 camera embedded programing interface
💻 C
📖 第 1 页 / 共 3 页
字号:
  sigjmp_buf * jmpbuf;    if (self == &__pthread_manager_thread)    {#ifdef THREAD_SELF      /* A new thread might get a cancel signal before it is fully	 initialized, so that the thread register might still point to the	 manager thread.  Double check that this is really the manager	 thread.  */      pthread_descr real_self = thread_self_stack();      if (real_self == &__pthread_manager_thread)	{	  __pthread_manager_sighandler(sig);	  return;	}      /* Oops, thread_self() isn't working yet..  */      self = real_self;# ifdef INIT_THREAD_SELF      INIT_THREAD_SELF(self, self->p_nr);# endif#else      __pthread_manager_sighandler(sig);      return;#endif    }  if (__builtin_expect (__pthread_exit_requested, 0)) {    /* Main thread should accumulate times for thread manager and its       children, so that timings for main thread account for all threads. */    if (self == __pthread_main_thread) {#ifdef USE_TLS      waitpid(__pthread_manager_thread->p_pid, NULL, __WCLONE);#else      waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE);#endif    }    _exit(__pthread_exit_code);  }  if (__builtin_expect (THREAD_GETMEM(self, p_canceled), 0)      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {    if (THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS)      pthread_exit(PTHREAD_CANCELED);    jmpbuf = THREAD_GETMEM(self, p_cancel_jmp);    if (jmpbuf != NULL) {      THREAD_SETMEM(self, p_cancel_jmp, NULL);      siglongjmp(*jmpbuf, 1);    }  }}/* Handler for the DEBUG signal.   The debugging strategy is as follows:   On reception of a REQ_DEBUG request (sent by new threads created to   the thread manager under debugging mode), the thread manager throws   __pthread_sig_debug to itself. The debugger (if active) intercepts   this signal, takes into account new threads and continue execution   of the thread manager by propagating the signal because it doesn't   know what it is specifically done for. In the current implementation,   the thread manager simply discards it. */static void pthread_handle_sigdebug(int sig){  /* Nothing */}/* Reset the state of the thread machinery after a fork().   Close the pipe used for requests and set the main thread to the forked   thread.   Notice that we can't free the stack segments, as the forked thread   may hold pointers into them. */void __pthread_reset_main_thread(){  pthread_descr self = thread_self();  if (__pthread_manager_request != -1) {    /* Free the thread manager stack */    free(__pthread_manager_thread_bos);    __pthread_manager_thread_bos = __pthread_manager_thread_tos = NULL;    /* Close the two ends of the pipe */    __libc_close(__pthread_manager_request);    __libc_close(__pthread_manager_reader);    __pthread_manager_request = __pthread_manager_reader = -1;  }  /* Update the pid of the main thread */  THREAD_SETMEM(self, p_pid, __getpid());  /* Make the forked thread the main thread */  __pthread_main_thread = self;  THREAD_SETMEM(self, p_nextlive, self);  THREAD_SETMEM(self, p_prevlive, self);  /* Now this thread modifies the global variables.  */  THREAD_SETMEM(self, p_errnop, &_errno);  THREAD_SETMEM(self, p_h_errnop, &_h_errno);}/* Process-wide exec() request */void __pthread_kill_other_threads_np(void){  struct sigaction sa;  /* Terminate all other threads and thread manager */  pthread_onexit_process(0, NULL);  /* Make current thread the main thread in case the calling thread     changes its mind, does not exec(), and creates new threads instead. */  __pthread_reset_main_thread();  /* Reset the signal handlers behaviour for the signals the     implementation uses since this would be passed to the new     process.  */  sigemptyset(&sa.sa_mask);  sa.sa_flags = 0;  sa.sa_handler = SIG_DFL;  __libc_sigaction(__pthread_sig_restart, &sa, NULL);  __libc_sigaction(__pthread_sig_cancel, &sa, NULL);  if (__pthread_sig_debug > 0)    __libc_sigaction(__pthread_sig_debug, &sa, NULL);}weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)/* Concurrency symbol level.  */static int current_level;int __pthread_setconcurrency(int level){  /* We don't do anything unless we have found a useful interpretation.  */  current_level = level;  return 0;}weak_alias (__pthread_setconcurrency, pthread_setconcurrency)int __pthread_getconcurrency(void){  return current_level;}weak_alias (__pthread_getconcurrency, pthread_getconcurrency)/* Primitives for controlling thread execution */void __pthread_wait_for_restart_signal(pthread_descr self){    sigset_t mask;    sigprocmask(SIG_SETMASK, NULL, &mask); /* Get current signal mask */    sigdelset(&mask, __pthread_sig_restart); /* Unblock the restart signal */    THREAD_SETMEM(self, p_signal, 0);    do {	sigsuspend(&mask);                   /* Wait for signal */    } while (THREAD_GETMEM(self, p_signal) !=__pthread_sig_restart);    READ_MEMORY_BARRIER(); /* See comment in __pthread_restart_new */}#ifndef __NR_rt_sigaction/* The _old variants are for 2.0 and early 2.1 kernels which don't have RT   signals.   On these kernels, we use SIGUSR1 and SIGUSR2 for restart and cancellation.   Since the restart signal does not queue, we use an atomic counter to create   queuing semantics. This is needed to resolve a rare race condition in   pthread_cond_timedwait_relative. */void __pthread_restart_old(pthread_descr th){    if (atomic_increment(&th->p_resume_count) == -1)	kill(th->p_pid, __pthread_sig_restart);}void __pthread_suspend_old(pthread_descr self){    if (atomic_decrement(&self->p_resume_count) <= 0)	__pthread_wait_for_restart_signal(self);}int__pthread_timedsuspend_old(pthread_descr self, const struct timespec *abstime){  sigset_t unblock, initial_mask;  int was_signalled = 0;  sigjmp_buf jmpbuf;  if (atomic_decrement(&self->p_resume_count) == 0) {    /* Set up a longjmp handler for the restart signal, unblock       the signal and sleep. */    if (sigsetjmp(jmpbuf, 1) == 0) {      THREAD_SETMEM(self, p_signal_jmp, &jmpbuf);      THREAD_SETMEM(self, p_signal, 0);      /* Unblock the restart signal */      sigemptyset(&unblock);      sigaddset(&unblock, __pthread_sig_restart);      sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask);      while (1) {	struct timeval now;	struct timespec reltime;	/* Compute a time offset relative to now.  */	__gettimeofday (&now, NULL);	reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000;	reltime.tv_sec = abstime->tv_sec - now.tv_sec;	if (reltime.tv_nsec < 0) {	  reltime.tv_nsec += 1000000000;	  reltime.tv_sec -= 1;	}	/* Sleep for the required duration. If woken by a signal,	   resume waiting as required by Single Unix Specification.  */	if (reltime.tv_sec < 0 || __libc_nanosleep(&reltime, NULL) == 0)	  break;      }      /* Block the restart signal again */      sigprocmask(SIG_SETMASK, &initial_mask, NULL);      was_signalled = 0;    } else {      was_signalled = 1;    }    THREAD_SETMEM(self, p_signal_jmp, NULL);  }  /* Now was_signalled is true if we exited the above code     due to the delivery of a restart signal.  In that case,     we know we have been dequeued and resumed and that the     resume count is balanced.  Otherwise, there are some     cases to consider. First, try to bump up the resume count     back to zero. If it goes to 1, it means restart() was     invoked on this thread. The signal must be consumed     and the count bumped down and everything is cool. We     can return a 1 to the caller.     Otherwise, no restart was delivered yet, so a potential     race exists; we return a 0 to the caller which must deal     with this race in an appropriate way; for example by     atomically removing the thread from consideration for a     wakeup---if such a thing fails, it means a restart is     being delivered. */  if (!was_signalled) {    if (atomic_increment(&self->p_resume_count) != -1) {      __pthread_wait_for_restart_signal(self);      atomic_decrement(&self->p_resume_count); /* should be zero now! */      /* woke spontaneously and consumed restart signal */      return 1;    }    /* woke spontaneously but did not consume restart---caller must resolve */    return 0;  }  /* woken due to restart signal */  return 1;}#endif /* __NR_rt_sigaction */#ifdef __NR_rt_sigactionvoid __pthread_restart_new(pthread_descr th){    /* The barrier is proabably not needed, in which case it still documents       our assumptions. The intent is to commit previous writes to shared       memory so the woken thread will have a consistent view.  Complementary       read barriers are present to the suspend functions. */    WRITE_MEMORY_BARRIER();    kill(th->p_pid, __pthread_sig_restart);}int __pthread_timedsuspend_new(pthread_descr self, const struct timespec *abstime){    sigset_t unblock, initial_mask;    int was_signalled = 0;    sigjmp_buf jmpbuf;    if (sigsetjmp(jmpbuf, 1) == 0) {	THREAD_SETMEM(self, p_signal_jmp, &jmpbuf);	THREAD_SETMEM(self, p_signal, 0);	/* Unblock the restart signal */	sigemptyset(&unblock);	sigaddset(&unblock, __pthread_sig_restart);	sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask);	while (1) {	    struct timeval now;	    struct timespec reltime;	    /* Compute a time offset relative to now.  */	    gettimeofday (&now, NULL);	    reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000;	    reltime.tv_sec = abstime->tv_sec - now.tv_sec;	    if (reltime.tv_nsec < 0) {		reltime.tv_nsec += 1000000000;		reltime.tv_sec -= 1;	    }	    /* Sleep for the required duration. If woken by a signal,	       resume waiting as required by Single Unix Specification.  */	    if (reltime.tv_sec < 0 || __libc_nanosleep(&reltime, NULL) == 0)		break;	}	/* Block the restart signal again */	sigprocmask(SIG_SETMASK, &initial_mask, NULL);	was_signalled = 0;    } else {	was_signalled = 1;    }    THREAD_SETMEM(self, p_signal_jmp, NULL);    /* Now was_signalled is true if we exited the above code       due to the delivery of a restart signal.  In that case,       everything is cool. We have been removed from whatever       we were waiting on by the other thread, and consumed its signal.       Otherwise we this thread woke up spontaneously, or due to a signal other       than restart. This is an ambiguous case  that must be resolved by       the caller; the thread is still eligible for a restart wakeup       so there is a race. */    READ_MEMORY_BARRIER(); /* See comment in __pthread_restart_new */    return was_signalled;}#endif/* Debugging aid */#ifdef DEBUG_PT#include <stdarg.h>void __pthread_message(char * fmt, ...){  char buffer[1024];  va_list args;  sprintf(buffer, "%05d : ", __getpid());  va_start(args, fmt);  vsnprintf(buffer + 8, sizeof(buffer) - 8, fmt, args);  va_end(args);  TEMP_FAILURE_RETRY(__libc_write(2, buffer, strlen(buffer)));}#endif#ifndef __PIC__/* We need a hook to force the cancelation wrappers to be linked in when   static libpthread is used.  */extern const int __pthread_provide_wrappers;static const int *const __pthread_require_wrappers =  &__pthread_provide_wrappers;#endif

⌨️ 快捷键说明

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