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

📄 pthread.c

📁 用于嵌入式Linux系统的标准C的库函数
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Linuxthreads - a simple clone()-based implementation of Posix        *//* threads for Linux.                                                   *//* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              *//*                                                                      *//* This program is free software; you can redistribute it and/or        *//* modify it under the terms of the GNU Library General Public License  *//* as published by the Free Software Foundation; either version 2       *//* of the License, or (at your option) any later version.               *//*                                                                      *//* This program is distributed in the hope that it will be useful,      *//* but WITHOUT ANY WARRANTY; without even the implied warranty of       *//* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *//* GNU Library General Public License for more details.                 *//* Thread creation, initialization, and basic low-level routines */#include <errno.h>#include <stddef.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <sys/wait.h>#include <sys/resource.h>#include <sys/sysctl.h>#include <shlib-compat.h>#include "pthread.h"#include "internals.h"#include "spinlock.h"#include "restart.h"#include <machine/syscall.h>/* for threading we use processes so we require a few EL/IX level 2 and    level 3 syscalls.  We only allow this file to see them to preserve   the interface. */#if defined(_ELIX_LEVEL) && _ELIX_LEVEL < 3static _syscall1_base(int,pipe,int *,filedes)#endif /* _ELIX_LEVEL < 3 */#if defined(_ELIX_LEVEL) && _ELIX_LEVEL < 2static _syscall2_base(int,setrlimit,int,resource,const struct rlimit *,rlp)int on_exit (void (*fn)(int, void *), void *arg){  register struct _atexit *p;  void (*x)(void) = (void (*)(void))fn;/* _REENT_SMALL on_exit() doesn't allow more than the required 32 entries.  */#ifndef _REENT_SMALL  if ((p = _REENT->_atexit) == NULL)    _REENT->_atexit = p = &_REENT->_atexit0;  if (p->_ind >= _ATEXIT_SIZE)    {      if ((p = (struct _atexit *) malloc (sizeof *p)) == NULL)        return -1;      p->_ind = 0;      p->_fntypes = 0;      p->_next = _REENT->_atexit;      _REENT->_atexit = p;    }#else  p = &_REENT->_atexit;  if (p->_ind >= _ATEXIT_SIZE)    return -1;#endif  p->_fntypes |= (1 << p->_ind);  p->_fnargs[p->_ind] = arg;  p->_fns[p->_ind++] = x;  return 0;}#endif /* _ELIX_LEVEL < 2 *//* We need the global/static resolver state here.  */#include <resolv.h>#undef _res/* FIXME: for now, set up _res here */struct __res_state _res;/* Sanity check.  */#if __ASSUME_REALTIME_SIGNALS && !defined __SIGRTMIN# error "This must not happen; new kernel assumed but old headers"#endif/* These variables are used by the setup code.  *//* Descriptor of the initial thread */struct _pthread_descr_struct __pthread_initial_thread = {  {    {      &__pthread_initial_thread /* pthread_descr self */    }  },  &__pthread_initial_thread,  /* pthread_descr p_nextlive */  &__pthread_initial_thread,  /* pthread_descr p_prevlive */  NULL,                       /* pthread_descr p_nextwaiting */  NULL,			      /* pthread_descr p_nextlock */  PTHREAD_THREADS_MAX,        /* pthread_t p_tid */  0,                          /* int p_pid */  0,                          /* int p_priority */  &__pthread_handles[0].h_lock, /* struct _pthread_fastlock * p_lock */  0,                          /* int p_signal */  NULL,                       /* sigjmp_buf * p_signal_buf */  NULL,                       /* sigjmp_buf * p_cancel_buf */  0,                          /* char p_terminated */  0,                          /* char p_detached */  0,                          /* char p_exited */  NULL,                       /* void * p_retval */  0,                          /* int p_retval */  NULL,                       /* pthread_descr p_joining */  NULL,                       /* struct _pthread_cleanup_buffer * p_cleanup */  0,                          /* char p_cancelstate */  0,                          /* char p_canceltype */  0,                          /* char p_canceled */  &__pthread_initial_thread.p_reent, /* struct _reent *p_reentp */  _REENT_INIT(__pthread_initial_thread.p_reent),  /* struct _reent p_reent */  NULL,                       /* int *p_h_errnop */  0,                          /* int p_h_errno */  NULL,                       /* char * p_in_sighandler */  0,                          /* char p_sigwaiting */  PTHREAD_START_ARGS_INITIALIZER(NULL),                              /* struct pthread_start_args p_start_args */  {NULL},                     /* void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE] */  {NULL},                     /* void * p_libc_specific[_LIBC_TSD_KEY_N] */  1,                          /* int p_userstack */  NULL,                       /* void * p_guardaddr */  0,                          /* size_t p_guardsize */  0,                          /* Always index 0 */  0,                          /* int p_report_events */  {{{0, }}, 0, NULL},         /* td_eventbuf_t p_eventbuf */  __ATOMIC_INITIALIZER,       /* struct pthread_atomic p_resume_count */  0,                          /* char p_woken_by_cancel */  0,                          /* char p_condvar_avail */  0,                          /* char p_sem_avail */  NULL,                       /* struct pthread_extricate_if *p_extricate */  NULL,	                      /* pthread_readlock_info *p_readlock_list; */  NULL,                       /* pthread_readlock_info *p_readlock_free; */  0                           /* int p_untracked_readlock_count; */};/* Descriptor of the manager thread; none of this is used but the error   variables, the p_pid and p_priority fields,   and the address for identification.  */struct _pthread_descr_struct __pthread_manager_thread = {  {    {      &__pthread_manager_thread /* pthread_descr self */    }  },  NULL,                       /* pthread_descr p_nextlive */  NULL,                       /* pthread_descr p_prevlive */  NULL,                       /* pthread_descr p_nextwaiting */  NULL,			      /* pthread_descr p_nextlock */  0,                          /* int p_tid */  0,                          /* int p_pid */  0,                          /* int p_priority */  &__pthread_handles[1].h_lock, /* struct _pthread_fastlock * p_lock */  0,                          /* int p_signal */  NULL,                       /* sigjmp_buf * p_signal_buf */  NULL,                       /* sigjmp_buf * p_cancel_buf */  0,                          /* char p_terminated */  0,                          /* char p_detached */  0,                          /* char p_exited */  NULL,                       /* void * p_retval */  0,                          /* int p_retval */  NULL,                       /* pthread_descr p_joining */  NULL,                       /* struct _pthread_cleanup_buffer * p_cleanup */  0,                          /* char p_cancelstate */  0,                          /* char p_canceltype */  0,                          /* char p_canceled */  &__pthread_manager_thread.p_reent, /* struct _reent *p_reentp */  _REENT_INIT(__pthread_manager_thread.p_reent), /* struct _reent p_reent */  NULL,                       /* int *p_h_errnop */  0,                          /* int p_h_errno */  NULL,                       /* char * p_in_sighandler */  0,                          /* char p_sigwaiting */  PTHREAD_START_ARGS_INITIALIZER(__pthread_manager),                              /* struct pthread_start_args p_start_args */  {NULL},                     /* void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE] */  {NULL},                     /* void * p_libc_specific[_LIBC_TSD_KEY_N] */  0,                          /* int p_userstack */  NULL,                       /* void * p_guardaddr */  0,                          /* size_t p_guardsize */  1,                          /* Always index 1 */  0,                          /* int p_report_events */  {{{0, }}, 0, NULL},         /* td_eventbuf_t p_eventbuf */  __ATOMIC_INITIALIZER,       /* struct pthread_atomic p_resume_count */  0,                          /* char p_woken_by_cancel */  0,                          /* char p_condvar_avail */  0,                          /* char p_sem_avail */  NULL,                       /* struct pthread_extricate_if *p_extricate */  NULL,	                      /* pthread_readlock_info *p_readlock_list; */  NULL,                       /* pthread_readlock_info *p_readlock_free; */  0                           /* int p_untracked_readlock_count; */};/* Pointer to the main thread (the father of the thread manager thread) *//* Originally, this is the initial thread, but this changes after fork() */pthread_descr __pthread_main_thread = &__pthread_initial_thread;/* Limit between the stack of the initial thread (above) and the   stacks of other threads (below). Aligned on a STACK_SIZE boundary. */char *__pthread_initial_thread_bos;/* File descriptor for sending requests to the thread manager. *//* Initially -1, meaning that the thread manager is not running. */int __pthread_manager_request = -1;/* Other end of the pipe for sending requests to the thread manager. */int __pthread_manager_reader;/* Limits of the thread manager stack */char *__pthread_manager_thread_bos;char *__pthread_manager_thread_tos;/* For process-wide exit() */int __pthread_exit_requested;int __pthread_exit_code;/* Maximum stack size.  */size_t __pthread_max_stacksize;/* Nozero if the machine has more than one processor.  */int __pthread_smp_kernel;#if !__ASSUME_REALTIME_SIGNALS/* Pointers that select new or old suspend/resume functions   based on availability of rt signals. */void (*__pthread_restart)(pthread_descr) = __pthread_restart_old;void (*__pthread_suspend)(pthread_descr) = __pthread_suspend_old;int (*__pthread_timedsuspend)(pthread_descr, const struct timespec *) = __pthread_timedsuspend_old;#endif	/* __ASSUME_REALTIME_SIGNALS *//* Communicate relevant LinuxThreads constants to gdb */const int __pthread_threads_max = PTHREAD_THREADS_MAX;const int __pthread_sizeof_handle = sizeof(struct pthread_handle_struct);const int __pthread_offsetof_descr = offsetof(struct pthread_handle_struct,                                              h_descr);const int __pthread_offsetof_pid = offsetof(struct _pthread_descr_struct,                                            p_pid);const int __linuxthreads_pthread_sizeof_descr  = sizeof(struct _pthread_descr_struct);/* Forward declarations */static void pthread_onexit_process(int retcode, void *arg);#ifndef HAVE_Z_NODELETEstatic void pthread_atexit_process(void *arg, int retcode);static void pthread_atexit_retcode(void *arg, int retcode);#endifstatic void pthread_handle_sigcancel(int sig);static void pthread_handle_sigrestart(int sig);static void pthread_handle_sigdebug(int sig);/* CPU clock handling.  */#if HP_TIMING_AVAILextern hp_timing_t _dl_cpuclock_offset;#endif/* Signal numbers used for the communication.   In these variables we keep track of the used variables.  If the   platform does not support any real-time signals we will define the   values to some unreasonable value which will signal failing of all   the functions below.  */#ifndef __SIGRTMINstatic int current_rtmin = -1;static int current_rtmax = -1;int __pthread_sig_restart = SIGUSR1;int __pthread_sig_cancel = SIGUSR2;int __pthread_sig_debug;#elsestatic int current_rtmin;static int current_rtmax;#if __SIGRTMAX - __SIGRTMIN >= 3int __pthread_sig_restart = __SIGRTMIN;int __pthread_sig_cancel = __SIGRTMIN + 1;int __pthread_sig_debug = __SIGRTMIN + 2;#elseint __pthread_sig_restart = SIGUSR1;int __pthread_sig_cancel = SIGUSR2;int __pthread_sig_debug;#endifstatic int rtsigs_initialized;#if !__ASSUME_REALTIME_SIGNALS# include "testrtsig.h"#endifstatic voidinit_rtsigs (void){#if !__ASSUME_REALTIME_SIGNALS  if (__builtin_expect (!kernel_has_rtsig (), 0))    {      current_rtmin = -1;      current_rtmax = -1;# if __SIGRTMAX - __SIGRTMIN >= 3      __pthread_sig_restart = SIGUSR1;      __pthread_sig_cancel = SIGUSR2;      __pthread_sig_debug = 0;# endif    }  else#endif	/* __ASSUME_REALTIME_SIGNALS */    {#if __SIGRTMAX - __SIGRTMIN >= 3      current_rtmin = __SIGRTMIN + 3;# if !__ASSUME_REALTIME_SIGNALS      __pthread_restart = __pthread_restart_new;      __pthread_suspend = __pthread_wait_for_restart_signal;      __pthread_timedsuspend = __pthread_timedsuspend_new;# endif /* __ASSUME_REALTIME_SIGNALS */#else      current_rtmin = __SIGRTMIN;#endif      current_rtmax = __SIGRTMAX;    }  rtsigs_initialized = 1;}#endif/* Return number of available real-time signal with highest priority.  */int__libc_current_sigrtmin (void){#ifdef __SIGRTMIN  if (__builtin_expect (!rtsigs_initialized, 0))    init_rtsigs ();#endif  return current_rtmin;}/* Return number of available real-time signal with lowest priority.  */int__libc_current_sigrtmax (void){#ifdef __SIGRTMIN  if (__builtin_expect (!rtsigs_initialized, 0))    init_rtsigs ();#endif  return current_rtmax;}/* Allocate real-time signal with highest/lowest available   priority.  Please note that we don't use a lock since we assume   this function to be called at program start.  */int__libc_allocate_rtsig (int high){#ifndef __SIGRTMIN  return -1;#else  if (__builtin_expect (!rtsigs_initialized, 0))    init_rtsigs ();  if (__builtin_expect (current_rtmin == -1, 0)      || __builtin_expect (current_rtmin > current_rtmax, 0))    /* We don't have anymore signal available.  */    return -1;  return high ? current_rtmin++ : current_rtmax--;#endif}/* The function we use to get the kernel revision.  */extern int __sysctl (int *name, int nlen, void *oldval, size_t *oldlenp,		     void *newval, size_t newlen);/* Test whether the machine has more than one processor.  This is not the   best test but good enough.  More complicated tests would require `malloc'   which is not available at that time.  */static intis_smp_system (void){  static const int sysctl_args[] = { CTL_KERN, KERN_VERSION };  char buf[512];  size_t reslen = sizeof (buf);  /* Try reading the number using `sysctl' first.  */  if (__sysctl ((int *) sysctl_args,		sizeof (sysctl_args) / sizeof (sysctl_args[0]),		buf, &reslen, NULL, 0) < 0)    {      /* This was not successful.  Now try reading the /proc filesystem.  */      int fd = __open ("/proc/sys/kernel/version", O_RDONLY);      if (__builtin_expect (fd, 0) == -1	  || (reslen = __read (fd, buf, sizeof (buf))) <= 0)	/* This also didn't work.  We give up and say it's a UP machine.  */	buf[0] = '\0';      __close (fd);    }  return strstr (buf, "SMP") != NULL;}/* Initialize the pthread library.   Initialization is split in two functions:   - a constructor function that blocks the __pthread_sig_restart signal     (must do this very early, since the program could capture the signal

⌨️ 快捷键说明

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