prthread.h 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #ifndef prthread_h___
  6. #define prthread_h___
  7. /*
  8. ** API for NSPR threads. On some architectures (Mac OS Classic
  9. ** notably) pre-emptibility is not guaranteed. Hard priority scheduling
  10. ** is not guaranteed, so programming using priority based synchronization
  11. ** is a no-no.
  12. **
  13. ** NSPR threads are scheduled based loosely on their client set priority.
  14. ** In general, a thread of a higher priority has a statistically better
  15. ** chance of running relative to threads of lower priority. However,
  16. ** NSPR uses multiple strategies to provide execution vehicles for thread
  17. ** abstraction of various host platforms. As it turns out, there is little
  18. ** NSPR can do to affect the scheduling attributes of "GLOBAL" threads.
  19. ** However, a semblance of GLOBAL threads is used to implement "LOCAL"
  20. ** threads. An arbitrary number of such LOCAL threads can be assigned to
  21. ** a single GLOBAL thread.
  22. **
  23. ** For scheduling, NSPR will attempt to run the highest priority LOCAL
  24. ** thread associated with a given GLOBAL thread. It is further assumed
  25. ** that the host OS will apply some form of "fair" scheduling on the
  26. ** GLOBAL threads.
  27. **
  28. ** Threads have a "system flag" which when set indicates the thread
  29. ** doesn't count for determining when the process should exit (the
  30. ** process exits when the last user thread exits).
  31. **
  32. ** Threads also have a "scope flag" which controls whether the threads
  33. ** are scheduled in the local scope or scheduled by the OS globally. This
  34. ** indicates whether a thread is permanently bound to a native OS thread.
  35. ** An unbound thread competes for scheduling resources in the same process.
  36. **
  37. ** Another flag is "state flag" which control whether the thread is joinable.
  38. ** It allows other threads to wait for the created thread to reach completion.
  39. **
  40. ** Threads can have "per-thread-data" attached to them. Each thread has a
  41. ** per-thread error number and error string which are updated when NSPR
  42. ** operations fail.
  43. */
  44. #include "prtypes.h"
  45. #include "prinrval.h"
  46. PR_BEGIN_EXTERN_C
  47. typedef struct PRThread PRThread;
  48. typedef struct PRThreadStack PRThreadStack;
  49. typedef enum PRThreadType {
  50. PR_USER_THREAD,
  51. PR_SYSTEM_THREAD
  52. } PRThreadType;
  53. typedef enum PRThreadScope {
  54. PR_LOCAL_THREAD,
  55. PR_GLOBAL_THREAD,
  56. PR_GLOBAL_BOUND_THREAD
  57. } PRThreadScope;
  58. typedef enum PRThreadState {
  59. PR_JOINABLE_THREAD,
  60. PR_UNJOINABLE_THREAD
  61. } PRThreadState;
  62. typedef enum PRThreadPriority
  63. {
  64. PR_PRIORITY_FIRST = 0, /* just a placeholder */
  65. PR_PRIORITY_LOW = 0, /* the lowest possible priority */
  66. PR_PRIORITY_NORMAL = 1, /* most common expected priority */
  67. PR_PRIORITY_HIGH = 2, /* slightly more aggressive scheduling */
  68. PR_PRIORITY_URGENT = 3, /* it does little good to have more than one */
  69. PR_PRIORITY_LAST = 3 /* this is just a placeholder */
  70. } PRThreadPriority;
  71. /*
  72. ** Create a new thread:
  73. ** "type" is the type of thread to create
  74. ** "start(arg)" will be invoked as the threads "main"
  75. ** "priority" will be created thread's priority
  76. ** "scope" will specify whether the thread is local or global
  77. ** "state" will specify whether the thread is joinable or not
  78. ** "stackSize" the size of the stack, in bytes. The value can be zero
  79. ** and then a machine specific stack size will be chosen.
  80. **
  81. ** This can return NULL if some kind of error occurs, such as if memory is
  82. ** tight.
  83. **
  84. ** If you want the thread to start up waiting for the creator to do
  85. ** something, enter a lock before creating the thread and then have the
  86. ** threads start routine enter and exit the same lock. When you are ready
  87. ** for the thread to run, exit the lock.
  88. **
  89. ** If you want to detect the completion of the created thread, the thread
  90. ** should be created joinable. Then, use PR_JoinThread to synchrnoize the
  91. ** termination of another thread.
  92. **
  93. ** When the start function returns the thread exits. If it is the last
  94. ** PR_USER_THREAD to exit then the process exits.
  95. */
  96. NSPR_API(PRThread*) PR_CreateThread(PRThreadType type,
  97. void (PR_CALLBACK *start)(void *arg),
  98. void *arg,
  99. PRThreadPriority priority,
  100. PRThreadScope scope,
  101. PRThreadState state,
  102. PRUint32 stackSize);
  103. /*
  104. ** Wait for thread termination:
  105. ** "thread" is the target thread
  106. **
  107. ** This can return PR_FAILURE if no joinable thread could be found
  108. ** corresponding to the specified target thread.
  109. **
  110. ** The calling thread is blocked until the target thread completes.
  111. ** Several threads cannot wait for the same thread to complete; one thread
  112. ** will operate successfully and others will terminate with an error PR_FAILURE.
  113. ** The calling thread will not be blocked if the target thread has already
  114. ** terminated.
  115. */
  116. NSPR_API(PRStatus) PR_JoinThread(PRThread *thread);
  117. /*
  118. ** Return the current thread object for the currently running code.
  119. ** Never returns NULL.
  120. */
  121. NSPR_API(PRThread*) PR_GetCurrentThread(void);
  122. #ifndef NO_NSPR_10_SUPPORT
  123. #define PR_CurrentThread() PR_GetCurrentThread() /* for nspr1.0 compat. */
  124. #endif /* NO_NSPR_10_SUPPORT */
  125. /*
  126. ** Get the priority of "thread".
  127. */
  128. NSPR_API(PRThreadPriority) PR_GetThreadPriority(const PRThread *thread);
  129. /*
  130. ** Change the priority of the "thread" to "priority".
  131. **
  132. ** PR_SetThreadPriority works in a best-effort manner. On some platforms a
  133. ** special privilege, such as root access, is required to change thread
  134. ** priorities, especially to raise thread priorities. If the caller doesn't
  135. ** have enough privileges to change thread priorites, the function has no
  136. ** effect except causing a future PR_GetThreadPriority call to return
  137. ** |priority|.
  138. */
  139. NSPR_API(void) PR_SetThreadPriority(PRThread *thread, PRThreadPriority priority);
  140. /*
  141. ** Set the name of the current thread, which will be visible in a debugger
  142. ** and accessible via a call to PR_GetThreadName().
  143. */
  144. NSPR_API(PRStatus) PR_SetCurrentThreadName(const char *name);
  145. /*
  146. ** Return the name of "thread", if set. Otherwise return NULL.
  147. */
  148. NSPR_API(const char *) PR_GetThreadName(const PRThread *thread);
  149. /*
  150. ** This routine returns a new index for per-thread-private data table.
  151. ** The index is visible to all threads within a process. This index can
  152. ** be used with the PR_SetThreadPrivate() and PR_GetThreadPrivate() routines
  153. ** to save and retrieve data associated with the index for a thread.
  154. **
  155. ** Each index is associationed with a destructor function ('dtor'). The function
  156. ** may be specified as NULL when the index is created. If it is not NULL, the
  157. ** function will be called when:
  158. ** - the thread exits and the private data for the associated index
  159. ** is not NULL,
  160. ** - new thread private data is set and the current private data is
  161. ** not NULL.
  162. **
  163. ** The index independently maintains specific values for each binding thread.
  164. ** A thread can only get access to its own thread-specific-data.
  165. **
  166. ** Upon a new index return the value associated with the index for all threads
  167. ** is NULL, and upon thread creation the value associated with all indices for
  168. ** that thread is NULL.
  169. **
  170. ** Returns PR_FAILURE if the total number of indices will exceed the maximun
  171. ** allowed.
  172. */
  173. typedef void (PR_CALLBACK *PRThreadPrivateDTOR)(void *priv);
  174. NSPR_API(PRStatus) PR_NewThreadPrivateIndex(
  175. PRUintn *newIndex, PRThreadPrivateDTOR destructor);
  176. /*
  177. ** Define some per-thread-private data.
  178. ** "tpdIndex" is an index into the per-thread private data table
  179. ** "priv" is the per-thread-private data
  180. **
  181. ** If the per-thread private data table has a previously registered
  182. ** destructor function and a non-NULL per-thread-private data value,
  183. ** the destructor function is invoked.
  184. **
  185. ** This can return PR_FAILURE if the index is invalid.
  186. */
  187. NSPR_API(PRStatus) PR_SetThreadPrivate(PRUintn tpdIndex, void *priv);
  188. /*
  189. ** Recover the per-thread-private data for the current thread. "tpdIndex" is
  190. ** the index into the per-thread private data table.
  191. **
  192. ** The returned value may be NULL which is indistinguishable from an error
  193. ** condition.
  194. **
  195. ** A thread can only get access to its own thread-specific-data.
  196. */
  197. NSPR_API(void*) PR_GetThreadPrivate(PRUintn tpdIndex);
  198. /*
  199. ** This routine sets the interrupt request for a target thread. The interrupt
  200. ** request remains in the thread's state until it is delivered exactly once
  201. ** or explicitly canceled.
  202. **
  203. ** A thread that has been interrupted will fail all NSPR blocking operations
  204. ** that return a PRStatus (I/O, waiting on a condition, etc).
  205. **
  206. ** PR_Interrupt may itself fail if the target thread is invalid.
  207. */
  208. NSPR_API(PRStatus) PR_Interrupt(PRThread *thread);
  209. /*
  210. ** Clear the interrupt request for the calling thread. If no such request
  211. ** is pending, this operation is a noop.
  212. */
  213. NSPR_API(void) PR_ClearInterrupt(void);
  214. /*
  215. ** Block the interrupt for the calling thread.
  216. */
  217. NSPR_API(void) PR_BlockInterrupt(void);
  218. /*
  219. ** Unblock the interrupt for the calling thread.
  220. */
  221. NSPR_API(void) PR_UnblockInterrupt(void);
  222. /*
  223. ** Make the current thread sleep until "ticks" time amount of time
  224. ** has expired. If "ticks" is PR_INTERVAL_NO_WAIT then the call is
  225. ** equivalent to calling PR_Yield. Calling PR_Sleep with an argument
  226. ** equivalent to PR_INTERVAL_NO_TIMEOUT is an error and will result
  227. ** in a PR_FAILURE error return.
  228. */
  229. NSPR_API(PRStatus) PR_Sleep(PRIntervalTime ticks);
  230. /*
  231. ** Get the scoping of this thread.
  232. */
  233. NSPR_API(PRThreadScope) PR_GetThreadScope(const PRThread *thread);
  234. /*
  235. ** Get the type of this thread.
  236. */
  237. NSPR_API(PRThreadType) PR_GetThreadType(const PRThread *thread);
  238. /*
  239. ** Get the join state of this thread.
  240. */
  241. NSPR_API(PRThreadState) PR_GetThreadState(const PRThread *thread);
  242. PR_END_EXTERN_C
  243. #endif /* prthread_h___ */