Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 | /* 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 _DESCR_H #define _DESCR_H 1 #define __need_res_state #include <resolv.h> #include <sched.h> #include <setjmp.h> #include <signal.h> #include <stdint.h> #include <sys/types.h> #include <hp-timing.h> #ifdef __UCLIBC_HAS_TLS__ #include <tls.h> #endif #include "uClibc-glue.h" /* Fast thread-specific data internal to libc. */ enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0, _LIBC_TSD_KEY_DL_ERROR, _LIBC_TSD_KEY_RPC_VARS, _LIBC_TSD_KEY_LOCALE, _LIBC_TSD_KEY_CTYPE_B, _LIBC_TSD_KEY_CTYPE_TOLOWER, _LIBC_TSD_KEY_CTYPE_TOUPPER, _LIBC_TSD_KEY_N }; /* The type of thread descriptors */ typedef struct _pthread_descr_struct *pthread_descr; /* Some more includes. */ #include <pt-machine.h> #include <linuxthreads_db/thread_dbP.h> /* 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) */ }; /* 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; /* 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) union dtv; struct _pthread_descr_struct { #if !defined __UCLIBC_HAS_TLS__ || !TLS_DTV_AT_TP || INCLUDE_TLS_PADDING /* This overlaps tcbhead_t (see tls.h), as used for TLS without threads. */ union { struct { void *tcb; /* Pointer to the TCB. This is not always the address of this thread descriptor. */ union dtv *dtvp; pthread_descr self; /* Pointer to this structure */ int multiple_threads; uintptr_t sysinfo; } data; void *__padding[16]; } p_header; # define p_multiple_threads p_header.data.multiple_threads #elif defined TLS_MULTIPLE_THREADS_IN_TCB && TLS_MULTIPLE_THREADS_IN_TCB int p_multiple_threads; #endif 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 */ 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 */ #ifndef __UCLIBC_HAS_TLS__ void * p_libc_specific[_LIBC_TSD_KEY_N]; /* thread-specific data for libc */ 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 */ struct __res_state *p_resp; /* Pointer to resolver state */ #endif struct __res_state p_res; /* per-thread resolver state */ 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 */ 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 */ char p_condvar_avail; /* flag if conditional variable became avail */ char p_sem_avail; /* flag if semaphore became available */ 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 */ int p_inheritsched; /* copied from the thread attribute */ #if HP_TIMING_AVAIL hp_timing_t p_cpuclock_offset; /* Initial CPU clock for thread. */ #endif #ifdef __UCLIBC_HAS_TLS__ char *p_stackaddr; /* Stack address. */ #endif size_t p_alloca_cutoff; /* Maximum size which should be allocated using alloca() instead of malloc(). */ /* 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. */ /* 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. */ extern char *__pthread_initial_thread_bos; /* Descriptor of the initial thread */ extern struct _pthread_descr_struct __pthread_initial_thread; /* Limits of the thread manager stack. */ extern char *__pthread_manager_thread_bos; extern char *__pthread_manager_thread_tos; /* Descriptor of the manager thread */ extern struct _pthread_descr_struct __pthread_manager_thread; extern pthread_descr __pthread_manager_threadp attribute_hidden; /* 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; /* 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 /* 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__ ((pure)); static __inline__ pthread_descr thread_self (void) __attribute__ ((pure)); static __inline__ pthread_descr thread_self (void) { #ifdef THREAD_SELF return THREAD_SELF; #else char *sp = CURRENT_STACK_FRAME; 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 #ifdef _STACK_GROWS_DOWN return (pthread_descr)(((unsigned long)sp | (STACK_SIZE-1))+1) - 1; #else return (pthread_descr)((unsigned long)sp &~ (STACK_SIZE-1)); #endif #endif } #endif /* descr.h */ |