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