| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481 | /* 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.                 */#ifndef _INTERNALS_H#define _INTERNALS_H   1/* Internal data structures *//* Includes */#include <bits/libc-tsd.h> /* for _LIBC_TSD_KEY_N */#include <limits.h>#include <setjmp.h>#include <signal.h>#include <unistd.h>#include <sys/types.h>#include "pt-machine.h"#include "semaphore.h"#include "../linuxthreads_db/thread_dbP.h"#ifndef THREAD_GETMEM# define THREAD_GETMEM(descr, member) descr->member#endif#ifndef THREAD_GETMEM_NC# define THREAD_GETMEM_NC(descr, member) descr->member#endif#ifndef THREAD_SETMEM# define THREAD_SETMEM(descr, member, value) descr->member = (value)#endif#ifndef THREAD_SETMEM_NC# define THREAD_SETMEM_NC(descr, member, value) descr->member = (value)#endif/* Arguments passed to thread creation routine */struct pthread_start_args {  void * (*start_routine)(void *); /* function to run */  void * arg;                   /* its argument */  sigset_t mask;                /* initial signal mask for thread */  int schedpolicy;              /* initial scheduling policy (if any) */  struct sched_param schedparam; /* initial scheduling parameters (if any) */};/* We keep thread specific data in a special data structure, a two-level   array.  The top-level array contains pointers to dynamically allocated   arrays of a certain number of data pointers.  So we can implement a   sparse array.  Each dynamic second-level array has	PTHREAD_KEY_2NDLEVEL_SIZE   entries.  This value shouldn't be too large.  */#define PTHREAD_KEY_2NDLEVEL_SIZE	32/* We need to address PTHREAD_KEYS_MAX key with PTHREAD_KEY_2NDLEVEL_SIZE   keys in each subarray.  */#define PTHREAD_KEY_1STLEVEL_SIZE \  ((PTHREAD_KEYS_MAX + PTHREAD_KEY_2NDLEVEL_SIZE - 1) \   / PTHREAD_KEY_2NDLEVEL_SIZE)typedef void (*destr_function)(void *);struct pthread_key_struct {  int in_use;                   /* already allocated? */  destr_function destr;         /* destruction routine */};#define PTHREAD_START_ARGS_INITIALIZER { NULL, NULL, {{0, }}, 0, { 0 } }/* The type of thread descriptors */typedef struct _pthread_descr_struct * pthread_descr;/* Callback interface for removing the thread from waiting on an   object if it is cancelled while waiting or about to wait.   This hold a pointer to the object, and a pointer to a function   which ``extricates'' the thread from its enqueued state.   The function takes two arguments: pointer to the wait object,   and a pointer to the thread. It returns 1 if an extrication   actually occured, and hence the thread must also be signalled.   It returns 0 if the thread had already been extricated. */typedef struct _pthread_extricate_struct {    void *pu_object;    int (*pu_extricate_func)(void *, pthread_descr);} pthread_extricate_if;/* Atomic counter made possible by compare_and_swap */struct pthread_atomic {  long p_count;  int p_spinlock;};/* Context info for read write locks. The pthread_rwlock_info structure   is information about a lock that has been read-locked by the thread   in whose list this structure appears. The pthread_rwlock_context   is embedded in the thread context and contains a pointer to the   head of the list of lock info structures, as well as a count of   read locks that are untracked, because no info structure could be   allocated for them. */struct _pthread_rwlock_t;typedef struct _pthread_rwlock_info {  struct _pthread_rwlock_info *pr_next;  struct _pthread_rwlock_t *pr_lock;  int pr_lock_count;} pthread_readlock_info;struct _pthread_descr_struct {  pthread_descr p_nextlive, p_prevlive;                                /* Double chaining of active threads */  pthread_descr p_nextwaiting;  /* Next element in the queue holding the thr */  pthread_descr p_nextlock;	/* can be on a queue and waiting on a lock */  pthread_t p_tid;              /* Thread identifier */  int p_pid;                    /* PID of Unix process */  int p_priority;               /* Thread priority (== 0 if not realtime) */  struct _pthread_fastlock * p_lock; /* Spinlock for synchronized accesses */  int p_signal;                 /* last signal received */  sigjmp_buf * p_signal_jmp;    /* where to siglongjmp on a signal or NULL */  sigjmp_buf * p_cancel_jmp;    /* where to siglongjmp on a cancel or NULL */  char p_terminated;            /* true if terminated e.g. by pthread_exit */  char p_detached;              /* true if detached */  char p_exited;                /* true if the assoc. process terminated */  void * p_retval;              /* placeholder for return value */  int p_retcode;                /* placeholder for return code */  pthread_descr p_joining;      /* thread joining on that thread or NULL */  struct _pthread_cleanup_buffer * p_cleanup; /* cleanup functions */  char p_cancelstate;           /* cancellation state */  char p_canceltype;            /* cancellation type (deferred/async) */  char p_canceled;              /* cancellation request pending */  int * p_errnop;               /* pointer to used errno variable */  int p_errno;                  /* error returned by last system call */  int * p_h_errnop;             /* pointer to used h_errno variable */  int p_h_errno;                /* error returned by last netdb function */  char * p_in_sighandler;       /* stack address of sighandler, or NULL */  char p_sigwaiting;            /* true if a sigwait() is in progress */  struct pthread_start_args p_start_args; /* arguments for thread creation */  void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE]; /* thread-specific data */  void * p_libc_specific[_LIBC_TSD_KEY_N]; /* thread-specific data for libc */  int p_userstack;		/* nonzero if the user provided the stack */  void *p_guardaddr;		/* address of guard area or NULL */  size_t p_guardsize;		/* size of guard area */  pthread_descr p_self;		/* Pointer to this structure */  int p_nr;                     /* Index of descriptor in __pthread_handles */  int p_report_events;         /* Nonzero if events must be reported.  */  td_eventbuf_t p_eventbuf;     /* Data for event.  */  struct pthread_atomic p_resume_count; /* number of times restart() was					   called on thread */  char p_woken_by_cancel;       /* cancellation performed wakeup */  pthread_extricate_if *p_extricate; /* See above */  pthread_readlock_info *p_readlock_list;  /* List of readlock info structs */  pthread_readlock_info *p_readlock_free;  /* Free list of structs */  int p_untracked_readlock_count;	/* Readlocks not tracked by list */  /* New elements must be added at the end.  */} __attribute__ ((aligned(32))); /* We need to align the structure so that				    doubles are aligned properly.  This is 8				    bytes on MIPS and 16 bytes on MIPS64.				    32 bytes might give better cache				    utilization.  *//* The type of thread handles. */typedef struct pthread_handle_struct * pthread_handle;struct pthread_handle_struct {  struct _pthread_fastlock h_lock; /* Fast lock for sychronized access */  pthread_descr h_descr;        /* Thread descriptor or NULL if invalid */  char * h_bottom;              /* Lowest address in the stack thread */};/* The type of messages sent to the thread manager thread */struct pthread_request {  pthread_descr req_thread;     /* Thread doing the request */  enum {                        /* Request kind */    REQ_CREATE, REQ_FREE, REQ_PROCESS_EXIT, REQ_MAIN_THREAD_EXIT,    REQ_POST, REQ_DEBUG  } req_kind;  union {                       /* Arguments for request */    struct {                    /* For REQ_CREATE: */      const pthread_attr_t * attr; /* thread attributes */      void * (*fn)(void *);     /*   start function */      void * arg;               /*   argument to start function */      sigset_t mask;            /*   signal mask */    } create;    struct {                    /* For REQ_FREE: */      pthread_t thread_id;      /*   identifier of thread to free */    } free;    struct {                    /* For REQ_PROCESS_EXIT: */      int code;                 /*   exit status */    } exit;    void * post;                /* For REQ_POST: the semaphore */  } req_args;};/* Signals used for suspend/restart and for cancellation notification.  */extern int __pthread_sig_restart;extern int __pthread_sig_cancel;/* Signal used for interfacing with gdb */extern int __pthread_sig_debug;/* Global array of thread handles, used for validating a thread id   and retrieving the corresponding thread descriptor. Also used for   mapping the available stack segments. */extern struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX];/* Descriptor of the initial thread */extern struct _pthread_descr_struct __pthread_initial_thread;/* Descriptor of the manager thread */extern struct _pthread_descr_struct __pthread_manager_thread;/* Descriptor of the main thread */extern pthread_descr __pthread_main_thread;/* Limit between the stack of the initial thread (above) and the   stacks of other threads (below). Aligned on a STACK_SIZE boundary.   Initially 0, meaning that the current thread is (by definition)   the initial thread. *//* For non-MMU systems also remember to stack top of the initial thread. * This is adapted when other stacks are malloc'ed since we don't know * the bounds a-priori. -StS */extern char *__pthread_initial_thread_bos;#ifndef __UCLIBC_HAS_MMU__extern char *__pthread_initial_thread_tos;#define NOMMU_INITIAL_THREAD_BOUNDS(tos,bos) if ((tos)>=__pthread_initial_thread_bos && (bos)<=__pthread_initial_thread_tos) __pthread_initial_thread_bos = (tos)+1#else#define NOMMU_INITIAL_THREAD_BOUNDS(tos,bos) /* empty */#endif /* __UCLIBC_HAS_MMU__ *//* Indicate whether at least one thread has a user-defined stack (if 1),   or all threads have stacks supplied by LinuxThreads (if 0). */extern int __pthread_nonstandard_stacks;/* File descriptor for sending requests to the thread manager.   Initially -1, meaning that __pthread_initialize_manager must be called. */extern int __pthread_manager_request;/* Other end of the pipe for sending requests to the thread manager. */extern int __pthread_manager_reader;/* Limits of the thread manager stack. */extern char *__pthread_manager_thread_bos;extern char *__pthread_manager_thread_tos;/* Pending request for a process-wide exit */extern int __pthread_exit_requested, __pthread_exit_code;/* Set to 1 by gdb if we're debugging */extern volatile int __pthread_threads_debug;/* Globally enabled events.  */extern volatile td_thr_events_t __pthread_threads_events;/* Pointer to descriptor of thread with last event.  */extern volatile pthread_descr __pthread_last_event;/* Return the handle corresponding to a thread id */static inline pthread_handle thread_handle(pthread_t id){  return &__pthread_handles[id % PTHREAD_THREADS_MAX];}/* Validate a thread handle. Must have acquired h->h_spinlock before. */static inline int invalid_handle(pthread_handle h, pthread_t id){  return h->h_descr == NULL || h->h_descr->p_tid != id;}/* Fill in defaults left unspecified by pt-machine.h.  *//* The page size we can get from the system.  This should likely not be   changed by the machine file but, you never know.  */#ifndef PAGE_SIZE#define PAGE_SIZE  (sysconf (_SC_PAGE_SIZE))#endif/* The max size of the thread stack segments.  If the default   THREAD_SELF implementation is used, this must be a power of two and   a multiple of PAGE_SIZE.  */#ifndef STACK_SIZE#define STACK_SIZE  (2 * 1024 * 1024)#endif/* The initial size of the thread stack.  Must be a multiple of PAGE_SIZE.  */#ifndef INITIAL_STACK_SIZE#define INITIAL_STACK_SIZE  (4 * PAGE_SIZE)#endif/* Size of the thread manager stack. The "- 32" avoids wasting space   with some malloc() implementations. */#ifndef THREAD_MANAGER_STACK_SIZE#define THREAD_MANAGER_STACK_SIZE  (2 * PAGE_SIZE - 32)#endif/* The base of the "array" of thread stacks.  The array will grow down from   here.  Defaults to the calculated bottom of the initial application   stack.  */#ifndef THREAD_STACK_START_ADDRESS#define THREAD_STACK_START_ADDRESS  __pthread_initial_thread_bos#endif/* Get some notion of the current stack.  Need not be exactly the top   of the stack, just something somewhere in the current frame.  */#ifndef CURRENT_STACK_FRAME#define CURRENT_STACK_FRAME  ({ char __csf; &__csf; })#endif/* Recover thread descriptor for the current thread */extern pthread_descr __pthread_find_self (void) __attribute__ ((const));static inline pthread_descr thread_self (void) __attribute__ ((const));static inline pthread_descr thread_self (void){#ifdef THREAD_SELF  return THREAD_SELF;#else  char *sp = CURRENT_STACK_FRAME;#ifdef __UCLIBC_HAS_MMU__  if (sp >= __pthread_initial_thread_bos)    return &__pthread_initial_thread;  else if (sp >= __pthread_manager_thread_bos	   && sp < __pthread_manager_thread_tos)    return &__pthread_manager_thread;  else if (__pthread_nonstandard_stacks)    return __pthread_find_self();  else    return (pthread_descr)(((unsigned long)sp | (STACK_SIZE-1))+1) - 1;#else  /* For non-MMU we need to be more careful about the initial thread stack.   * We refine the initial thread stack bounds dynamically as we allocate   * the other stack frame such that it doesn't overlap with them. Then   * we can be sure to pick the right thread according to the current SP */  /* Since we allow other stack frames to be above or below, we need to   * treat this case special. When pthread_initialize() wasn't called yet,   * only the initial thread is there. */  if (__pthread_initial_thread_bos == NULL) {      return &__pthread_initial_thread;  }  else if (sp >= __pthread_initial_thread_bos	   && sp < __pthread_initial_thread_tos) {      return &__pthread_initial_thread;  }  else if (sp >= __pthread_manager_thread_bos	   && sp < __pthread_manager_thread_tos) {      return &__pthread_manager_thread;  }  else {      return __pthread_find_self();  }#endif /* __UCLIBC_HAS_MMU__ */#endif}/* Max number of times we must spin on a spinlock calling sched_yield().   After MAX_SPIN_COUNT iterations, we put the calling thread to sleep. */#ifndef MAX_SPIN_COUNT#define MAX_SPIN_COUNT 50#endif/* Duration of sleep (in nanoseconds) when we can't acquire a spinlock   after MAX_SPIN_COUNT iterations of sched_yield().   With the 2.0 and 2.1 kernels, this MUST BE > 2ms.   (Otherwise the kernel does busy-waiting for realtime threads,    giving other threads no chance to run.) */#ifndef SPIN_SLEEP_DURATION#define SPIN_SLEEP_DURATION 2000001#endif/* Debugging */#ifdef DEBUG#include <assert.h>#define ASSERT assert#define MSG __pthread_message#else#define ASSERT(x)#define MSG(msg,arg...)#endif/* Internal global functions */void __pthread_destroy_specifics(void);void __pthread_perform_cleanup(void);int __pthread_initialize_manager(void);void __pthread_message(char * fmt, ...);int __pthread_manager(void *reqfd);int __pthread_manager_event(void *reqfd);void __pthread_manager_sighandler(int sig);void __pthread_reset_main_thread(void);void __fresetlockfiles(void);void __pthread_manager_adjust_prio(int thread_prio);void __pthread_set_own_extricate_if(pthread_descr self, pthread_extricate_if *peif);void __pthread_initialize_minimal (void);extern int __pthread_attr_setguardsize __P ((pthread_attr_t *__attr,					     size_t __guardsize));extern int __pthread_attr_getguardsize __P ((__const pthread_attr_t *__attr,					     size_t *__guardsize));extern int __pthread_attr_setstackaddr __P ((pthread_attr_t *__attr,					     void *__stackaddr));extern int __pthread_attr_getstackaddr __P ((__const pthread_attr_t *__attr,					     void **__stackaddr));extern int __pthread_attr_setstacksize __P ((pthread_attr_t *__attr,					     size_t __stacksize));extern int __pthread_attr_getstacksize __P ((__const pthread_attr_t *__attr,					     size_t *__stacksize));extern int __pthread_getconcurrency __P ((void));extern int __pthread_setconcurrency __P ((int __level));extern int __pthread_mutexattr_gettype __P ((__const pthread_mutexattr_t *__attr,					     int *__kind));extern void __pthread_kill_other_threads_np __P ((void));void __pthread_restart_old(pthread_descr th);void __pthread_suspend_old(pthread_descr self);void __pthread_restart_new(pthread_descr th);void __pthread_suspend_new(pthread_descr self);void __pthread_wait_for_restart_signal(pthread_descr self);void __pthread_init_condvar(int rt_sig_available);/* Global pointers to old or new suspend functions */extern void (*__pthread_restart)(pthread_descr);extern void (*__pthread_suspend)(pthread_descr);/* Prototypes for the function without cancelation support when the   normal version has it.  */extern int __libc_close (int fd);extern int __libc_nanosleep (const struct timespec *requested_time,			     struct timespec *remaining);extern ssize_t __libc_read (int fd, void *buf, size_t count);extern pid_t __libc_waitpid (pid_t pid, int *stat_loc, int options);extern ssize_t __libc_write (int fd, const void *buf, size_t count);/* Prototypes for some of the new semaphore functions.  */extern int __new_sem_post (sem_t * sem);/* The functions called the signal events.  */extern void __linuxthreads_create_event (void);extern void __linuxthreads_death_event (void);extern void __linuxthreads_reap_event (void);#endif /* internals.h */
 |