1062c5bc4SJason Schmidlapp /* 2062c5bc4SJason Schmidlapp * implement.h 3062c5bc4SJason Schmidlapp * 4062c5bc4SJason Schmidlapp * Definitions that don't need to be public. 5062c5bc4SJason Schmidlapp * 6062c5bc4SJason Schmidlapp * Keeps all the internals out of pthread.h 7062c5bc4SJason Schmidlapp * 8062c5bc4SJason Schmidlapp * -------------------------------------------------------------------------- 9062c5bc4SJason Schmidlapp * 10062c5bc4SJason Schmidlapp * Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems 11062c5bc4SJason Schmidlapp * Copyright(C) 2008 Jason Schmidlapp 12062c5bc4SJason Schmidlapp * 13062c5bc4SJason Schmidlapp * Contact Email: jschmidlapp@users.sourceforge.net 14062c5bc4SJason Schmidlapp * 15062c5bc4SJason Schmidlapp * 16062c5bc4SJason Schmidlapp * Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems 17062c5bc4SJason Schmidlapp * Copyright(C) 2008 Jason Schmidlapp 18062c5bc4SJason Schmidlapp * 19062c5bc4SJason Schmidlapp * Contact Email: jschmidlapp@users.sourceforge.net 20062c5bc4SJason Schmidlapp * 21062c5bc4SJason Schmidlapp * 22062c5bc4SJason Schmidlapp * Based upon Pthreads-win32 - POSIX Threads Library for Win32 23062c5bc4SJason Schmidlapp * Copyright(C) 1998 John E. Bossom 24062c5bc4SJason Schmidlapp * Copyright(C) 1999,2005 Pthreads-win32 contributors 25062c5bc4SJason Schmidlapp * 26062c5bc4SJason Schmidlapp * Contact Email: rpj@callisto.canberra.edu.au 27062c5bc4SJason Schmidlapp * 28062c5bc4SJason Schmidlapp * The original list of contributors to the Pthreads-win32 project 29062c5bc4SJason Schmidlapp * is contained in the file CONTRIBUTORS.ptw32 included with the 30062c5bc4SJason Schmidlapp * source code distribution. The list can also be seen at the 31062c5bc4SJason Schmidlapp * following World Wide Web location: 32062c5bc4SJason Schmidlapp * http://sources.redhat.com/pthreads-win32/contributors.html 33062c5bc4SJason Schmidlapp * 34062c5bc4SJason Schmidlapp * This library is free software; you can redistribute it and/or 35062c5bc4SJason Schmidlapp * modify it under the terms of the GNU Lesser General Public 36062c5bc4SJason Schmidlapp * License as published by the Free Software Foundation; either 37062c5bc4SJason Schmidlapp * version 2 of the License, or (at your option) any later version. 38062c5bc4SJason Schmidlapp * 39062c5bc4SJason Schmidlapp * This library is distributed in the hope that it will be useful, 40062c5bc4SJason Schmidlapp * but WITHOUT ANY WARRANTY; without even the implied warranty of 41062c5bc4SJason Schmidlapp * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 42062c5bc4SJason Schmidlapp * Lesser General Public License for more details. 43062c5bc4SJason Schmidlapp * 44062c5bc4SJason Schmidlapp * You should have received a copy of the GNU Lesser General Public 45062c5bc4SJason Schmidlapp * License along with this library in the file COPYING.LIB; 46062c5bc4SJason Schmidlapp * if not, write to the Free Software Foundation, Inc., 47062c5bc4SJason Schmidlapp * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 48062c5bc4SJason Schmidlapp */ 49062c5bc4SJason Schmidlapp 50062c5bc4SJason Schmidlapp 51062c5bc4SJason Schmidlapp #ifndef _IMPLEMENT_H 52062c5bc4SJason Schmidlapp #define _IMPLEMENT_H 53062c5bc4SJason Schmidlapp 54062c5bc4SJason Schmidlapp #include "pte_osal.h" 55062c5bc4SJason Schmidlapp 56062c5bc4SJason Schmidlapp /* use local include files during development */ 57062c5bc4SJason Schmidlapp #include "semaphore.h" 58062c5bc4SJason Schmidlapp #include "sched.h" 59062c5bc4SJason Schmidlapp 60062c5bc4SJason Schmidlapp 61062c5bc4SJason Schmidlapp typedef enum 62062c5bc4SJason Schmidlapp { 63062c5bc4SJason Schmidlapp /* 64062c5bc4SJason Schmidlapp * This enumeration represents the state of the thread; 65062c5bc4SJason Schmidlapp * The thread is still "alive" if the numeric value of the 66062c5bc4SJason Schmidlapp * state is greater or equal "PThreadStateRunning". 67062c5bc4SJason Schmidlapp */ 68062c5bc4SJason Schmidlapp PThreadStateInitial = 0, /* Thread not running */ 69062c5bc4SJason Schmidlapp PThreadStateRunning, /* Thread alive & kicking */ 70062c5bc4SJason Schmidlapp PThreadStateSuspended, /* Thread alive but suspended */ 71062c5bc4SJason Schmidlapp PThreadStateCancelPending, /* Thread alive but is */ 72062c5bc4SJason Schmidlapp /* has cancelation pending. */ 73062c5bc4SJason Schmidlapp PThreadStateCanceling, /* Thread alive but is */ 74062c5bc4SJason Schmidlapp /* in the process of terminating */ 75062c5bc4SJason Schmidlapp /* due to a cancellation request */ 76062c5bc4SJason Schmidlapp PThreadStateException, /* Thread alive but exiting */ 77062c5bc4SJason Schmidlapp /* due to an exception */ 78062c5bc4SJason Schmidlapp PThreadStateLast 79062c5bc4SJason Schmidlapp } 80062c5bc4SJason Schmidlapp PThreadState; 81062c5bc4SJason Schmidlapp 82062c5bc4SJason Schmidlapp 83062c5bc4SJason Schmidlapp typedef struct pte_thread_t_ pte_thread_t; 84062c5bc4SJason Schmidlapp 85062c5bc4SJason Schmidlapp struct pte_thread_t_ 86062c5bc4SJason Schmidlapp { 87062c5bc4SJason Schmidlapp pte_osThreadHandle threadId; /* OS specific thread handle */ 88062c5bc4SJason Schmidlapp pthread_t ptHandle; /* This thread's permanent pthread_t handle */ 89062c5bc4SJason Schmidlapp pte_thread_t * prevReuse; /* Links threads on reuse stack */ 90062c5bc4SJason Schmidlapp volatile PThreadState state; 91062c5bc4SJason Schmidlapp void *exitStatus; 92062c5bc4SJason Schmidlapp void *parms; 93062c5bc4SJason Schmidlapp int ptErrno; 94062c5bc4SJason Schmidlapp int detachState; 95062c5bc4SJason Schmidlapp pthread_mutex_t threadLock; /* Used for serialised access to public thread state */ 96062c5bc4SJason Schmidlapp int sched_priority; /* As set, not as currently is */ 97062c5bc4SJason Schmidlapp pthread_mutex_t cancelLock; /* Used for async-cancel safety */ 98062c5bc4SJason Schmidlapp int cancelState; 99062c5bc4SJason Schmidlapp int cancelType; 100062c5bc4SJason Schmidlapp int cancelEvent; 101062c5bc4SJason Schmidlapp #ifdef PTE_CLEANUP_C 102062c5bc4SJason Schmidlapp jmp_buf start_mark; 103062c5bc4SJason Schmidlapp #endif /* PTE_CLEANUP_C */ 104062c5bc4SJason Schmidlapp int implicit: 105062c5bc4SJason Schmidlapp 1; 106062c5bc4SJason Schmidlapp void *keys; 107062c5bc4SJason Schmidlapp void *nextAssoc; 108062c5bc4SJason Schmidlapp }; 109062c5bc4SJason Schmidlapp 110062c5bc4SJason Schmidlapp 111062c5bc4SJason Schmidlapp /* 112062c5bc4SJason Schmidlapp * Special value to mark attribute objects as valid. 113062c5bc4SJason Schmidlapp */ 114062c5bc4SJason Schmidlapp #define PTE_ATTR_VALID ((unsigned long) 0xC4C0FFEE) 115062c5bc4SJason Schmidlapp 116062c5bc4SJason Schmidlapp struct pthread_attr_t_ 117062c5bc4SJason Schmidlapp { 118062c5bc4SJason Schmidlapp unsigned long valid; 119062c5bc4SJason Schmidlapp void *stackaddr; 120062c5bc4SJason Schmidlapp size_t stacksize; 121062c5bc4SJason Schmidlapp int detachstate; 122062c5bc4SJason Schmidlapp struct sched_param param; 123062c5bc4SJason Schmidlapp int inheritsched; 124062c5bc4SJason Schmidlapp int contentionscope; 125062c5bc4SJason Schmidlapp }; 126062c5bc4SJason Schmidlapp 127062c5bc4SJason Schmidlapp 128062c5bc4SJason Schmidlapp /* 129062c5bc4SJason Schmidlapp * ==================== 130062c5bc4SJason Schmidlapp * ==================== 131062c5bc4SJason Schmidlapp * Semaphores, Mutexes and Condition Variables 132062c5bc4SJason Schmidlapp * ==================== 133062c5bc4SJason Schmidlapp * ==================== 134062c5bc4SJason Schmidlapp */ 135062c5bc4SJason Schmidlapp 136062c5bc4SJason Schmidlapp struct sem_t_ 137062c5bc4SJason Schmidlapp { 138062c5bc4SJason Schmidlapp int value; 139062c5bc4SJason Schmidlapp pthread_mutex_t lock; 140062c5bc4SJason Schmidlapp pte_osSemaphoreHandle sem; 141062c5bc4SJason Schmidlapp }; 142062c5bc4SJason Schmidlapp 143062c5bc4SJason Schmidlapp #define PTE_OBJECT_AUTO_INIT ((void *) -1) 144062c5bc4SJason Schmidlapp #define PTE_OBJECT_INVALID 0 145062c5bc4SJason Schmidlapp 146062c5bc4SJason Schmidlapp struct pthread_mutex_t_ 147062c5bc4SJason Schmidlapp { 148062c5bc4SJason Schmidlapp pte_osSemaphoreHandle handle; 149062c5bc4SJason Schmidlapp int lock_idx; 150062c5bc4SJason Schmidlapp /* Provides exclusive access to mutex state 151062c5bc4SJason Schmidlapp via the Interlocked* mechanism. 152062c5bc4SJason Schmidlapp 0: unlocked/free. 153062c5bc4SJason Schmidlapp 1: locked - no other waiters. 154062c5bc4SJason Schmidlapp -1: locked - with possible other waiters. 155062c5bc4SJason Schmidlapp */ 156062c5bc4SJason Schmidlapp int recursive_count; /* Number of unlocks a thread needs to perform 157062c5bc4SJason Schmidlapp before the lock is released (recursive 158062c5bc4SJason Schmidlapp mutexes only). */ 159062c5bc4SJason Schmidlapp int kind; /* Mutex type. */ 160062c5bc4SJason Schmidlapp pthread_t ownerThread; 161062c5bc4SJason Schmidlapp }; 162062c5bc4SJason Schmidlapp 163062c5bc4SJason Schmidlapp struct pthread_mutexattr_t_ 164062c5bc4SJason Schmidlapp { 165062c5bc4SJason Schmidlapp int pshared; 166062c5bc4SJason Schmidlapp int kind; 167062c5bc4SJason Schmidlapp }; 168062c5bc4SJason Schmidlapp 169062c5bc4SJason Schmidlapp /* 170062c5bc4SJason Schmidlapp * Possible values, other than PTE_OBJECT_INVALID, 171062c5bc4SJason Schmidlapp * for the "interlock" element in a spinlock. 172062c5bc4SJason Schmidlapp * 173062c5bc4SJason Schmidlapp * In this implementation, when a spinlock is initialised, 174062c5bc4SJason Schmidlapp * the number of cpus available to the process is checked. 175062c5bc4SJason Schmidlapp * If there is only one cpu then "interlock" is set equal to 176062c5bc4SJason Schmidlapp * PTE_SPIN_USE_MUTEX and u.mutex is a initialised mutex. 177062c5bc4SJason Schmidlapp * If the number of cpus is greater than 1 then "interlock" 178062c5bc4SJason Schmidlapp * is set equal to PTE_SPIN_UNLOCKED and the number is 179062c5bc4SJason Schmidlapp * stored in u.cpus. This arrangement allows the spinlock 180062c5bc4SJason Schmidlapp * routines to attempt an InterlockedCompareExchange on "interlock" 181062c5bc4SJason Schmidlapp * immediately and, if that fails, to try the inferior mutex. 182062c5bc4SJason Schmidlapp * 183062c5bc4SJason Schmidlapp * "u.cpus" isn't used for anything yet, but could be used at 184062c5bc4SJason Schmidlapp * some point to optimise spinlock behaviour. 185062c5bc4SJason Schmidlapp */ 186062c5bc4SJason Schmidlapp #define PTE_SPIN_UNLOCKED (1) 187062c5bc4SJason Schmidlapp #define PTE_SPIN_LOCKED (2) 188062c5bc4SJason Schmidlapp #define PTE_SPIN_USE_MUTEX (3) 189062c5bc4SJason Schmidlapp 190062c5bc4SJason Schmidlapp struct pthread_spinlock_t_ 191062c5bc4SJason Schmidlapp { 192062c5bc4SJason Schmidlapp int interlock; /* Locking element for multi-cpus. */ 193062c5bc4SJason Schmidlapp union 194062c5bc4SJason Schmidlapp { 195062c5bc4SJason Schmidlapp int cpus; /* No. of cpus if multi cpus, or */ 196062c5bc4SJason Schmidlapp pthread_mutex_t mutex; /* mutex if single cpu. */ 197062c5bc4SJason Schmidlapp } u; 198062c5bc4SJason Schmidlapp }; 199062c5bc4SJason Schmidlapp 200062c5bc4SJason Schmidlapp struct pthread_barrier_t_ 201062c5bc4SJason Schmidlapp { 202062c5bc4SJason Schmidlapp unsigned int nCurrentBarrierHeight; 203062c5bc4SJason Schmidlapp unsigned int nInitialBarrierHeight; 204062c5bc4SJason Schmidlapp int iStep; 205062c5bc4SJason Schmidlapp int pshared; 206062c5bc4SJason Schmidlapp sem_t semBarrierBreeched[2]; 207062c5bc4SJason Schmidlapp }; 208062c5bc4SJason Schmidlapp 209062c5bc4SJason Schmidlapp struct pthread_barrierattr_t_ 210062c5bc4SJason Schmidlapp { 211062c5bc4SJason Schmidlapp int pshared; 212062c5bc4SJason Schmidlapp }; 213062c5bc4SJason Schmidlapp 214062c5bc4SJason Schmidlapp struct pthread_key_t_ 215062c5bc4SJason Schmidlapp { 216062c5bc4SJason Schmidlapp unsigned key; 217062c5bc4SJason Schmidlapp void (*destructor) (void *); 218062c5bc4SJason Schmidlapp pthread_mutex_t keyLock; 219062c5bc4SJason Schmidlapp void *threads; 220062c5bc4SJason Schmidlapp }; 221062c5bc4SJason Schmidlapp 222062c5bc4SJason Schmidlapp 223062c5bc4SJason Schmidlapp typedef struct ThreadParms ThreadParms; 224062c5bc4SJason Schmidlapp typedef struct ThreadKeyAssoc ThreadKeyAssoc; 225062c5bc4SJason Schmidlapp 226062c5bc4SJason Schmidlapp struct ThreadParms 227062c5bc4SJason Schmidlapp { 228062c5bc4SJason Schmidlapp pthread_t tid; 229062c5bc4SJason Schmidlapp void *(*start) (void *); 230062c5bc4SJason Schmidlapp void *arg; 231062c5bc4SJason Schmidlapp }; 232062c5bc4SJason Schmidlapp 233062c5bc4SJason Schmidlapp struct pthread_cond_t_ 234062c5bc4SJason Schmidlapp { 235062c5bc4SJason Schmidlapp long nWaitersBlocked; /* Number of threads blocked */ 236062c5bc4SJason Schmidlapp long nWaitersGone; /* Number of threads timed out */ 237062c5bc4SJason Schmidlapp long nWaitersToUnblock; /* Number of threads to unblock */ 238062c5bc4SJason Schmidlapp sem_t semBlockQueue; /* Queue up threads waiting for the */ 239062c5bc4SJason Schmidlapp /* condition to become signalled */ 240062c5bc4SJason Schmidlapp sem_t semBlockLock; /* Semaphore that guards access to */ 241062c5bc4SJason Schmidlapp /* | waiters blocked count/block queue */ 242062c5bc4SJason Schmidlapp /* +-> Mandatory Sync.LEVEL-1 */ 243062c5bc4SJason Schmidlapp pthread_mutex_t mtxUnblockLock; /* Mutex that guards access to */ 244062c5bc4SJason Schmidlapp /* | waiters (to)unblock(ed) counts */ 245062c5bc4SJason Schmidlapp /* +-> Optional* Sync.LEVEL-2 */ 246062c5bc4SJason Schmidlapp pthread_cond_t next; /* Doubly linked list */ 247062c5bc4SJason Schmidlapp pthread_cond_t prev; 248062c5bc4SJason Schmidlapp }; 249062c5bc4SJason Schmidlapp 250062c5bc4SJason Schmidlapp 251062c5bc4SJason Schmidlapp struct pthread_condattr_t_ 252062c5bc4SJason Schmidlapp { 253062c5bc4SJason Schmidlapp int pshared; 254*7af8bdd5SJeremy Soller // TODO: use clock_id 255*7af8bdd5SJeremy Soller clockid_t clock_id; 256062c5bc4SJason Schmidlapp }; 257062c5bc4SJason Schmidlapp 258062c5bc4SJason Schmidlapp #define PTE_RWLOCK_MAGIC 0xfacade2 259062c5bc4SJason Schmidlapp 260062c5bc4SJason Schmidlapp struct pthread_rwlock_t_ 261062c5bc4SJason Schmidlapp { 262062c5bc4SJason Schmidlapp pthread_mutex_t mtxExclusiveAccess; 263062c5bc4SJason Schmidlapp pthread_mutex_t mtxSharedAccessCompleted; 264062c5bc4SJason Schmidlapp pthread_cond_t cndSharedAccessCompleted; 265062c5bc4SJason Schmidlapp int nSharedAccessCount; 266062c5bc4SJason Schmidlapp int nExclusiveAccessCount; 267062c5bc4SJason Schmidlapp int nCompletedSharedAccessCount; 268062c5bc4SJason Schmidlapp int nMagic; 269062c5bc4SJason Schmidlapp }; 270062c5bc4SJason Schmidlapp 271062c5bc4SJason Schmidlapp struct pthread_rwlockattr_t_ 272062c5bc4SJason Schmidlapp { 273062c5bc4SJason Schmidlapp int pshared; 274062c5bc4SJason Schmidlapp }; 275062c5bc4SJason Schmidlapp 276062c5bc4SJason Schmidlapp /* 277062c5bc4SJason Schmidlapp * MCS lock queue node - see pte_MCS_lock.c 278062c5bc4SJason Schmidlapp */ 279062c5bc4SJason Schmidlapp struct pte_mcs_node_t_ 280062c5bc4SJason Schmidlapp { 281062c5bc4SJason Schmidlapp struct pte_mcs_node_t_ **lock; /* ptr to tail of queue */ 282062c5bc4SJason Schmidlapp struct pte_mcs_node_t_ *next; /* ptr to successor in queue */ 283062c5bc4SJason Schmidlapp unsigned int readyFlag; /* set after lock is released by 284062c5bc4SJason Schmidlapp predecessor */ 285062c5bc4SJason Schmidlapp unsigned int nextFlag; /* set after 'next' ptr is set by 286062c5bc4SJason Schmidlapp successor */ 287062c5bc4SJason Schmidlapp }; 288062c5bc4SJason Schmidlapp 289062c5bc4SJason Schmidlapp typedef struct pte_mcs_node_t_ pte_mcs_local_node_t; 290062c5bc4SJason Schmidlapp typedef struct pte_mcs_node_t_ *pte_mcs_lock_t; 291062c5bc4SJason Schmidlapp 292062c5bc4SJason Schmidlapp 293062c5bc4SJason Schmidlapp struct ThreadKeyAssoc 294062c5bc4SJason Schmidlapp { 295062c5bc4SJason Schmidlapp /* 296062c5bc4SJason Schmidlapp * Purpose: 297062c5bc4SJason Schmidlapp * This structure creates an association between a thread and a key. 298062c5bc4SJason Schmidlapp * It is used to implement the implicit invocation of a user defined 299062c5bc4SJason Schmidlapp * destroy routine for thread specific data registered by a user upon 300062c5bc4SJason Schmidlapp * exiting a thread. 301062c5bc4SJason Schmidlapp * 302062c5bc4SJason Schmidlapp * Graphically, the arrangement is as follows, where: 303062c5bc4SJason Schmidlapp * 304062c5bc4SJason Schmidlapp * K - Key with destructor 305062c5bc4SJason Schmidlapp * (head of chain is key->threads) 306062c5bc4SJason Schmidlapp * T - Thread that has called pthread_setspecific(Kn) 307062c5bc4SJason Schmidlapp * (head of chain is thread->keys) 308062c5bc4SJason Schmidlapp * A - Association. Each association is a node at the 309062c5bc4SJason Schmidlapp * intersection of two doubly-linked lists. 310062c5bc4SJason Schmidlapp * 311062c5bc4SJason Schmidlapp * T1 T2 T3 312062c5bc4SJason Schmidlapp * | | | 313062c5bc4SJason Schmidlapp * | | | 314062c5bc4SJason Schmidlapp * K1 -----+-----A-----A-----> 315062c5bc4SJason Schmidlapp * | | | 316062c5bc4SJason Schmidlapp * | | | 317062c5bc4SJason Schmidlapp * K2 -----A-----A-----+-----> 318062c5bc4SJason Schmidlapp * | | | 319062c5bc4SJason Schmidlapp * | | | 320062c5bc4SJason Schmidlapp * K3 -----A-----+-----A-----> 321062c5bc4SJason Schmidlapp * | | | 322062c5bc4SJason Schmidlapp * | | | 323062c5bc4SJason Schmidlapp * V V V 324062c5bc4SJason Schmidlapp * 325062c5bc4SJason Schmidlapp * Access to the association is guarded by two locks: the key's 326062c5bc4SJason Schmidlapp * general lock (guarding the row) and the thread's general 327062c5bc4SJason Schmidlapp * lock (guarding the column). This avoids the need for a 328062c5bc4SJason Schmidlapp * dedicated lock for each association, which not only consumes 329062c5bc4SJason Schmidlapp * more handles but requires that: before the lock handle can 330062c5bc4SJason Schmidlapp * be released - both the key must be deleted and the thread 331062c5bc4SJason Schmidlapp * must have called the destructor. The two-lock arrangement 332062c5bc4SJason Schmidlapp * allows the resources to be freed as soon as either thread or 333062c5bc4SJason Schmidlapp * key is concluded. 334062c5bc4SJason Schmidlapp * 335062c5bc4SJason Schmidlapp * To avoid deadlock: whenever both locks are required, the key 336062c5bc4SJason Schmidlapp * and thread locks are always acquired in the order: key lock 337062c5bc4SJason Schmidlapp * then thread lock. An exception to this exists when a thread 338062c5bc4SJason Schmidlapp * calls the destructors, however this is done carefully to 339062c5bc4SJason Schmidlapp * avoid deadlock. 340062c5bc4SJason Schmidlapp * 341062c5bc4SJason Schmidlapp * An association is created when a thread first calls 342062c5bc4SJason Schmidlapp * pthread_setspecific() on a key that has a specified 343062c5bc4SJason Schmidlapp * destructor. 344062c5bc4SJason Schmidlapp * 345062c5bc4SJason Schmidlapp * An association is destroyed either immediately after the 346062c5bc4SJason Schmidlapp * thread calls the key destructor function on thread exit, or 347062c5bc4SJason Schmidlapp * when the key is deleted. 348062c5bc4SJason Schmidlapp * 349062c5bc4SJason Schmidlapp * Attributes: 350062c5bc4SJason Schmidlapp * thread 351062c5bc4SJason Schmidlapp * reference to the thread that owns the 352062c5bc4SJason Schmidlapp * association. This is actually the pointer to the 353062c5bc4SJason Schmidlapp * thread struct itself. Since the association is 354062c5bc4SJason Schmidlapp * destroyed before the thread exits, this can never 355062c5bc4SJason Schmidlapp * point to a different logical thread to the one that 356062c5bc4SJason Schmidlapp * created the assoc, i.e. after thread struct reuse. 357062c5bc4SJason Schmidlapp * 358062c5bc4SJason Schmidlapp * key 359062c5bc4SJason Schmidlapp * reference to the key that owns the association. 360062c5bc4SJason Schmidlapp * 361062c5bc4SJason Schmidlapp * nextKey 362062c5bc4SJason Schmidlapp * The pthread_t->keys attribute is the head of a 363062c5bc4SJason Schmidlapp * chain of associations that runs through the nextKey 364062c5bc4SJason Schmidlapp * link. This chain provides the 1 to many relationship 365062c5bc4SJason Schmidlapp * between a pthread_t and all pthread_key_t on which 366062c5bc4SJason Schmidlapp * it called pthread_setspecific. 367062c5bc4SJason Schmidlapp * 368062c5bc4SJason Schmidlapp * prevKey 369062c5bc4SJason Schmidlapp * Similarly. 370062c5bc4SJason Schmidlapp * 371062c5bc4SJason Schmidlapp * nextThread 372062c5bc4SJason Schmidlapp * The pthread_key_t->threads attribute is the head of 373062c5bc4SJason Schmidlapp * a chain of assoctiations that runs through the 374062c5bc4SJason Schmidlapp * nextThreads link. This chain provides the 1 to many 375062c5bc4SJason Schmidlapp * relationship between a pthread_key_t and all the 376062c5bc4SJason Schmidlapp * PThreads that have called pthread_setspecific for 377062c5bc4SJason Schmidlapp * this pthread_key_t. 378062c5bc4SJason Schmidlapp * 379062c5bc4SJason Schmidlapp * prevThread 380062c5bc4SJason Schmidlapp * Similarly. 381062c5bc4SJason Schmidlapp * 382062c5bc4SJason Schmidlapp * Notes: 383062c5bc4SJason Schmidlapp * 1) As soon as either the key or the thread is no longer 384062c5bc4SJason Schmidlapp * referencing the association, it can be destroyed. The 385062c5bc4SJason Schmidlapp * association will be removed from both chains. 386062c5bc4SJason Schmidlapp * 387062c5bc4SJason Schmidlapp * 2) An association is only created by 388062c5bc4SJason Schmidlapp * pthread_setspecific if the user provided a 389062c5bc4SJason Schmidlapp * destroyRoutine when they created the key. 390062c5bc4SJason Schmidlapp * 391062c5bc4SJason Schmidlapp * 392062c5bc4SJason Schmidlapp */ 393062c5bc4SJason Schmidlapp pte_thread_t * thread; 394062c5bc4SJason Schmidlapp pthread_key_t key; 395062c5bc4SJason Schmidlapp ThreadKeyAssoc *nextKey; 396062c5bc4SJason Schmidlapp ThreadKeyAssoc *nextThread; 397062c5bc4SJason Schmidlapp ThreadKeyAssoc *prevKey; 398062c5bc4SJason Schmidlapp ThreadKeyAssoc *prevThread; 399062c5bc4SJason Schmidlapp }; 400062c5bc4SJason Schmidlapp 401062c5bc4SJason Schmidlapp /* 402062c5bc4SJason Schmidlapp * Services available through EXCEPTION_PTE_SERVICES 403062c5bc4SJason Schmidlapp * and also used [as parameters to pte_throw()] as 404062c5bc4SJason Schmidlapp * generic exception selectors. 405062c5bc4SJason Schmidlapp */ 406062c5bc4SJason Schmidlapp 407062c5bc4SJason Schmidlapp #define PTE_EPS_EXIT (1) 408062c5bc4SJason Schmidlapp #define PTE_EPS_CANCEL (2) 409062c5bc4SJason Schmidlapp 410062c5bc4SJason Schmidlapp 411062c5bc4SJason Schmidlapp /* Useful macros */ 412062c5bc4SJason Schmidlapp #define PTE_MAX(a,b) ((a)<(b)?(b):(a)) 413062c5bc4SJason Schmidlapp #define PTE_MIN(a,b) ((a)>(b)?(b):(a)) 414062c5bc4SJason Schmidlapp 415062c5bc4SJason Schmidlapp 416062c5bc4SJason Schmidlapp /* Thread Reuse stack bottom marker. Must not be NULL or any valid pointer to memory. */ 417062c5bc4SJason Schmidlapp #define PTE_THREAD_REUSE_EMPTY ((pte_thread_t *) 1) 418062c5bc4SJason Schmidlapp 419062c5bc4SJason Schmidlapp extern int pte_processInitialized; 420062c5bc4SJason Schmidlapp extern pte_thread_t * pte_threadReuseTop; 421062c5bc4SJason Schmidlapp extern pte_thread_t * pte_threadReuseBottom; 422062c5bc4SJason Schmidlapp extern pthread_key_t pte_selfThreadKey; 423062c5bc4SJason Schmidlapp extern pthread_key_t pte_cleanupKey; 424062c5bc4SJason Schmidlapp extern pthread_cond_t pte_cond_list_head; 425062c5bc4SJason Schmidlapp extern pthread_cond_t pte_cond_list_tail; 426062c5bc4SJason Schmidlapp 427062c5bc4SJason Schmidlapp extern int pte_mutex_default_kind; 428062c5bc4SJason Schmidlapp 429062c5bc4SJason Schmidlapp extern int pte_concurrency; 430062c5bc4SJason Schmidlapp 431062c5bc4SJason Schmidlapp extern int pte_features; 432062c5bc4SJason Schmidlapp 433062c5bc4SJason Schmidlapp extern pte_osMutexHandle pte_thread_reuse_lock; 434062c5bc4SJason Schmidlapp extern pte_osMutexHandle pte_mutex_test_init_lock; 435062c5bc4SJason Schmidlapp extern pte_osMutexHandle pte_cond_list_lock; 436062c5bc4SJason Schmidlapp extern pte_osMutexHandle pte_cond_test_init_lock; 437062c5bc4SJason Schmidlapp extern pte_osMutexHandle pte_rwlock_test_init_lock; 438062c5bc4SJason Schmidlapp extern pte_osMutexHandle pte_spinlock_test_init_lock; 439062c5bc4SJason Schmidlapp 440062c5bc4SJason Schmidlapp 441062c5bc4SJason Schmidlapp #ifdef __cplusplus 442062c5bc4SJason Schmidlapp extern "C" 443062c5bc4SJason Schmidlapp { 444062c5bc4SJason Schmidlapp #endif /* __cplusplus */ 445062c5bc4SJason Schmidlapp 446062c5bc4SJason Schmidlapp /* 447062c5bc4SJason Schmidlapp * ===================== 448062c5bc4SJason Schmidlapp * ===================== 449062c5bc4SJason Schmidlapp * Forward Declarations 450062c5bc4SJason Schmidlapp * ===================== 451062c5bc4SJason Schmidlapp * ===================== 452062c5bc4SJason Schmidlapp */ 453062c5bc4SJason Schmidlapp 454062c5bc4SJason Schmidlapp int pte_is_attr (const pthread_attr_t * attr); 455062c5bc4SJason Schmidlapp 456062c5bc4SJason Schmidlapp int pte_cond_check_need_init (pthread_cond_t * cond); 457062c5bc4SJason Schmidlapp int pte_mutex_check_need_init (pthread_mutex_t * mutex); 458062c5bc4SJason Schmidlapp int pte_rwlock_check_need_init (pthread_rwlock_t * rwlock); 459062c5bc4SJason Schmidlapp int pte_spinlock_check_need_init (pthread_spinlock_t * lock); 460062c5bc4SJason Schmidlapp 461062c5bc4SJason Schmidlapp int pte_processInitialize (void); 462062c5bc4SJason Schmidlapp 463062c5bc4SJason Schmidlapp void pte_processTerminate (void); 464062c5bc4SJason Schmidlapp 465062c5bc4SJason Schmidlapp void pte_threadDestroy (pthread_t tid); 466062c5bc4SJason Schmidlapp void pte_threadExitAndDestroy (pthread_t tid); 467062c5bc4SJason Schmidlapp 468062c5bc4SJason Schmidlapp void pte_pop_cleanup_all (int execute); 469062c5bc4SJason Schmidlapp 470062c5bc4SJason Schmidlapp pthread_t pte_new (void); 471062c5bc4SJason Schmidlapp 472062c5bc4SJason Schmidlapp pthread_t pte_threadReusePop (void); 473062c5bc4SJason Schmidlapp 474062c5bc4SJason Schmidlapp void pte_threadReusePush (pthread_t thread); 475062c5bc4SJason Schmidlapp 476062c5bc4SJason Schmidlapp int pte_getprocessors (int *count); 477062c5bc4SJason Schmidlapp 478062c5bc4SJason Schmidlapp int pte_setthreadpriority (pthread_t thread, int policy, int priority); 479062c5bc4SJason Schmidlapp 480062c5bc4SJason Schmidlapp void pte_rwlock_cancelwrwait (void *arg); 481062c5bc4SJason Schmidlapp 482062c5bc4SJason Schmidlapp int pte_threadStart (void *vthreadParms); 483062c5bc4SJason Schmidlapp 484062c5bc4SJason Schmidlapp void pte_callUserDestroyRoutines (pthread_t thread); 485062c5bc4SJason Schmidlapp 486062c5bc4SJason Schmidlapp int pte_tkAssocCreate (pte_thread_t * thread, pthread_key_t key); 487062c5bc4SJason Schmidlapp 488062c5bc4SJason Schmidlapp void pte_tkAssocDestroy (ThreadKeyAssoc * assoc); 489062c5bc4SJason Schmidlapp 490062c5bc4SJason Schmidlapp int sem_wait_nocancel (sem_t * sem); 491062c5bc4SJason Schmidlapp 492062c5bc4SJason Schmidlapp unsigned int pte_relmillisecs (const struct timespec * abstime); 493062c5bc4SJason Schmidlapp 494062c5bc4SJason Schmidlapp void pte_mcs_lock_acquire (pte_mcs_lock_t * lock, pte_mcs_local_node_t * node); 495062c5bc4SJason Schmidlapp 496062c5bc4SJason Schmidlapp void pte_mcs_lock_release (pte_mcs_local_node_t * node); 497062c5bc4SJason Schmidlapp 498062c5bc4SJason Schmidlapp /* Declared in private.c */ 499062c5bc4SJason Schmidlapp void pte_throw (unsigned int exception); 500062c5bc4SJason Schmidlapp 501062c5bc4SJason Schmidlapp int pte_cancellable_wait (pte_osSemaphoreHandle semHandle, unsigned int* timeout); 502062c5bc4SJason Schmidlapp 503062c5bc4SJason Schmidlapp #define PTE_ATOMIC_EXCHANGE pte_osAtomicExchange 504062c5bc4SJason Schmidlapp #define PTE_ATOMIC_EXCHANGE_ADD pte_osAtomicExchangeAdd 505062c5bc4SJason Schmidlapp #define PTE_ATOMIC_COMPARE_EXCHANGE pte_osAtomicCompareExchange 506062c5bc4SJason Schmidlapp #define PTE_ATOMIC_DECREMENT pte_osAtomicDecrement 507062c5bc4SJason Schmidlapp #define PTE_ATOMIC_INCREMENT pte_osAtomicIncrement 508062c5bc4SJason Schmidlapp 509062c5bc4SJason Schmidlapp int pte_thread_detach_np(); 510062c5bc4SJason Schmidlapp int pte_thread_detach_and_exit_np(); 511062c5bc4SJason Schmidlapp 512062c5bc4SJason Schmidlapp 513062c5bc4SJason Schmidlapp #ifdef __cplusplus 514062c5bc4SJason Schmidlapp } 515062c5bc4SJason Schmidlapp #endif /* __cplusplus */ 516062c5bc4SJason Schmidlapp 517062c5bc4SJason Schmidlapp 518062c5bc4SJason Schmidlapp #endif /* _IMPLEMENT_H */ 519