1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
---|
2 | /* ***** BEGIN LICENSE BLOCK *****
|
---|
3 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
---|
4 | *
|
---|
5 | * The contents of this file are subject to the Mozilla Public License Version
|
---|
6 | * 1.1 (the "License"); you may not use this file except in compliance with
|
---|
7 | * the License. You may obtain a copy of the License at
|
---|
8 | * http://www.mozilla.org/MPL/
|
---|
9 | *
|
---|
10 | * Software distributed under the License is distributed on an "AS IS" basis,
|
---|
11 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
---|
12 | * for the specific language governing rights and limitations under the
|
---|
13 | * License.
|
---|
14 | *
|
---|
15 | * The Original Code is the Netscape Portable Runtime (NSPR).
|
---|
16 | *
|
---|
17 | * The Initial Developer of the Original Code is
|
---|
18 | * Netscape Communications Corporation.
|
---|
19 | * Portions created by the Initial Developer are Copyright (C) 1998-2000
|
---|
20 | * the Initial Developer. All Rights Reserved.
|
---|
21 | *
|
---|
22 | * Contributor(s):
|
---|
23 | *
|
---|
24 | * Alternatively, the contents of this file may be used under the terms of
|
---|
25 | * either the GNU General Public License Version 2 or later (the "GPL"), or
|
---|
26 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
---|
27 | * in which case the provisions of the GPL or the LGPL are applicable instead
|
---|
28 | * of those above. If you wish to allow use of your version of this file only
|
---|
29 | * under the terms of either the GPL or the LGPL, and not to allow others to
|
---|
30 | * use your version of this file under the terms of the MPL, indicate your
|
---|
31 | * decision by deleting the provisions above and replace them with the notice
|
---|
32 | * and other provisions required by the GPL or the LGPL. If you do not delete
|
---|
33 | * the provisions above, a recipient may use your version of this file under
|
---|
34 | * the terms of any one of the MPL, the GPL or the LGPL.
|
---|
35 | *
|
---|
36 | * ***** END LICENSE BLOCK ***** */
|
---|
37 |
|
---|
38 | #ifndef prthread_h___
|
---|
39 | #define prthread_h___
|
---|
40 |
|
---|
41 | /*
|
---|
42 | ** API for NSPR threads. On some architectures (MAC and WIN16
|
---|
43 | ** notably) pre-emptibility is not guaranteed. Hard priority scheduling
|
---|
44 | ** is not guaranteed, so programming using priority based synchronization
|
---|
45 | ** is a no-no.
|
---|
46 | **
|
---|
47 | ** NSPR threads are scheduled based loosly on their client set priority.
|
---|
48 | ** In general, a thread of a higher priority has a statistically better
|
---|
49 | ** chance of running relative to threads of lower priority. However,
|
---|
50 | ** NSPR uses multiple strategies to provide execution vehicles for thread
|
---|
51 | ** abstraction of various host platforms. As it turns out, there is little
|
---|
52 | ** NSPR can do to affect the scheduling attributes of "GLOBAL" threads.
|
---|
53 | ** However, a semblance of GLOBAL threads is used to implement "LOCAL"
|
---|
54 | ** threads. An arbitrary number of such LOCAL threads can be assigned to
|
---|
55 | ** a single GLOBAL thread.
|
---|
56 | **
|
---|
57 | ** For scheduling, NSPR will attempt to run the highest priority LOCAL
|
---|
58 | ** thread associated with a given GLOBAL thread. It is further assumed
|
---|
59 | ** that the host OS will apply some form of "fair" scheduling on the
|
---|
60 | ** GLOBAL threads.
|
---|
61 | **
|
---|
62 | ** Threads have a "system flag" which when set indicates the thread
|
---|
63 | ** doesn't count for determining when the process should exit (the
|
---|
64 | ** process exits when the last user thread exits).
|
---|
65 | **
|
---|
66 | ** Threads also have a "scope flag" which controls whether the threads
|
---|
67 | ** are scheduled in the local scope or scheduled by the OS globally. This
|
---|
68 | ** indicates whether a thread is permanently bound to a native OS thread.
|
---|
69 | ** An unbound thread competes for scheduling resources in the same process.
|
---|
70 | **
|
---|
71 | ** Another flag is "state flag" which control whether the thread is joinable.
|
---|
72 | ** It allows other threads to wait for the created thread to reach completion.
|
---|
73 | **
|
---|
74 | ** Threads can have "per-thread-data" attached to them. Each thread has a
|
---|
75 | ** per-thread error number and error string which are updated when NSPR
|
---|
76 | ** operations fail.
|
---|
77 | */
|
---|
78 | #include "prtypes.h"
|
---|
79 | #include "prinrval.h"
|
---|
80 |
|
---|
81 | #ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
|
---|
82 | #define PR_CreateThread VBoxNsprPR_CreateThread
|
---|
83 | #define PR_JoinThread VBoxNsprPR_JoinThread
|
---|
84 | #define PR_Sleep VBoxNsprPR_Sleep
|
---|
85 | #define PR_GetCurrentThread VBoxNsprPR_GetCurrentThread
|
---|
86 | #define PR_GetThreadState VBoxNsprPR_GetThreadState
|
---|
87 | #define PR_SetThreadPrivate VBoxNsprPR_SetThreadPrivate
|
---|
88 | #define PR_GetThreadPrivate VBoxNsprPR_GetThreadPrivate
|
---|
89 | #define PR_NewThreadPrivateIndex VBoxNsprPR_NewThreadPrivateIndex
|
---|
90 | #define PR_GetThreadPriority VBoxNsprPR_GetThreadPriority
|
---|
91 | #define PR_SetThreadPriority VBoxNsprPR_SetThreadPriority
|
---|
92 | #define PR_Interrupt VBoxNsprPR_Interrupt
|
---|
93 | #define PR_ClearInterrupt VBoxNsprPR_ClearInterrupt
|
---|
94 | #define PR_BlockInterrupt VBoxNsprPR_BlockInterrupt
|
---|
95 | #define PR_UnblockInterrupt VBoxNsprPR_UnblockInterrupt
|
---|
96 | #define PR_GetThreadScope VBoxNsprPR_GetThreadScope
|
---|
97 | #define PR_GetThreadType VBoxNsprPR_GetThreadType
|
---|
98 | #endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
|
---|
99 |
|
---|
100 | PR_BEGIN_EXTERN_C
|
---|
101 |
|
---|
102 | typedef struct PRThread PRThread;
|
---|
103 | typedef struct PRThreadStack PRThreadStack;
|
---|
104 |
|
---|
105 | typedef enum PRThreadType {
|
---|
106 | PR_USER_THREAD,
|
---|
107 | PR_SYSTEM_THREAD
|
---|
108 | } PRThreadType;
|
---|
109 |
|
---|
110 | typedef enum PRThreadScope {
|
---|
111 | PR_LOCAL_THREAD,
|
---|
112 | PR_GLOBAL_THREAD,
|
---|
113 | PR_GLOBAL_BOUND_THREAD
|
---|
114 | } PRThreadScope;
|
---|
115 |
|
---|
116 | typedef enum PRThreadState {
|
---|
117 | PR_JOINABLE_THREAD,
|
---|
118 | PR_UNJOINABLE_THREAD
|
---|
119 | } PRThreadState;
|
---|
120 |
|
---|
121 | typedef enum PRThreadPriority
|
---|
122 | {
|
---|
123 | PR_PRIORITY_FIRST = 0, /* just a placeholder */
|
---|
124 | PR_PRIORITY_LOW = 0, /* the lowest possible priority */
|
---|
125 | PR_PRIORITY_NORMAL = 1, /* most common expected priority */
|
---|
126 | PR_PRIORITY_HIGH = 2, /* slightly more aggressive scheduling */
|
---|
127 | PR_PRIORITY_URGENT = 3, /* it does little good to have more than one */
|
---|
128 | PR_PRIORITY_LAST = 3 /* this is just a placeholder */
|
---|
129 | } PRThreadPriority;
|
---|
130 |
|
---|
131 | /*
|
---|
132 | ** Create a new thread:
|
---|
133 | ** "type" is the type of thread to create
|
---|
134 | ** "start(arg)" will be invoked as the threads "main"
|
---|
135 | ** "priority" will be created thread's priority
|
---|
136 | ** "scope" will specify whether the thread is local or global
|
---|
137 | ** "state" will specify whether the thread is joinable or not
|
---|
138 | ** "stackSize" the size of the stack, in bytes. The value can be zero
|
---|
139 | ** and then a machine specific stack size will be chosen.
|
---|
140 | **
|
---|
141 | ** This can return NULL if some kind of error occurs, such as if memory is
|
---|
142 | ** tight.
|
---|
143 | **
|
---|
144 | ** If you want the thread to start up waiting for the creator to do
|
---|
145 | ** something, enter a lock before creating the thread and then have the
|
---|
146 | ** threads start routine enter and exit the same lock. When you are ready
|
---|
147 | ** for the thread to run, exit the lock.
|
---|
148 | **
|
---|
149 | ** If you want to detect the completion of the created thread, the thread
|
---|
150 | ** should be created joinable. Then, use PR_JoinThread to synchrnoize the
|
---|
151 | ** termination of another thread.
|
---|
152 | **
|
---|
153 | ** When the start function returns the thread exits. If it is the last
|
---|
154 | ** PR_USER_THREAD to exit then the process exits.
|
---|
155 | */
|
---|
156 | NSPR_API(PRThread*) PR_CreateThread(PRThreadType type,
|
---|
157 | void (PR_CALLBACK *start)(void *arg),
|
---|
158 | void *arg,
|
---|
159 | PRThreadPriority priority,
|
---|
160 | PRThreadScope scope,
|
---|
161 | PRThreadState state,
|
---|
162 | PRUint32 stackSize);
|
---|
163 |
|
---|
164 | /*
|
---|
165 | ** Wait for thread termination:
|
---|
166 | ** "thread" is the target thread
|
---|
167 | **
|
---|
168 | ** This can return PR_FAILURE if no joinable thread could be found
|
---|
169 | ** corresponding to the specified target thread.
|
---|
170 | **
|
---|
171 | ** The calling thread is blocked until the target thread completes.
|
---|
172 | ** Several threads cannot wait for the same thread to complete; one thread
|
---|
173 | ** will operate successfully and others will terminate with an error PR_FAILURE.
|
---|
174 | ** The calling thread will not be blocked if the target thread has already
|
---|
175 | ** terminated.
|
---|
176 | */
|
---|
177 | NSPR_API(PRStatus) PR_JoinThread(PRThread *thread);
|
---|
178 |
|
---|
179 | /*
|
---|
180 | ** Return the current thread object for the currently running code.
|
---|
181 | ** Never returns NULL.
|
---|
182 | */
|
---|
183 | NSPR_API(PRThread*) PR_GetCurrentThread(void);
|
---|
184 | #ifndef NO_NSPR_10_SUPPORT
|
---|
185 | #define PR_CurrentThread() PR_GetCurrentThread() /* for nspr1.0 compat. */
|
---|
186 | #endif /* NO_NSPR_10_SUPPORT */
|
---|
187 |
|
---|
188 | /*
|
---|
189 | ** Get the priority of "thread".
|
---|
190 | */
|
---|
191 | NSPR_API(PRThreadPriority) PR_GetThreadPriority(const PRThread *thread);
|
---|
192 |
|
---|
193 | /*
|
---|
194 | ** Change the priority of the "thread" to "priority".
|
---|
195 | */
|
---|
196 | NSPR_API(void) PR_SetThreadPriority(PRThread *thread, PRThreadPriority priority);
|
---|
197 |
|
---|
198 | /*
|
---|
199 | ** This routine returns a new index for per-thread-private data table.
|
---|
200 | ** The index is visible to all threads within a process. This index can
|
---|
201 | ** be used with the PR_SetThreadPrivate() and PR_GetThreadPrivate() routines
|
---|
202 | ** to save and retrieve data associated with the index for a thread.
|
---|
203 | **
|
---|
204 | ** Each index is associationed with a destructor function ('dtor'). The function
|
---|
205 | ** may be specified as NULL when the index is created. If it is not NULL, the
|
---|
206 | ** function will be called when:
|
---|
207 | ** - the thread exits and the private data for the associated index
|
---|
208 | ** is not NULL,
|
---|
209 | ** - new thread private data is set and the current private data is
|
---|
210 | ** not NULL.
|
---|
211 | **
|
---|
212 | ** The index independently maintains specific values for each binding thread.
|
---|
213 | ** A thread can only get access to its own thread-specific-data.
|
---|
214 | **
|
---|
215 | ** Upon a new index return the value associated with the index for all threads
|
---|
216 | ** is NULL, and upon thread creation the value associated with all indices for
|
---|
217 | ** that thread is NULL.
|
---|
218 | **
|
---|
219 | ** Returns PR_FAILURE if the total number of indices will exceed the maximun
|
---|
220 | ** allowed.
|
---|
221 | */
|
---|
222 | typedef void (PR_CALLBACK *PRThreadPrivateDTOR)(void *priv);
|
---|
223 |
|
---|
224 | NSPR_API(PRStatus) PR_NewThreadPrivateIndex(
|
---|
225 | PRUintn *newIndex, PRThreadPrivateDTOR destructor);
|
---|
226 |
|
---|
227 | /*
|
---|
228 | ** Define some per-thread-private data.
|
---|
229 | ** "tpdIndex" is an index into the per-thread private data table
|
---|
230 | ** "priv" is the per-thread-private data
|
---|
231 | **
|
---|
232 | ** If the per-thread private data table has a previously registered
|
---|
233 | ** destructor function and a non-NULL per-thread-private data value,
|
---|
234 | ** the destructor function is invoked.
|
---|
235 | **
|
---|
236 | ** This can return PR_FAILURE if the index is invalid.
|
---|
237 | */
|
---|
238 | NSPR_API(PRStatus) PR_SetThreadPrivate(PRUintn tpdIndex, void *priv);
|
---|
239 |
|
---|
240 | /*
|
---|
241 | ** Recover the per-thread-private data for the current thread. "tpdIndex" is
|
---|
242 | ** the index into the per-thread private data table.
|
---|
243 | **
|
---|
244 | ** The returned value may be NULL which is indistinguishable from an error
|
---|
245 | ** condition.
|
---|
246 | **
|
---|
247 | ** A thread can only get access to its own thread-specific-data.
|
---|
248 | */
|
---|
249 | NSPR_API(void*) PR_GetThreadPrivate(PRUintn tpdIndex);
|
---|
250 |
|
---|
251 | /*
|
---|
252 | ** This routine sets the interrupt request for a target thread. The interrupt
|
---|
253 | ** request remains in the thread's state until it is delivered exactly once
|
---|
254 | ** or explicitly canceled.
|
---|
255 | **
|
---|
256 | ** A thread that has been interrupted will fail all NSPR blocking operations
|
---|
257 | ** that return a PRStatus (I/O, waiting on a condition, etc).
|
---|
258 | **
|
---|
259 | ** PR_Interrupt may itself fail if the target thread is invalid.
|
---|
260 | */
|
---|
261 | NSPR_API(PRStatus) PR_Interrupt(PRThread *thread);
|
---|
262 |
|
---|
263 | /*
|
---|
264 | ** Clear the interrupt request for the calling thread. If no such request
|
---|
265 | ** is pending, this operation is a noop.
|
---|
266 | */
|
---|
267 | NSPR_API(void) PR_ClearInterrupt(void);
|
---|
268 |
|
---|
269 | /*
|
---|
270 | ** Block the interrupt for the calling thread.
|
---|
271 | */
|
---|
272 | NSPR_API(void) PR_BlockInterrupt(void);
|
---|
273 |
|
---|
274 | /*
|
---|
275 | ** Unblock the interrupt for the calling thread.
|
---|
276 | */
|
---|
277 | NSPR_API(void) PR_UnblockInterrupt(void);
|
---|
278 |
|
---|
279 | /*
|
---|
280 | ** Make the current thread sleep until "ticks" time amount of time
|
---|
281 | ** has expired. If "ticks" is PR_INTERVAL_NO_WAIT then the call is
|
---|
282 | ** equivalent to calling PR_Yield. Calling PR_Sleep with an argument
|
---|
283 | ** equivalent to PR_INTERVAL_NO_TIMEOUT is an error and will result
|
---|
284 | ** in a PR_FAILURE error return.
|
---|
285 | */
|
---|
286 | NSPR_API(PRStatus) PR_Sleep(PRIntervalTime ticks);
|
---|
287 |
|
---|
288 | /*
|
---|
289 | ** Get the scoping of this thread.
|
---|
290 | */
|
---|
291 | NSPR_API(PRThreadScope) PR_GetThreadScope(const PRThread *thread);
|
---|
292 |
|
---|
293 | /*
|
---|
294 | ** Get the type of this thread.
|
---|
295 | */
|
---|
296 | NSPR_API(PRThreadType) PR_GetThreadType(const PRThread *thread);
|
---|
297 |
|
---|
298 | /*
|
---|
299 | ** Get the join state of this thread.
|
---|
300 | */
|
---|
301 | NSPR_API(PRThreadState) PR_GetThreadState(const PRThread *thread);
|
---|
302 |
|
---|
303 | PR_END_EXTERN_C
|
---|
304 |
|
---|
305 | #endif /* prthread_h___ */
|
---|