xref: /relibc/pthreads-emb/implement.h (revision 7af8bdd54f609ebec03115d05be2bcc851986fad)
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