implement.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. /*
  2. * implement.h
  3. *
  4. * Definitions that don't need to be public.
  5. *
  6. * Keeps all the internals out of pthread.h
  7. *
  8. * --------------------------------------------------------------------------
  9. *
  10. * Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
  11. * Copyright(C) 2008 Jason Schmidlapp
  12. *
  13. * Contact Email: [email protected]
  14. *
  15. *
  16. * Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
  17. * Copyright(C) 2008 Jason Schmidlapp
  18. *
  19. * Contact Email: [email protected]
  20. *
  21. *
  22. * Based upon Pthreads-win32 - POSIX Threads Library for Win32
  23. * Copyright(C) 1998 John E. Bossom
  24. * Copyright(C) 1999,2005 Pthreads-win32 contributors
  25. *
  26. * Contact Email: [email protected]
  27. *
  28. * The original list of contributors to the Pthreads-win32 project
  29. * is contained in the file CONTRIBUTORS.ptw32 included with the
  30. * source code distribution. The list can also be seen at the
  31. * following World Wide Web location:
  32. * http://sources.redhat.com/pthreads-win32/contributors.html
  33. *
  34. * This library is free software; you can redistribute it and/or
  35. * modify it under the terms of the GNU Lesser General Public
  36. * License as published by the Free Software Foundation; either
  37. * version 2 of the License, or (at your option) any later version.
  38. *
  39. * This library is distributed in the hope that it will be useful,
  40. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  41. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  42. * Lesser General Public License for more details.
  43. *
  44. * You should have received a copy of the GNU Lesser General Public
  45. * License along with this library in the file COPYING.LIB;
  46. * if not, write to the Free Software Foundation, Inc.,
  47. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  48. */
  49. #ifndef _IMPLEMENT_H
  50. #define _IMPLEMENT_H
  51. #include "pte_osal.h"
  52. /* use local include files during development */
  53. #include "semaphore.h"
  54. #include "sched.h"
  55. typedef enum
  56. {
  57. /*
  58. * This enumeration represents the state of the thread;
  59. * The thread is still "alive" if the numeric value of the
  60. * state is greater or equal "PThreadStateRunning".
  61. */
  62. PThreadStateInitial = 0, /* Thread not running */
  63. PThreadStateRunning, /* Thread alive & kicking */
  64. PThreadStateSuspended, /* Thread alive but suspended */
  65. PThreadStateCancelPending, /* Thread alive but is */
  66. /* has cancelation pending. */
  67. PThreadStateCanceling, /* Thread alive but is */
  68. /* in the process of terminating */
  69. /* due to a cancellation request */
  70. PThreadStateException, /* Thread alive but exiting */
  71. /* due to an exception */
  72. PThreadStateLast
  73. }
  74. PThreadState;
  75. typedef struct pte_thread_t_ pte_thread_t;
  76. struct pte_thread_t_
  77. {
  78. pte_osThreadHandle threadId; /* OS specific thread handle */
  79. pthread_t ptHandle; /* This thread's permanent pthread_t handle */
  80. pte_thread_t * prevReuse; /* Links threads on reuse stack */
  81. volatile PThreadState state;
  82. void *exitStatus;
  83. void *parms;
  84. int ptErrno;
  85. int detachState;
  86. pthread_mutex_t threadLock; /* Used for serialised access to public thread state */
  87. int sched_priority; /* As set, not as currently is */
  88. pthread_mutex_t cancelLock; /* Used for async-cancel safety */
  89. int cancelState;
  90. int cancelType;
  91. int cancelEvent;
  92. #ifdef PTE_CLEANUP_C
  93. jmp_buf start_mark;
  94. #endif /* PTE_CLEANUP_C */
  95. int implicit:
  96. 1;
  97. void *keys;
  98. void *nextAssoc;
  99. };
  100. /*
  101. * Special value to mark attribute objects as valid.
  102. */
  103. #define PTE_ATTR_VALID ((unsigned long) 0xC4C0FFEE)
  104. struct pthread_attr_t_
  105. {
  106. unsigned long valid;
  107. void *stackaddr;
  108. size_t stacksize;
  109. int detachstate;
  110. struct sched_param param;
  111. int inheritsched;
  112. int contentionscope;
  113. };
  114. /*
  115. * ====================
  116. * ====================
  117. * Semaphores, Mutexes and Condition Variables
  118. * ====================
  119. * ====================
  120. */
  121. struct sem_t_
  122. {
  123. int value;
  124. pthread_mutex_t lock;
  125. pte_osSemaphoreHandle sem;
  126. };
  127. #define PTE_OBJECT_AUTO_INIT ((void *) -1)
  128. #define PTE_OBJECT_INVALID 0
  129. struct pthread_mutex_t_
  130. {
  131. pte_osSemaphoreHandle handle;
  132. int lock_idx;
  133. /* Provides exclusive access to mutex state
  134. via the Interlocked* mechanism.
  135. 0: unlocked/free.
  136. 1: locked - no other waiters.
  137. -1: locked - with possible other waiters.
  138. */
  139. int recursive_count; /* Number of unlocks a thread needs to perform
  140. before the lock is released (recursive
  141. mutexes only). */
  142. int kind; /* Mutex type. */
  143. pthread_t ownerThread;
  144. };
  145. struct pthread_mutexattr_t_
  146. {
  147. int pshared;
  148. int kind;
  149. };
  150. /*
  151. * Possible values, other than PTE_OBJECT_INVALID,
  152. * for the "interlock" element in a spinlock.
  153. *
  154. * In this implementation, when a spinlock is initialised,
  155. * the number of cpus available to the process is checked.
  156. * If there is only one cpu then "interlock" is set equal to
  157. * PTE_SPIN_USE_MUTEX and u.mutex is a initialised mutex.
  158. * If the number of cpus is greater than 1 then "interlock"
  159. * is set equal to PTE_SPIN_UNLOCKED and the number is
  160. * stored in u.cpus. This arrangement allows the spinlock
  161. * routines to attempt an InterlockedCompareExchange on "interlock"
  162. * immediately and, if that fails, to try the inferior mutex.
  163. *
  164. * "u.cpus" isn't used for anything yet, but could be used at
  165. * some point to optimise spinlock behaviour.
  166. */
  167. #define PTE_SPIN_UNLOCKED (1)
  168. #define PTE_SPIN_LOCKED (2)
  169. #define PTE_SPIN_USE_MUTEX (3)
  170. struct pthread_spinlock_t_
  171. {
  172. int interlock; /* Locking element for multi-cpus. */
  173. union
  174. {
  175. int cpus; /* No. of cpus if multi cpus, or */
  176. pthread_mutex_t mutex; /* mutex if single cpu. */
  177. } u;
  178. };
  179. struct pthread_barrier_t_
  180. {
  181. unsigned int nCurrentBarrierHeight;
  182. unsigned int nInitialBarrierHeight;
  183. int iStep;
  184. int pshared;
  185. sem_t semBarrierBreeched[2];
  186. };
  187. struct pthread_barrierattr_t_
  188. {
  189. int pshared;
  190. };
  191. struct pthread_key_t_
  192. {
  193. unsigned key;
  194. void (*destructor) (void *);
  195. pthread_mutex_t keyLock;
  196. void *threads;
  197. };
  198. typedef struct ThreadParms ThreadParms;
  199. typedef struct ThreadKeyAssoc ThreadKeyAssoc;
  200. struct ThreadParms
  201. {
  202. pthread_t tid;
  203. void *(*start) (void *);
  204. void *arg;
  205. };
  206. struct pthread_cond_t_
  207. {
  208. long nWaitersBlocked; /* Number of threads blocked */
  209. long nWaitersGone; /* Number of threads timed out */
  210. long nWaitersToUnblock; /* Number of threads to unblock */
  211. sem_t semBlockQueue; /* Queue up threads waiting for the */
  212. /* condition to become signalled */
  213. sem_t semBlockLock; /* Semaphore that guards access to */
  214. /* | waiters blocked count/block queue */
  215. /* +-> Mandatory Sync.LEVEL-1 */
  216. pthread_mutex_t mtxUnblockLock; /* Mutex that guards access to */
  217. /* | waiters (to)unblock(ed) counts */
  218. /* +-> Optional* Sync.LEVEL-2 */
  219. pthread_cond_t next; /* Doubly linked list */
  220. pthread_cond_t prev;
  221. };
  222. struct pthread_condattr_t_
  223. {
  224. int pshared;
  225. };
  226. #define PTE_RWLOCK_MAGIC 0xfacade2
  227. struct pthread_rwlock_t_
  228. {
  229. pthread_mutex_t mtxExclusiveAccess;
  230. pthread_mutex_t mtxSharedAccessCompleted;
  231. pthread_cond_t cndSharedAccessCompleted;
  232. int nSharedAccessCount;
  233. int nExclusiveAccessCount;
  234. int nCompletedSharedAccessCount;
  235. int nMagic;
  236. };
  237. struct pthread_rwlockattr_t_
  238. {
  239. int pshared;
  240. };
  241. /*
  242. * MCS lock queue node - see pte_MCS_lock.c
  243. */
  244. struct pte_mcs_node_t_
  245. {
  246. struct pte_mcs_node_t_ **lock; /* ptr to tail of queue */
  247. struct pte_mcs_node_t_ *next; /* ptr to successor in queue */
  248. unsigned int readyFlag; /* set after lock is released by
  249. predecessor */
  250. unsigned int nextFlag; /* set after 'next' ptr is set by
  251. successor */
  252. };
  253. typedef struct pte_mcs_node_t_ pte_mcs_local_node_t;
  254. typedef struct pte_mcs_node_t_ *pte_mcs_lock_t;
  255. struct ThreadKeyAssoc
  256. {
  257. /*
  258. * Purpose:
  259. * This structure creates an association between a thread and a key.
  260. * It is used to implement the implicit invocation of a user defined
  261. * destroy routine for thread specific data registered by a user upon
  262. * exiting a thread.
  263. *
  264. * Graphically, the arrangement is as follows, where:
  265. *
  266. * K - Key with destructor
  267. * (head of chain is key->threads)
  268. * T - Thread that has called pthread_setspecific(Kn)
  269. * (head of chain is thread->keys)
  270. * A - Association. Each association is a node at the
  271. * intersection of two doubly-linked lists.
  272. *
  273. * T1 T2 T3
  274. * | | |
  275. * | | |
  276. * K1 -----+-----A-----A----->
  277. * | | |
  278. * | | |
  279. * K2 -----A-----A-----+----->
  280. * | | |
  281. * | | |
  282. * K3 -----A-----+-----A----->
  283. * | | |
  284. * | | |
  285. * V V V
  286. *
  287. * Access to the association is guarded by two locks: the key's
  288. * general lock (guarding the row) and the thread's general
  289. * lock (guarding the column). This avoids the need for a
  290. * dedicated lock for each association, which not only consumes
  291. * more handles but requires that: before the lock handle can
  292. * be released - both the key must be deleted and the thread
  293. * must have called the destructor. The two-lock arrangement
  294. * allows the resources to be freed as soon as either thread or
  295. * key is concluded.
  296. *
  297. * To avoid deadlock: whenever both locks are required, the key
  298. * and thread locks are always acquired in the order: key lock
  299. * then thread lock. An exception to this exists when a thread
  300. * calls the destructors, however this is done carefully to
  301. * avoid deadlock.
  302. *
  303. * An association is created when a thread first calls
  304. * pthread_setspecific() on a key that has a specified
  305. * destructor.
  306. *
  307. * An association is destroyed either immediately after the
  308. * thread calls the key destructor function on thread exit, or
  309. * when the key is deleted.
  310. *
  311. * Attributes:
  312. * thread
  313. * reference to the thread that owns the
  314. * association. This is actually the pointer to the
  315. * thread struct itself. Since the association is
  316. * destroyed before the thread exits, this can never
  317. * point to a different logical thread to the one that
  318. * created the assoc, i.e. after thread struct reuse.
  319. *
  320. * key
  321. * reference to the key that owns the association.
  322. *
  323. * nextKey
  324. * The pthread_t->keys attribute is the head of a
  325. * chain of associations that runs through the nextKey
  326. * link. This chain provides the 1 to many relationship
  327. * between a pthread_t and all pthread_key_t on which
  328. * it called pthread_setspecific.
  329. *
  330. * prevKey
  331. * Similarly.
  332. *
  333. * nextThread
  334. * The pthread_key_t->threads attribute is the head of
  335. * a chain of assoctiations that runs through the
  336. * nextThreads link. This chain provides the 1 to many
  337. * relationship between a pthread_key_t and all the
  338. * PThreads that have called pthread_setspecific for
  339. * this pthread_key_t.
  340. *
  341. * prevThread
  342. * Similarly.
  343. *
  344. * Notes:
  345. * 1) As soon as either the key or the thread is no longer
  346. * referencing the association, it can be destroyed. The
  347. * association will be removed from both chains.
  348. *
  349. * 2) An association is only created by
  350. * pthread_setspecific if the user provided a
  351. * destroyRoutine when they created the key.
  352. *
  353. *
  354. */
  355. pte_thread_t * thread;
  356. pthread_key_t key;
  357. ThreadKeyAssoc *nextKey;
  358. ThreadKeyAssoc *nextThread;
  359. ThreadKeyAssoc *prevKey;
  360. ThreadKeyAssoc *prevThread;
  361. };
  362. /*
  363. * Services available through EXCEPTION_PTE_SERVICES
  364. * and also used [as parameters to pte_throw()] as
  365. * generic exception selectors.
  366. */
  367. #define PTE_EPS_EXIT (1)
  368. #define PTE_EPS_CANCEL (2)
  369. /* Useful macros */
  370. #define PTE_MAX(a,b) ((a)<(b)?(b):(a))
  371. #define PTE_MIN(a,b) ((a)>(b)?(b):(a))
  372. /* Thread Reuse stack bottom marker. Must not be NULL or any valid pointer to memory. */
  373. #define PTE_THREAD_REUSE_EMPTY ((pte_thread_t *) 1)
  374. extern int pte_processInitialized;
  375. extern pte_thread_t * pte_threadReuseTop;
  376. extern pte_thread_t * pte_threadReuseBottom;
  377. extern pthread_key_t pte_selfThreadKey;
  378. extern pthread_key_t pte_cleanupKey;
  379. extern pthread_cond_t pte_cond_list_head;
  380. extern pthread_cond_t pte_cond_list_tail;
  381. extern int pte_mutex_default_kind;
  382. extern int pte_concurrency;
  383. extern int pte_features;
  384. extern pte_osMutexHandle pte_thread_reuse_lock;
  385. extern pte_osMutexHandle pte_mutex_test_init_lock;
  386. extern pte_osMutexHandle pte_cond_list_lock;
  387. extern pte_osMutexHandle pte_cond_test_init_lock;
  388. extern pte_osMutexHandle pte_rwlock_test_init_lock;
  389. extern pte_osMutexHandle pte_spinlock_test_init_lock;
  390. #ifdef __cplusplus
  391. extern "C"
  392. {
  393. #endif /* __cplusplus */
  394. /*
  395. * =====================
  396. * =====================
  397. * Forward Declarations
  398. * =====================
  399. * =====================
  400. */
  401. int pte_is_attr (const pthread_attr_t * attr);
  402. int pte_cond_check_need_init (pthread_cond_t * cond);
  403. int pte_mutex_check_need_init (pthread_mutex_t * mutex);
  404. int pte_rwlock_check_need_init (pthread_rwlock_t * rwlock);
  405. int pte_spinlock_check_need_init (pthread_spinlock_t * lock);
  406. int pte_processInitialize (void);
  407. void pte_processTerminate (void);
  408. void pte_threadDestroy (pthread_t tid);
  409. void pte_threadExitAndDestroy (pthread_t tid);
  410. void pte_pop_cleanup_all (int execute);
  411. pthread_t pte_new (void);
  412. pthread_t pte_threadReusePop (void);
  413. void pte_threadReusePush (pthread_t thread);
  414. int pte_getprocessors (int *count);
  415. int pte_setthreadpriority (pthread_t thread, int policy, int priority);
  416. void pte_rwlock_cancelwrwait (void *arg);
  417. int pte_threadStart (void *vthreadParms);
  418. void pte_callUserDestroyRoutines (pthread_t thread);
  419. int pte_tkAssocCreate (pte_thread_t * thread, pthread_key_t key);
  420. void pte_tkAssocDestroy (ThreadKeyAssoc * assoc);
  421. int sem_wait_nocancel (sem_t * sem);
  422. unsigned int pte_relmillisecs (const struct timespec * abstime);
  423. void pte_mcs_lock_acquire (pte_mcs_lock_t * lock, pte_mcs_local_node_t * node);
  424. void pte_mcs_lock_release (pte_mcs_local_node_t * node);
  425. /* Declared in private.c */
  426. void pte_throw (unsigned int exception);
  427. int pte_cancellable_wait (pte_osSemaphoreHandle semHandle, unsigned int* timeout);
  428. #define PTE_ATOMIC_EXCHANGE pte_osAtomicExchange
  429. #define PTE_ATOMIC_EXCHANGE_ADD pte_osAtomicExchangeAdd
  430. #define PTE_ATOMIC_COMPARE_EXCHANGE pte_osAtomicCompareExchange
  431. #define PTE_ATOMIC_DECREMENT pte_osAtomicDecrement
  432. #define PTE_ATOMIC_INCREMENT pte_osAtomicIncrement
  433. int pte_thread_detach_np();
  434. int pte_thread_detach_and_exit_np();
  435. #ifdef __cplusplus
  436. }
  437. #endif /* __cplusplus */
  438. #endif /* _IMPLEMENT_H */