implement.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  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. // TODO: use clock_id
  226. clockid_t clock_id;
  227. };
  228. #define PTE_RWLOCK_MAGIC 0xfacade2
  229. struct pthread_rwlock_t_
  230. {
  231. pthread_mutex_t mtxExclusiveAccess;
  232. pthread_mutex_t mtxSharedAccessCompleted;
  233. pthread_cond_t cndSharedAccessCompleted;
  234. int nSharedAccessCount;
  235. int nExclusiveAccessCount;
  236. int nCompletedSharedAccessCount;
  237. int nMagic;
  238. };
  239. struct pthread_rwlockattr_t_
  240. {
  241. int pshared;
  242. };
  243. /*
  244. * MCS lock queue node - see pte_MCS_lock.c
  245. */
  246. struct pte_mcs_node_t_
  247. {
  248. struct pte_mcs_node_t_ **lock; /* ptr to tail of queue */
  249. struct pte_mcs_node_t_ *next; /* ptr to successor in queue */
  250. unsigned int readyFlag; /* set after lock is released by
  251. predecessor */
  252. unsigned int nextFlag; /* set after 'next' ptr is set by
  253. successor */
  254. };
  255. typedef struct pte_mcs_node_t_ pte_mcs_local_node_t;
  256. typedef struct pte_mcs_node_t_ *pte_mcs_lock_t;
  257. struct ThreadKeyAssoc
  258. {
  259. /*
  260. * Purpose:
  261. * This structure creates an association between a thread and a key.
  262. * It is used to implement the implicit invocation of a user defined
  263. * destroy routine for thread specific data registered by a user upon
  264. * exiting a thread.
  265. *
  266. * Graphically, the arrangement is as follows, where:
  267. *
  268. * K - Key with destructor
  269. * (head of chain is key->threads)
  270. * T - Thread that has called pthread_setspecific(Kn)
  271. * (head of chain is thread->keys)
  272. * A - Association. Each association is a node at the
  273. * intersection of two doubly-linked lists.
  274. *
  275. * T1 T2 T3
  276. * | | |
  277. * | | |
  278. * K1 -----+-----A-----A----->
  279. * | | |
  280. * | | |
  281. * K2 -----A-----A-----+----->
  282. * | | |
  283. * | | |
  284. * K3 -----A-----+-----A----->
  285. * | | |
  286. * | | |
  287. * V V V
  288. *
  289. * Access to the association is guarded by two locks: the key's
  290. * general lock (guarding the row) and the thread's general
  291. * lock (guarding the column). This avoids the need for a
  292. * dedicated lock for each association, which not only consumes
  293. * more handles but requires that: before the lock handle can
  294. * be released - both the key must be deleted and the thread
  295. * must have called the destructor. The two-lock arrangement
  296. * allows the resources to be freed as soon as either thread or
  297. * key is concluded.
  298. *
  299. * To avoid deadlock: whenever both locks are required, the key
  300. * and thread locks are always acquired in the order: key lock
  301. * then thread lock. An exception to this exists when a thread
  302. * calls the destructors, however this is done carefully to
  303. * avoid deadlock.
  304. *
  305. * An association is created when a thread first calls
  306. * pthread_setspecific() on a key that has a specified
  307. * destructor.
  308. *
  309. * An association is destroyed either immediately after the
  310. * thread calls the key destructor function on thread exit, or
  311. * when the key is deleted.
  312. *
  313. * Attributes:
  314. * thread
  315. * reference to the thread that owns the
  316. * association. This is actually the pointer to the
  317. * thread struct itself. Since the association is
  318. * destroyed before the thread exits, this can never
  319. * point to a different logical thread to the one that
  320. * created the assoc, i.e. after thread struct reuse.
  321. *
  322. * key
  323. * reference to the key that owns the association.
  324. *
  325. * nextKey
  326. * The pthread_t->keys attribute is the head of a
  327. * chain of associations that runs through the nextKey
  328. * link. This chain provides the 1 to many relationship
  329. * between a pthread_t and all pthread_key_t on which
  330. * it called pthread_setspecific.
  331. *
  332. * prevKey
  333. * Similarly.
  334. *
  335. * nextThread
  336. * The pthread_key_t->threads attribute is the head of
  337. * a chain of assoctiations that runs through the
  338. * nextThreads link. This chain provides the 1 to many
  339. * relationship between a pthread_key_t and all the
  340. * PThreads that have called pthread_setspecific for
  341. * this pthread_key_t.
  342. *
  343. * prevThread
  344. * Similarly.
  345. *
  346. * Notes:
  347. * 1) As soon as either the key or the thread is no longer
  348. * referencing the association, it can be destroyed. The
  349. * association will be removed from both chains.
  350. *
  351. * 2) An association is only created by
  352. * pthread_setspecific if the user provided a
  353. * destroyRoutine when they created the key.
  354. *
  355. *
  356. */
  357. pte_thread_t * thread;
  358. pthread_key_t key;
  359. ThreadKeyAssoc *nextKey;
  360. ThreadKeyAssoc *nextThread;
  361. ThreadKeyAssoc *prevKey;
  362. ThreadKeyAssoc *prevThread;
  363. };
  364. /*
  365. * Services available through EXCEPTION_PTE_SERVICES
  366. * and also used [as parameters to pte_throw()] as
  367. * generic exception selectors.
  368. */
  369. #define PTE_EPS_EXIT (1)
  370. #define PTE_EPS_CANCEL (2)
  371. /* Useful macros */
  372. #define PTE_MAX(a,b) ((a)<(b)?(b):(a))
  373. #define PTE_MIN(a,b) ((a)>(b)?(b):(a))
  374. /* Thread Reuse stack bottom marker. Must not be NULL or any valid pointer to memory. */
  375. #define PTE_THREAD_REUSE_EMPTY ((pte_thread_t *) 1)
  376. extern int pte_processInitialized;
  377. extern pte_thread_t * pte_threadReuseTop;
  378. extern pte_thread_t * pte_threadReuseBottom;
  379. extern pthread_key_t pte_selfThreadKey;
  380. extern pthread_key_t pte_cleanupKey;
  381. extern pthread_cond_t pte_cond_list_head;
  382. extern pthread_cond_t pte_cond_list_tail;
  383. extern int pte_mutex_default_kind;
  384. extern int pte_concurrency;
  385. extern int pte_features;
  386. extern pte_osMutexHandle pte_thread_reuse_lock;
  387. extern pte_osMutexHandle pte_mutex_test_init_lock;
  388. extern pte_osMutexHandle pte_cond_list_lock;
  389. extern pte_osMutexHandle pte_cond_test_init_lock;
  390. extern pte_osMutexHandle pte_rwlock_test_init_lock;
  391. extern pte_osMutexHandle pte_spinlock_test_init_lock;
  392. #ifdef __cplusplus
  393. extern "C"
  394. {
  395. #endif /* __cplusplus */
  396. /*
  397. * =====================
  398. * =====================
  399. * Forward Declarations
  400. * =====================
  401. * =====================
  402. */
  403. int pte_is_attr (const pthread_attr_t * attr);
  404. int pte_cond_check_need_init (pthread_cond_t * cond);
  405. int pte_mutex_check_need_init (pthread_mutex_t * mutex);
  406. int pte_rwlock_check_need_init (pthread_rwlock_t * rwlock);
  407. int pte_spinlock_check_need_init (pthread_spinlock_t * lock);
  408. int pte_processInitialize (void);
  409. void pte_processTerminate (void);
  410. void pte_threadDestroy (pthread_t tid);
  411. void pte_threadExitAndDestroy (pthread_t tid);
  412. void pte_pop_cleanup_all (int execute);
  413. pthread_t pte_new (void);
  414. pthread_t pte_threadReusePop (void);
  415. void pte_threadReusePush (pthread_t thread);
  416. int pte_getprocessors (int *count);
  417. int pte_setthreadpriority (pthread_t thread, int policy, int priority);
  418. void pte_rwlock_cancelwrwait (void *arg);
  419. int pte_threadStart (void *vthreadParms);
  420. void pte_callUserDestroyRoutines (pthread_t thread);
  421. int pte_tkAssocCreate (pte_thread_t * thread, pthread_key_t key);
  422. void pte_tkAssocDestroy (ThreadKeyAssoc * assoc);
  423. int sem_wait_nocancel (sem_t * sem);
  424. unsigned int pte_relmillisecs (const struct timespec * abstime);
  425. void pte_mcs_lock_acquire (pte_mcs_lock_t * lock, pte_mcs_local_node_t * node);
  426. void pte_mcs_lock_release (pte_mcs_local_node_t * node);
  427. /* Declared in private.c */
  428. void pte_throw (unsigned int exception);
  429. int pte_cancellable_wait (pte_osSemaphoreHandle semHandle, unsigned int* timeout);
  430. #define PTE_ATOMIC_EXCHANGE pte_osAtomicExchange
  431. #define PTE_ATOMIC_EXCHANGE_ADD pte_osAtomicExchangeAdd
  432. #define PTE_ATOMIC_COMPARE_EXCHANGE pte_osAtomicCompareExchange
  433. #define PTE_ATOMIC_DECREMENT pte_osAtomicDecrement
  434. #define PTE_ATOMIC_INCREMENT pte_osAtomicIncrement
  435. int pte_thread_detach_np();
  436. int pte_thread_detach_and_exit_np();
  437. #ifdef __cplusplus
  438. }
  439. #endif /* __cplusplus */
  440. #endif /* _IMPLEMENT_H */