/src/nspr/pr/include/private/primpl.h
Line | Count | Source (jump to first uncovered line) |
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 | | |
6 | | #ifndef primpl_h___ |
7 | | #define primpl_h___ |
8 | | |
9 | | #if defined(_PR_PTHREADS) |
10 | | #include <pthread.h> |
11 | | #endif |
12 | | |
13 | | #ifdef WIN32 |
14 | | /* |
15 | | * Allow use of functions and symbols first defined in Win2k. |
16 | | */ |
17 | | #if !defined(WINVER) || (WINVER < 0x0500) |
18 | | #undef WINVER |
19 | | #define WINVER 0x0500 |
20 | | #endif |
21 | | #if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) |
22 | | #undef _WIN32_WINNT |
23 | | #define _WIN32_WINNT 0x0500 |
24 | | #endif |
25 | | #endif /* WIN32 */ |
26 | | |
27 | | #include "nspr.h" |
28 | | #include "prpriv.h" |
29 | | |
30 | | typedef struct PRSegment PRSegment; |
31 | | |
32 | | #include "md/prosdep.h" |
33 | | #include "obsolete/probslet.h" |
34 | | |
35 | | #ifdef _PR_HAVE_POSIX_SEMAPHORES |
36 | | #include <semaphore.h> |
37 | | #elif defined(_PR_HAVE_SYSV_SEMAPHORES) |
38 | | #include <sys/sem.h> |
39 | | #endif |
40 | | |
41 | | #ifdef HAVE_SYSCALL |
42 | | #include <sys/syscall.h> |
43 | | #endif |
44 | | |
45 | | /************************************************************************* |
46 | | ***** A Word about Model Dependent Function Naming Convention *********** |
47 | | *************************************************************************/ |
48 | | |
49 | | /* |
50 | | NSPR 2.0 must implement its function across a range of platforms |
51 | | including: MAC, Windows/16, Windows/95, Windows/NT, and several |
52 | | variants of Unix. Each implementation shares common code as well |
53 | | as having platform dependent portions. This standard describes how |
54 | | the model dependent portions are to be implemented. |
55 | | |
56 | | In header file pr/include/primpl.h, each publicly declared |
57 | | platform dependent function is declared as: |
58 | | |
59 | | NSPR_API void _PR_MD_FUNCTION( long arg1, long arg2 ); |
60 | | #define _PR_MD_FUNCTION _MD_FUNCTION |
61 | | |
62 | | In header file pr/include/md/<platform>/_<platform>.h, |
63 | | each #define'd macro is redefined as one of: |
64 | | |
65 | | #define _MD_FUNCTION <blanks> |
66 | | #define _MD_FUNCTION <expanded macro> |
67 | | #define _MD_FUNCTION <osFunction> |
68 | | #define _MD_FUNCTION <_MD_Function> |
69 | | |
70 | | Where: |
71 | | |
72 | | <blanks> is no definition at all. In this case, the function is not implemented |
73 | | and is never called for this platform. |
74 | | For example: |
75 | | #define _MD_INIT_CPUS() |
76 | | |
77 | | <expanded macro> is a C language macro expansion. |
78 | | For example: |
79 | | #define _MD_CLEAN_THREAD(_thread) \ |
80 | | PR_BEGIN_MACRO \ |
81 | | PR_DestroyCondVar(_thread->md.asyncIOCVar); \ |
82 | | PR_DestroyLock(_thread->md.asyncIOLock); \ |
83 | | PR_END_MACRO |
84 | | |
85 | | <osFunction> is some function implemented by the host operating system. |
86 | | For example: |
87 | | #define _MD_EXIT exit |
88 | | |
89 | | <_MD_function> is the name of a function implemented for this platform in |
90 | | pr/src/md/<platform>/<soruce>.c file. |
91 | | For example: |
92 | | #define _MD_GETFILEINFO _MD_GetFileInfo |
93 | | |
94 | | In <source>.c, the implementation is: |
95 | | PR_IMPLEMENT(PRInt32) _MD_GetFileInfo(const char *fn, PRFileInfo *info); |
96 | | */ |
97 | | |
98 | | PR_BEGIN_EXTERN_C |
99 | | |
100 | | typedef struct _MDLock _MDLock; |
101 | | typedef struct _MDCVar _MDCVar; |
102 | | typedef struct _MDSegment _MDSegment; |
103 | | typedef struct _MDThread _MDThread; |
104 | | typedef struct _MDThreadStack _MDThreadStack; |
105 | | typedef struct _MDSemaphore _MDSemaphore; |
106 | | typedef struct _MDDir _MDDir; |
107 | | #ifdef MOZ_UNICODE |
108 | | typedef struct _MDDirUTF16 _MDDirUTF16; |
109 | | #endif /* MOZ_UNICODE */ |
110 | | typedef struct _MDFileDesc _MDFileDesc; |
111 | | typedef struct _MDProcess _MDProcess; |
112 | | typedef struct _MDFileMap _MDFileMap; |
113 | | |
114 | | #if defined(_PR_PTHREADS) |
115 | | |
116 | | /* |
117 | | ** The following definitions are unique to implementing NSPR using pthreads. |
118 | | ** Since pthreads defines most of the thread and thread synchronization |
119 | | ** stuff, this is a pretty small set. |
120 | | */ |
121 | | |
122 | 0 | #define PT_CV_NOTIFIED_LENGTH 6 |
123 | | typedef struct _PT_Notified _PT_Notified; |
124 | | struct _PT_Notified |
125 | | { |
126 | | PRIntn length; /* # of used entries in this structure */ |
127 | | struct |
128 | | { |
129 | | PRCondVar *cv; /* the condition variable notified */ |
130 | | PRIntn times; /* and the number of times notified */ |
131 | | } cv[PT_CV_NOTIFIED_LENGTH]; |
132 | | _PT_Notified *link; /* link to another of these | NULL */ |
133 | | }; |
134 | | |
135 | | /* |
136 | | * bits defined for pthreads 'state' field |
137 | | */ |
138 | 0 | #define PT_THREAD_DETACHED 0x01 /* thread can't be joined */ |
139 | 0 | #define PT_THREAD_GLOBAL 0x02 /* a global thread (unlikely) */ |
140 | 0 | #define PT_THREAD_SYSTEM 0x04 /* system (not user) thread */ |
141 | 0 | #define PT_THREAD_PRIMORD 0x08 /* this is the primordial thread */ |
142 | 0 | #define PT_THREAD_ABORTED 0x10 /* thread has been interrupted */ |
143 | 0 | #define PT_THREAD_GCABLE 0x20 /* thread is garbage collectible */ |
144 | 0 | #define PT_THREAD_SUSPENDED 0x40 /* thread has been suspended */ |
145 | 0 | #define PT_THREAD_FOREIGN 0x80 /* thread is not one of ours */ |
146 | 0 | #define PT_THREAD_BOUND 0x100 /* a bound-global thread */ |
147 | | |
148 | | #define _PT_THREAD_INTERRUPTED(thr) \ |
149 | 0 | (!(thr->interrupt_blocked) && (thr->state & PT_THREAD_ABORTED)) |
150 | | #define _PT_THREAD_BLOCK_INTERRUPT(thr) \ |
151 | 0 | (thr->interrupt_blocked = 1) |
152 | | #define _PT_THREAD_UNBLOCK_INTERRUPT(thr) \ |
153 | 0 | (thr->interrupt_blocked = 0) |
154 | | |
155 | 0 | #define _PT_IS_GCABLE_THREAD(thr) ((thr)->state & PT_THREAD_GCABLE) |
156 | | |
157 | | /* |
158 | | ** Possible values for thread's suspend field |
159 | | ** Note that the first two can be the same as they are really mutually exclusive, |
160 | | ** i.e. both cannot be happening at the same time. We have two symbolic names |
161 | | ** just as a mnemonic. |
162 | | **/ |
163 | 0 | #define PT_THREAD_RESUMED 0x80 /* thread has been resumed */ |
164 | 0 | #define PT_THREAD_SETGCABLE 0x100 /* set the GCAble flag */ |
165 | | |
166 | | #if defined(DEBUG) |
167 | | |
168 | | typedef struct PTDebug |
169 | | { |
170 | | PRTime timeStarted; |
171 | | PRUintn locks_created, locks_destroyed; |
172 | | PRUintn locks_acquired, locks_released; |
173 | | PRUintn cvars_created, cvars_destroyed; |
174 | | PRUintn cvars_notified, delayed_cv_deletes; |
175 | | } PTDebug; |
176 | | |
177 | | #endif /* defined(DEBUG) */ |
178 | | |
179 | | NSPR_API(void) PT_FPrintStats(PRFileDesc *fd, const char *msg); |
180 | | |
181 | | /* |
182 | | * On Linux and its derivatives POSIX priority scheduling works only for |
183 | | * real-time threads. On those platforms we set thread's nice values |
184 | | * instead which requires us to track kernel thread IDs for each POSIX |
185 | | * thread we create. |
186 | | */ |
187 | | #if defined(LINUX) && defined(HAVE_SETPRIORITY) && \ |
188 | | ((defined(HAVE_SYSCALL) && defined(SYS_gettid)) || defined(HAVE_GETTID)) |
189 | | #define _PR_NICE_PRIORITY_SCHEDULING |
190 | | #endif |
191 | | |
192 | | #else /* defined(_PR_PTHREADS) */ |
193 | | |
194 | | NSPR_API(void) PT_FPrintStats(PRFileDesc *fd, const char *msg); |
195 | | |
196 | | /* |
197 | | ** This section is contains those parts needed to implement NSPR on |
198 | | ** platforms in general. One would assume that the pthreads implementation |
199 | | ** included lots of the same types, at least conceptually. |
200 | | */ |
201 | | |
202 | | /* |
203 | | * Local threads only. No multiple CPU support and hence all the |
204 | | * following routines are no-op. |
205 | | */ |
206 | | #ifdef _PR_LOCAL_THREADS_ONLY |
207 | | |
208 | | #define _PR_MD_SUSPEND_THREAD(thread) |
209 | | #define _PR_MD_RESUME_THREAD(thread) |
210 | | #define _PR_MD_SUSPEND_CPU(cpu) |
211 | | #define _PR_MD_RESUME_CPU(cpu) |
212 | | #define _PR_MD_BEGIN_SUSPEND_ALL() |
213 | | #define _PR_MD_END_SUSPEND_ALL() |
214 | | #define _PR_MD_BEGIN_RESUME_ALL() |
215 | | #define _PR_MD_END_RESUME_ALL() |
216 | | #define _PR_MD_INIT_ATTACHED_THREAD(thread) PR_FAILURE |
217 | | |
218 | | #endif |
219 | | |
220 | | typedef struct _PRCPUQueue _PRCPUQueue; |
221 | | typedef struct _PRCPU _PRCPU; |
222 | | typedef struct _MDCPU _MDCPU; |
223 | | |
224 | | struct _PRCPUQueue { |
225 | | _MDLock runQLock; /* lock for the run + wait queues */ |
226 | | _MDLock sleepQLock; /* lock for the run + wait queues */ |
227 | | _MDLock miscQLock; /* lock for the run + wait queues */ |
228 | | |
229 | | PRCList runQ[PR_PRIORITY_LAST + 1]; /* run queue for this CPU */ |
230 | | PRUint32 runQReadyMask; |
231 | | PRCList sleepQ; |
232 | | PRIntervalTime sleepQmax; |
233 | | PRCList pauseQ; |
234 | | PRCList suspendQ; |
235 | | PRCList waitingToJoinQ; |
236 | | |
237 | | PRUintn numCPUs; /* number of CPUs using this Q */ |
238 | | }; |
239 | | |
240 | | struct _PRCPU { |
241 | | PRCList links; /* link list of CPUs */ |
242 | | PRUint32 id; /* id for this CPU */ |
243 | | |
244 | | union { |
245 | | PRInt32 bits; |
246 | | PRUint8 missed[4]; |
247 | | } u; |
248 | | PRIntn where; /* index into u.missed */ |
249 | | PRPackedBool paused; /* cpu is paused */ |
250 | | PRPackedBool exit; /* cpu should exit */ |
251 | | |
252 | | PRThread *thread; /* native thread for this CPUThread */ |
253 | | PRThread *idle_thread; /* user-level idle thread for this CPUThread */ |
254 | | |
255 | | PRIntervalTime last_clock; /* the last time we went into |
256 | | * _PR_ClockInterrupt() on this CPU |
257 | | */ |
258 | | |
259 | | _PRCPUQueue *queue; |
260 | | |
261 | | _MDCPU md; |
262 | | }; |
263 | | |
264 | | typedef struct _PRInterruptTable { |
265 | | const char *name; |
266 | | PRUintn missed_bit; |
267 | | void (*handler)(void); |
268 | | } _PRInterruptTable; |
269 | | |
270 | | #define _PR_CPU_PTR(_qp) \ |
271 | | ((_PRCPU*) ((char*) (_qp) - offsetof(_PRCPU,links))) |
272 | | |
273 | | #if !defined(WIN32) \ |
274 | | && !(defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY)) |
275 | | #define _MD_GET_ATTACHED_THREAD() (_PR_MD_CURRENT_THREAD()) |
276 | | #endif |
277 | | |
278 | | #ifdef _PR_LOCAL_THREADS_ONLY |
279 | | |
280 | | NSPR_API(struct _PRCPU *) _pr_currentCPU; |
281 | | NSPR_API(PRThread *) _pr_currentThread; |
282 | | NSPR_API(PRThread *) _pr_lastThread; |
283 | | NSPR_API(PRInt32) _pr_intsOff; |
284 | | |
285 | | #define _MD_CURRENT_CPU() (_pr_currentCPU) |
286 | | #define _MD_SET_CURRENT_CPU(_cpu) (_pr_currentCPU = (_cpu)) |
287 | | #define _MD_CURRENT_THREAD() (_pr_currentThread) |
288 | | #define _MD_SET_CURRENT_THREAD(_thread) (_pr_currentThread = (_thread)) |
289 | | #define _MD_LAST_THREAD() (_pr_lastThread) |
290 | | #define _MD_SET_LAST_THREAD(t) (_pr_lastThread = t) |
291 | | |
292 | | #define _MD_GET_INTSOFF() (_pr_intsOff) |
293 | | #define _MD_SET_INTSOFF(_val) (_pr_intsOff = _val) |
294 | | |
295 | | |
296 | | /* The unbalanced curly braces in these two macros are intentional */ |
297 | | #define _PR_LOCK_HEAP() { PRIntn _is; if (_pr_currentCPU) _PR_INTSOFF(_is); |
298 | | #define _PR_UNLOCK_HEAP() if (_pr_currentCPU) _PR_INTSON(_is); } |
299 | | |
300 | | #endif /* _PR_LOCAL_THREADS_ONLY */ |
301 | | |
302 | | extern PRInt32 _native_threads_only; |
303 | | |
304 | | #if defined(_PR_GLOBAL_THREADS_ONLY) |
305 | | |
306 | | #define _MD_GET_INTSOFF() 0 |
307 | | #define _MD_SET_INTSOFF(_val) |
308 | | #define _PR_INTSOFF(_is) |
309 | | #define _PR_FAST_INTSON(_is) |
310 | | #define _PR_INTSON(_is) |
311 | | #define _PR_THREAD_LOCK(_thread) |
312 | | #define _PR_THREAD_UNLOCK(_thread) |
313 | | #define _PR_RUNQ_LOCK(cpu) |
314 | | #define _PR_RUNQ_UNLOCK(cpu) |
315 | | #define _PR_SLEEPQ_LOCK(thread) |
316 | | #define _PR_SLEEPQ_UNLOCK(thread) |
317 | | #define _PR_MISCQ_LOCK(thread) |
318 | | #define _PR_MISCQ_UNLOCK(thread) |
319 | | #define _PR_CPU_LIST_LOCK() |
320 | | #define _PR_CPU_LIST_UNLOCK() |
321 | | |
322 | | #define _PR_ADD_RUNQ(_thread, _cpu, _pri) |
323 | | #define _PR_DEL_RUNQ(_thread) |
324 | | #define _PR_ADD_SLEEPQ(_thread, _timeout) |
325 | | #define _PR_DEL_SLEEPQ(_thread, _propogate) |
326 | | #define _PR_ADD_JOINQ(_thread, _cpu) |
327 | | #define _PR_DEL_JOINQ(_thread) |
328 | | #define _PR_ADD_SUSPENDQ(_thread, _cpu) |
329 | | #define _PR_DEL_SUSPENDQ(_thread) |
330 | | |
331 | | #define _PR_THREAD_SWITCH_CPU(_thread, _newCPU) |
332 | | |
333 | | #define _PR_IS_NATIVE_THREAD(thread) 1 |
334 | | #define _PR_IS_NATIVE_THREAD_SUPPORTED() 1 |
335 | | |
336 | | #else |
337 | | |
338 | | #define _PR_INTSOFF(_is) \ |
339 | | PR_BEGIN_MACRO \ |
340 | | (_is) = _PR_MD_GET_INTSOFF(); \ |
341 | | _PR_MD_SET_INTSOFF(1); \ |
342 | | PR_END_MACRO |
343 | | |
344 | | #define _PR_FAST_INTSON(_is) \ |
345 | | PR_BEGIN_MACRO \ |
346 | | _PR_MD_SET_INTSOFF(_is); \ |
347 | | PR_END_MACRO |
348 | | |
349 | | #define _PR_INTSON(_is) \ |
350 | | PR_BEGIN_MACRO \ |
351 | | if ((_is == 0) && (_PR_MD_CURRENT_CPU())->u.bits) \ |
352 | | _PR_IntsOn((_PR_MD_CURRENT_CPU())); \ |
353 | | _PR_MD_SET_INTSOFF(_is); \ |
354 | | PR_END_MACRO |
355 | | |
356 | | #ifdef _PR_LOCAL_THREADS_ONLY |
357 | | |
358 | | #define _PR_IS_NATIVE_THREAD(thread) 0 |
359 | | #define _PR_THREAD_LOCK(_thread) |
360 | | #define _PR_THREAD_UNLOCK(_thread) |
361 | | #define _PR_RUNQ_LOCK(cpu) |
362 | | #define _PR_RUNQ_UNLOCK(cpu) |
363 | | #define _PR_SLEEPQ_LOCK(thread) |
364 | | #define _PR_SLEEPQ_UNLOCK(thread) |
365 | | #define _PR_MISCQ_LOCK(thread) |
366 | | #define _PR_MISCQ_UNLOCK(thread) |
367 | | #define _PR_CPU_LIST_LOCK() |
368 | | #define _PR_CPU_LIST_UNLOCK() |
369 | | |
370 | | #define _PR_ADD_RUNQ(_thread, _cpu, _pri) \ |
371 | | PR_BEGIN_MACRO \ |
372 | | PR_APPEND_LINK(&(_thread)->links, &_PR_RUNQ(_cpu)[_pri]); \ |
373 | | _PR_RUNQREADYMASK(_cpu) |= (1L << _pri); \ |
374 | | PR_END_MACRO |
375 | | |
376 | | #define _PR_DEL_RUNQ(_thread) \ |
377 | | PR_BEGIN_MACRO \ |
378 | | _PRCPU *_cpu = _thread->cpu; \ |
379 | | PRInt32 _pri = _thread->priority; \ |
380 | | PR_REMOVE_LINK(&(_thread)->links); \ |
381 | | if (PR_CLIST_IS_EMPTY(&_PR_RUNQ(_cpu)[_pri])) \ |
382 | | _PR_RUNQREADYMASK(_cpu) &= ~(1L << _pri); \ |
383 | | PR_END_MACRO |
384 | | |
385 | | #define _PR_ADD_SLEEPQ(_thread, _timeout) \ |
386 | | _PR_AddSleepQ(_thread, _timeout); |
387 | | |
388 | | #define _PR_DEL_SLEEPQ(_thread, _propogate) \ |
389 | | _PR_DelSleepQ(_thread, _propogate); |
390 | | |
391 | | #define _PR_ADD_JOINQ(_thread, _cpu) \ |
392 | | PR_APPEND_LINK(&(_thread)->links, &_PR_WAITINGTOJOINQ(_cpu)); |
393 | | |
394 | | #define _PR_DEL_JOINQ(_thread) \ |
395 | | PR_REMOVE_LINK(&(_thread)->links); |
396 | | |
397 | | #define _PR_ADD_SUSPENDQ(_thread, _cpu) \ |
398 | | PR_APPEND_LINK(&(_thread)->links, &_PR_SUSPENDQ(_cpu)); |
399 | | |
400 | | #define _PR_DEL_SUSPENDQ(_thread) \ |
401 | | PR_REMOVE_LINK(&(_thread)->links); |
402 | | |
403 | | #define _PR_THREAD_SWITCH_CPU(_thread, _newCPU) |
404 | | |
405 | | #define _PR_IS_NATIVE_THREAD_SUPPORTED() 0 |
406 | | |
407 | | #else /* _PR_LOCAL_THREADS_ONLY */ |
408 | | |
409 | | /* These are for the "combined" thread model */ |
410 | | |
411 | | #define _PR_THREAD_LOCK(_thread) \ |
412 | | _PR_MD_LOCK(&(_thread)->threadLock); |
413 | | |
414 | | #define _PR_THREAD_UNLOCK(_thread) \ |
415 | | _PR_MD_UNLOCK(&(_thread)->threadLock); |
416 | | |
417 | | #define _PR_RUNQ_LOCK(_cpu) \ |
418 | | PR_BEGIN_MACRO \ |
419 | | _PR_MD_LOCK(&(_cpu)->queue->runQLock );\ |
420 | | PR_END_MACRO |
421 | | |
422 | | #define _PR_RUNQ_UNLOCK(_cpu) \ |
423 | | PR_BEGIN_MACRO \ |
424 | | _PR_MD_UNLOCK(&(_cpu)->queue->runQLock );\ |
425 | | PR_END_MACRO |
426 | | |
427 | | #define _PR_SLEEPQ_LOCK(_cpu) \ |
428 | | _PR_MD_LOCK(&(_cpu)->queue->sleepQLock ); |
429 | | |
430 | | #define _PR_SLEEPQ_UNLOCK(_cpu) \ |
431 | | _PR_MD_UNLOCK(&(_cpu)->queue->sleepQLock ); |
432 | | |
433 | | #define _PR_MISCQ_LOCK(_cpu) \ |
434 | | _PR_MD_LOCK(&(_cpu)->queue->miscQLock ); |
435 | | |
436 | | #define _PR_MISCQ_UNLOCK(_cpu) \ |
437 | | _PR_MD_UNLOCK(&(_cpu)->queue->miscQLock ); |
438 | | |
439 | | #define _PR_CPU_LIST_LOCK() _PR_MD_LOCK(&_pr_cpuLock) |
440 | | #define _PR_CPU_LIST_UNLOCK() _PR_MD_UNLOCK(&_pr_cpuLock) |
441 | | |
442 | | #define QUEUE_RUN 0x1 |
443 | | #define QUEUE_SLEEP 0x2 |
444 | | #define QUEUE_JOIN 0x4 |
445 | | #define QUEUE_SUSPEND 0x8 |
446 | | #define QUEUE_LOCK 0x10 |
447 | | |
448 | | #define _PR_ADD_RUNQ(_thread, _cpu, _pri) \ |
449 | | PR_BEGIN_MACRO \ |
450 | | PR_APPEND_LINK(&(_thread)->links, &_PR_RUNQ(_cpu)[_pri]); \ |
451 | | _PR_RUNQREADYMASK(_cpu) |= (1L << _pri); \ |
452 | | PR_ASSERT((_thread)->queueCount == 0); \ |
453 | | (_thread)->queueCount = QUEUE_RUN; \ |
454 | | PR_END_MACRO |
455 | | |
456 | | #define _PR_DEL_RUNQ(_thread) \ |
457 | | PR_BEGIN_MACRO \ |
458 | | _PRCPU *_cpu = _thread->cpu; \ |
459 | | PRInt32 _pri = _thread->priority; \ |
460 | | PR_REMOVE_LINK(&(_thread)->links); \ |
461 | | if (PR_CLIST_IS_EMPTY(&_PR_RUNQ(_cpu)[_pri])) \ |
462 | | _PR_RUNQREADYMASK(_cpu) &= ~(1L << _pri); \ |
463 | | PR_ASSERT((_thread)->queueCount == QUEUE_RUN);\ |
464 | | (_thread)->queueCount = 0; \ |
465 | | PR_END_MACRO |
466 | | |
467 | | #define _PR_ADD_SLEEPQ(_thread, _timeout) \ |
468 | | PR_ASSERT((_thread)->queueCount == 0); \ |
469 | | (_thread)->queueCount = QUEUE_SLEEP; \ |
470 | | _PR_AddSleepQ(_thread, _timeout); |
471 | | |
472 | | #define _PR_DEL_SLEEPQ(_thread, _propogate) \ |
473 | | PR_ASSERT((_thread)->queueCount == QUEUE_SLEEP);\ |
474 | | (_thread)->queueCount = 0; \ |
475 | | _PR_DelSleepQ(_thread, _propogate); |
476 | | |
477 | | #define _PR_ADD_JOINQ(_thread, _cpu) \ |
478 | | PR_ASSERT((_thread)->queueCount == 0); \ |
479 | | (_thread)->queueCount = QUEUE_JOIN; \ |
480 | | PR_APPEND_LINK(&(_thread)->links, &_PR_WAITINGTOJOINQ(_cpu)); |
481 | | |
482 | | #define _PR_DEL_JOINQ(_thread) \ |
483 | | PR_ASSERT((_thread)->queueCount == QUEUE_JOIN);\ |
484 | | (_thread)->queueCount = 0; \ |
485 | | PR_REMOVE_LINK(&(_thread)->links); |
486 | | |
487 | | #define _PR_ADD_SUSPENDQ(_thread, _cpu) \ |
488 | | PR_ASSERT((_thread)->queueCount == 0); \ |
489 | | (_thread)->queueCount = QUEUE_SUSPEND; \ |
490 | | PR_APPEND_LINK(&(_thread)->links, &_PR_SUSPENDQ(_cpu)); |
491 | | |
492 | | #define _PR_DEL_SUSPENDQ(_thread) \ |
493 | | PR_ASSERT((_thread)->queueCount == QUEUE_SUSPEND);\ |
494 | | (_thread)->queueCount = 0; \ |
495 | | PR_REMOVE_LINK(&(_thread)->links); |
496 | | |
497 | | #define _PR_THREAD_SWITCH_CPU(_thread, _newCPU) \ |
498 | | (_thread)->cpu = (_newCPU); |
499 | | |
500 | | #define _PR_IS_NATIVE_THREAD(thread) (thread->flags & _PR_GLOBAL_SCOPE) |
501 | | #define _PR_IS_NATIVE_THREAD_SUPPORTED() 1 |
502 | | |
503 | | #endif /* _PR_LOCAL_THREADS_ONLY */ |
504 | | |
505 | | #endif /* _PR_GLOBAL_THREADS_ONLY */ |
506 | | |
507 | | #define _PR_SET_RESCHED_FLAG() _PR_MD_CURRENT_CPU()->u.missed[3] = 1 |
508 | | #define _PR_CLEAR_RESCHED_FLAG() _PR_MD_CURRENT_CPU()->u.missed[3] = 0 |
509 | | |
510 | | extern _PRInterruptTable _pr_interruptTable[]; |
511 | | |
512 | | /* Bits for _pr_interruptState.u.missed[0,1] */ |
513 | | #define _PR_MISSED_CLOCK 0x1 |
514 | | #define _PR_MISSED_IO 0x2 |
515 | | #define _PR_MISSED_CHILD 0x4 |
516 | | |
517 | | extern void _PR_IntsOn(_PRCPU *cpu); |
518 | | |
519 | | NSPR_API(void) _PR_WakeupCPU(void); |
520 | | NSPR_API(void) _PR_PauseCPU(void); |
521 | | |
522 | | /************************************************************************/ |
523 | | |
524 | | #define _PR_LOCK_LOCK(_lock) \ |
525 | | _PR_MD_LOCK(&(_lock)->ilock); |
526 | | #define _PR_LOCK_UNLOCK(_lock) \ |
527 | | _PR_MD_UNLOCK(&(_lock)->ilock); |
528 | | |
529 | | extern void _PR_UnblockLockWaiter(PRLock *lock); |
530 | | extern PRStatus _PR_InitLock(PRLock *lock); |
531 | | extern void _PR_FreeLock(PRLock *lock); |
532 | | |
533 | | #define _PR_LOCK_PTR(_qp) \ |
534 | | ((PRLock*) ((char*) (_qp) - offsetof(PRLock,links))) |
535 | | |
536 | | /************************************************************************/ |
537 | | |
538 | | #define _PR_CVAR_LOCK(_cvar) \ |
539 | | _PR_MD_LOCK(&(_cvar)->ilock); |
540 | | #define _PR_CVAR_UNLOCK(_cvar) \ |
541 | | _PR_MD_UNLOCK(&(_cvar)->ilock); |
542 | | |
543 | | extern PRStatus _PR_InitCondVar(PRCondVar *cvar, PRLock *lock); |
544 | | extern void _PR_FreeCondVar(PRCondVar *cvar); |
545 | | extern PRStatus _PR_WaitCondVar( |
546 | | PRThread *thread, PRCondVar *cvar, PRLock *lock, PRIntervalTime timeout); |
547 | | extern void _PR_NotifyCondVar(PRCondVar *cvar, PRThread *me); |
548 | | extern PRUint32 _PR_CondVarToString(PRCondVar *cvar, char *buf, PRUint32 buflen); |
549 | | |
550 | | NSPR_API(void) _PR_Notify(PRMonitor *mon, PRBool all, PRBool sticky); |
551 | | |
552 | | /* PRThread.flags */ |
553 | | #define _PR_SYSTEM 0x01 |
554 | | #define _PR_INTERRUPT 0x02 |
555 | | #define _PR_ATTACHED 0x04 /* created via PR_AttachThread */ |
556 | | #define _PR_PRIMORDIAL 0x08 /* the thread that called PR_Init */ |
557 | | #define _PR_ON_SLEEPQ 0x10 /* thread is on the sleepQ */ |
558 | | #define _PR_ON_PAUSEQ 0x20 /* thread is on the pauseQ */ |
559 | | #define _PR_SUSPENDING 0x40 /* thread wants to suspend */ |
560 | | #define _PR_GLOBAL_SCOPE 0x80 /* thread is global scope */ |
561 | | #define _PR_IDLE_THREAD 0x200 /* this is an idle thread */ |
562 | | #define _PR_GCABLE_THREAD 0x400 /* this is a collectable thread */ |
563 | | #define _PR_BOUND_THREAD 0x800 /* a bound thread */ |
564 | | #define _PR_INTERRUPT_BLOCKED 0x1000 /* interrupts blocked */ |
565 | | |
566 | | /* PRThread.state */ |
567 | | #define _PR_UNBORN 0 |
568 | | #define _PR_RUNNABLE 1 |
569 | | #define _PR_RUNNING 2 |
570 | | #define _PR_LOCK_WAIT 3 |
571 | | #define _PR_COND_WAIT 4 |
572 | | #define _PR_JOIN_WAIT 5 |
573 | | #define _PR_IO_WAIT 6 |
574 | | #define _PR_SUSPENDED 7 |
575 | | #define _PR_DEAD_STATE 8 /* for debugging */ |
576 | | |
577 | | /* PRThreadStack.flags */ |
578 | | #define _PR_STACK_VM 0x1 /* using vm instead of malloc */ |
579 | | #define _PR_STACK_MAPPED 0x2 /* vm is mapped */ |
580 | | #define _PR_STACK_PRIMORDIAL 0x4 /* stack for primordial thread */ |
581 | | |
582 | | /* |
583 | | ** If the default stcksize from the client is zero, we need to pick a machine |
584 | | ** dependent value. This is only for standard user threads. For custom threads, |
585 | | ** 0 has a special meaning. |
586 | | ** Adjust stackSize. Round up to a page boundary. |
587 | | */ |
588 | | |
589 | | #ifndef _MD_MINIMUM_STACK_SIZE |
590 | | #define _MD_MINIMUM_STACK_SIZE 0 |
591 | | #endif |
592 | | |
593 | | #if (!defined(HAVE_CUSTOM_USER_THREADS)) |
594 | | #define _PR_ADJUST_STACKSIZE(stackSize) \ |
595 | | PR_BEGIN_MACRO \ |
596 | | if (stackSize == 0) \ |
597 | | stackSize = _MD_DEFAULT_STACK_SIZE; \ |
598 | | if (stackSize < _MD_MINIMUM_STACK_SIZE) \ |
599 | | stackSize = _MD_MINIMUM_STACK_SIZE; \ |
600 | | stackSize = (stackSize + (1 << _pr_pageShift) - 1) >> _pr_pageShift; \ |
601 | | stackSize <<= _pr_pageShift; \ |
602 | | PR_END_MACRO |
603 | | #else |
604 | | #define _PR_ADJUST_STACKSIZE(stackSize) |
605 | | #endif |
606 | | |
607 | | #define _PR_IS_GCABLE_THREAD(thr) ((thr)->flags & _PR_GCABLE_THREAD) |
608 | | |
609 | | #define _PR_PENDING_INTERRUPT(thr) \ |
610 | | (!((thr)->flags & _PR_INTERRUPT_BLOCKED) && ((thr)->flags & _PR_INTERRUPT)) |
611 | | #define _PR_THREAD_BLOCK_INTERRUPT(thr) \ |
612 | | (thr->flags |= _PR_INTERRUPT_BLOCKED) |
613 | | #define _PR_THREAD_UNBLOCK_INTERRUPT(thr) \ |
614 | | (thr->flags &= ~_PR_INTERRUPT_BLOCKED) |
615 | | |
616 | | #define _PR_THREAD_PTR(_qp) \ |
617 | | ((PRThread*) ((char*) (_qp) - offsetof(PRThread,links))) |
618 | | |
619 | | #define _PR_ACTIVE_THREAD_PTR(_qp) \ |
620 | | ((PRThread*) ((char*) (_qp) - offsetof(PRThread,active))) |
621 | | |
622 | | #define _PR_THREAD_CONDQ_PTR(_qp) \ |
623 | | ((PRThread*) ((char*) (_qp) - offsetof(PRThread,waitQLinks))) |
624 | | |
625 | | #define _PR_THREAD_MD_TO_PTR(_md) \ |
626 | | ((PRThread*) ((char*) (_md) - offsetof(PRThread,md))) |
627 | | |
628 | | #define _PR_THREAD_STACK_TO_PTR(_stack) \ |
629 | | ((PRThread*) (_stack->thr)) |
630 | | |
631 | | extern PRCList _pr_active_local_threadQ; |
632 | | extern PRCList _pr_active_global_threadQ; |
633 | | extern PRCList _pr_cpuQ; |
634 | | extern _MDLock _pr_cpuLock; |
635 | | extern PRInt32 _pr_md_idle_cpus; |
636 | | |
637 | | #define _PR_ACTIVE_LOCAL_THREADQ() _pr_active_local_threadQ |
638 | | #define _PR_ACTIVE_GLOBAL_THREADQ() _pr_active_global_threadQ |
639 | | #define _PR_CPUQ() _pr_cpuQ |
640 | | #define _PR_RUNQ(_cpu) ((_cpu)->queue->runQ) |
641 | | #define _PR_RUNQREADYMASK(_cpu) ((_cpu)->queue->runQReadyMask) |
642 | | #define _PR_SLEEPQ(_cpu) ((_cpu)->queue->sleepQ) |
643 | | #define _PR_SLEEPQMAX(_cpu) ((_cpu)->queue->sleepQmax) |
644 | | #define _PR_PAUSEQ(_cpu) ((_cpu)->queue->pauseQ) |
645 | | #define _PR_SUSPENDQ(_cpu) ((_cpu)->queue->suspendQ) |
646 | | #define _PR_WAITINGTOJOINQ(_cpu) ((_cpu)->queue->waitingToJoinQ) |
647 | | |
648 | | extern PRUint32 _pr_recycleThreads; /* Flag for behavior on thread cleanup */ |
649 | | extern PRLock *_pr_deadQLock; |
650 | | extern PRUint32 _pr_numNativeDead; |
651 | | extern PRUint32 _pr_numUserDead; |
652 | | extern PRCList _pr_deadNativeQ; |
653 | | extern PRCList _pr_deadUserQ; |
654 | | #define _PR_DEADNATIVEQ _pr_deadNativeQ |
655 | | #define _PR_DEADUSERQ _pr_deadUserQ |
656 | | #define _PR_DEADQ_LOCK PR_Lock(_pr_deadQLock); |
657 | | #define _PR_DEADQ_UNLOCK PR_Unlock(_pr_deadQLock); |
658 | | #define _PR_INC_DEADNATIVE (_pr_numNativeDead++) |
659 | | #define _PR_DEC_DEADNATIVE (_pr_numNativeDead--) |
660 | | #define _PR_NUM_DEADNATIVE (_pr_numNativeDead) |
661 | | #define _PR_INC_DEADUSER (_pr_numUserDead++) |
662 | | #define _PR_DEC_DEADUSER (_pr_numUserDead--) |
663 | | #define _PR_NUM_DEADUSER (_pr_numUserDead) |
664 | | |
665 | | extern PRUint32 _pr_utid; |
666 | | |
667 | | extern struct _PRCPU *_pr_primordialCPU; |
668 | | |
669 | | extern PRLock *_pr_activeLock; /* lock for userActive and systemActive */ |
670 | | extern PRInt32 _pr_userActive; /* number of active user threads */ |
671 | | extern PRInt32 _pr_systemActive; /* number of active system threads */ |
672 | | extern PRInt32 _pr_primordialExitCount; /* number of user threads left |
673 | | * before the primordial thread |
674 | | * can exit. */ |
675 | | extern PRCondVar *_pr_primordialExitCVar; /* the condition variable for |
676 | | * notifying the primordial thread |
677 | | * when all other user threads |
678 | | * have terminated. */ |
679 | | |
680 | | extern PRUintn _pr_maxPTDs; |
681 | | |
682 | | extern PRLock *_pr_terminationCVLock; |
683 | | |
684 | | /************************************************************************* |
685 | | * Internal routines either called by PR itself or from machine-dependent * |
686 | | * code. * |
687 | | *************************************************************************/ |
688 | | |
689 | | extern void _PR_ClockInterrupt(void); |
690 | | |
691 | | extern void _PR_Schedule(void); |
692 | | extern void _PR_SetThreadPriority( |
693 | | PRThread* thread, PRThreadPriority priority); |
694 | | |
695 | | /*********************************************************************** |
696 | | ** FUNCTION: _PR_NewSegment() |
697 | | ** DESCRIPTION: |
698 | | ** Allocate a memory segment. The "size" value is rounded up to the |
699 | | ** native system page size and a page aligned portion of memory is |
700 | | ** returned. This memory is not part of the malloc heap. If "vaddr" is |
701 | | ** not NULL then PR tries to allocate the segment at the desired virtual |
702 | | ** address. |
703 | | ** INPUTS: size: size of the desired memory segment |
704 | | ** vaddr: address at which the newly aquired segment is to be |
705 | | ** mapped into memory. |
706 | | ** OUTPUTS: a memory segment is allocated, a PRSegment is allocated |
707 | | ** RETURN: pointer to PRSegment |
708 | | ***********************************************************************/ |
709 | | extern PRSegment* _PR_NewSegment(PRUint32 size, void *vaddr); |
710 | | |
711 | | /*********************************************************************** |
712 | | ** FUNCTION: _PR_DestroySegment() |
713 | | ** DESCRIPTION: |
714 | | ** The memory segment and the PRSegment are freed |
715 | | ** INPUTS: seg: pointer to PRSegment to be freed |
716 | | ** OUTPUTS: the the PRSegment and its associated memory segment are freed |
717 | | ** RETURN: void |
718 | | ***********************************************************************/ |
719 | | extern void _PR_DestroySegment(PRSegment *seg); |
720 | | |
721 | | extern PRThreadStack * _PR_NewStack(PRUint32 stackSize); |
722 | | extern void _PR_FreeStack(PRThreadStack *stack); |
723 | | extern PRBool _PR_NotifyThread (PRThread *thread, PRThread *me); |
724 | | extern void _PR_NotifyLockedThread (PRThread *thread); |
725 | | |
726 | | NSPR_API(void) _PR_AddSleepQ(PRThread *thread, PRIntervalTime timeout); |
727 | | NSPR_API(void) _PR_DelSleepQ(PRThread *thread, PRBool propogate_time); |
728 | | |
729 | | extern void _PR_AddThreadToRunQ(PRThread *me, PRThread *thread); |
730 | | |
731 | | NSPR_API(PRThread*) _PR_CreateThread(PRThreadType type, |
732 | | void (*start)(void *arg), |
733 | | void *arg, |
734 | | PRThreadPriority priority, |
735 | | PRThreadScope scope, |
736 | | PRThreadState state, |
737 | | PRUint32 stackSize, |
738 | | PRUint32 flags); |
739 | | |
740 | | extern void _PR_NativeDestroyThread(PRThread *thread); |
741 | | extern void _PR_UserDestroyThread(PRThread *thread); |
742 | | |
743 | | extern PRThread* _PRI_AttachThread( |
744 | | PRThreadType type, PRThreadPriority priority, |
745 | | PRThreadStack *stack, PRUint32 flags); |
746 | | |
747 | | extern void _PRI_DetachThread(void); |
748 | | |
749 | | |
750 | | #define _PR_IO_PENDING(_thread) ((_thread)->io_pending) |
751 | | |
752 | | NSPR_API(void) _PR_MD_INIT_CPUS(); |
753 | | #define _PR_MD_INIT_CPUS _MD_INIT_CPUS |
754 | | |
755 | | NSPR_API(void) _PR_MD_WAKEUP_CPUS(); |
756 | | #define _PR_MD_WAKEUP_CPUS _MD_WAKEUP_CPUS |
757 | | |
758 | | /* Interrupts related */ |
759 | | |
760 | | NSPR_API(void) _PR_MD_START_INTERRUPTS(void); |
761 | | #define _PR_MD_START_INTERRUPTS _MD_START_INTERRUPTS |
762 | | |
763 | | NSPR_API(void) _PR_MD_STOP_INTERRUPTS(void); |
764 | | #define _PR_MD_STOP_INTERRUPTS _MD_STOP_INTERRUPTS |
765 | | |
766 | | NSPR_API(void) _PR_MD_ENABLE_CLOCK_INTERRUPTS(void); |
767 | | #define _PR_MD_ENABLE_CLOCK_INTERRUPTS _MD_ENABLE_CLOCK_INTERRUPTS |
768 | | |
769 | | NSPR_API(void) _PR_MD_DISABLE_CLOCK_INTERRUPTS(void); |
770 | | #define _PR_MD_DISABLE_CLOCK_INTERRUPTS _MD_DISABLE_CLOCK_INTERRUPTS |
771 | | |
772 | | NSPR_API(void) _PR_MD_BLOCK_CLOCK_INTERRUPTS(void); |
773 | | #define _PR_MD_BLOCK_CLOCK_INTERRUPTS _MD_BLOCK_CLOCK_INTERRUPTS |
774 | | |
775 | | NSPR_API(void) _PR_MD_UNBLOCK_CLOCK_INTERRUPTS(void); |
776 | | #define _PR_MD_UNBLOCK_CLOCK_INTERRUPTS _MD_UNBLOCK_CLOCK_INTERRUPTS |
777 | | |
778 | | /* The _PR_MD_WAIT_LOCK and _PR_MD_WAKEUP_WAITER functions put to sleep and |
779 | | * awaken a thread which is waiting on a lock or cvar. |
780 | | */ |
781 | | extern PRStatus _PR_MD_WAIT(PRThread *, PRIntervalTime timeout); |
782 | | #define _PR_MD_WAIT _MD_WAIT |
783 | | |
784 | | extern PRStatus _PR_MD_WAKEUP_WAITER(PRThread *); |
785 | | #define _PR_MD_WAKEUP_WAITER _MD_WAKEUP_WAITER |
786 | | |
787 | | #ifndef _PR_LOCAL_THREADS_ONLY /* not if only local threads supported */ |
788 | | NSPR_API(void) _PR_MD_CLOCK_INTERRUPT(void); |
789 | | #define _PR_MD_CLOCK_INTERRUPT _MD_CLOCK_INTERRUPT |
790 | | #endif |
791 | | |
792 | | /* Stack debugging */ |
793 | | NSPR_API(void) _PR_MD_INIT_STACK(PRThreadStack *ts, PRIntn redzone); |
794 | | #define _PR_MD_INIT_STACK _MD_INIT_STACK |
795 | | |
796 | | NSPR_API(void) _PR_MD_CLEAR_STACK(PRThreadStack* ts); |
797 | | #define _PR_MD_CLEAR_STACK _MD_CLEAR_STACK |
798 | | |
799 | | /* CPU related */ |
800 | | NSPR_API(PRInt32) _PR_MD_GET_INTSOFF(void); |
801 | | #define _PR_MD_GET_INTSOFF _MD_GET_INTSOFF |
802 | | |
803 | | NSPR_API(void) _PR_MD_SET_INTSOFF(PRInt32 _val); |
804 | | #define _PR_MD_SET_INTSOFF _MD_SET_INTSOFF |
805 | | |
806 | | NSPR_API(_PRCPU*) _PR_MD_CURRENT_CPU(void); |
807 | | #define _PR_MD_CURRENT_CPU _MD_CURRENT_CPU |
808 | | |
809 | | NSPR_API(void) _PR_MD_SET_CURRENT_CPU(_PRCPU *cpu); |
810 | | #define _PR_MD_SET_CURRENT_CPU _MD_SET_CURRENT_CPU |
811 | | |
812 | | NSPR_API(void) _PR_MD_INIT_RUNNING_CPU(_PRCPU *cpu); |
813 | | #define _PR_MD_INIT_RUNNING_CPU _MD_INIT_RUNNING_CPU |
814 | | |
815 | | /* |
816 | | * Returns the number of threads awoken or 0 if a timeout occurred; |
817 | | */ |
818 | | extern PRInt32 _PR_MD_PAUSE_CPU(PRIntervalTime timeout); |
819 | | #define _PR_MD_PAUSE_CPU _MD_PAUSE_CPU |
820 | | |
821 | | extern void _PR_MD_CLEANUP_BEFORE_EXIT(void); |
822 | | #define _PR_MD_CLEANUP_BEFORE_EXIT _MD_CLEANUP_BEFORE_EXIT |
823 | | |
824 | | extern void _PR_MD_EXIT(PRIntn status); |
825 | | #define _PR_MD_EXIT _MD_EXIT |
826 | | |
827 | | /* Locks related */ |
828 | | |
829 | | NSPR_API(void) _PR_MD_INIT_LOCKS(void); |
830 | | #define _PR_MD_INIT_LOCKS _MD_INIT_LOCKS |
831 | | |
832 | | NSPR_API(PRStatus) _PR_MD_NEW_LOCK(_MDLock *md); |
833 | | #define _PR_MD_NEW_LOCK _MD_NEW_LOCK |
834 | | |
835 | | NSPR_API(void) _PR_MD_FREE_LOCK(_MDLock *md); |
836 | | #define _PR_MD_FREE_LOCK _MD_FREE_LOCK |
837 | | |
838 | | NSPR_API(void) _PR_MD_LOCK(_MDLock *md); |
839 | | #define _PR_MD_LOCK _MD_LOCK |
840 | | |
841 | | /* Return 0 on success, a nonzero value on failure. */ |
842 | | NSPR_API(PRIntn) _PR_MD_TEST_AND_LOCK(_MDLock *md); |
843 | | #define _PR_MD_TEST_AND_LOCK _MD_TEST_AND_LOCK |
844 | | |
845 | | NSPR_API(void) _PR_MD_UNLOCK(_MDLock *md); |
846 | | #define _PR_MD_UNLOCK _MD_UNLOCK |
847 | | |
848 | | NSPR_API(void) _PR_MD_IOQ_LOCK(void); |
849 | | #define _PR_MD_IOQ_LOCK _MD_IOQ_LOCK |
850 | | |
851 | | NSPR_API(void) _PR_MD_IOQ_UNLOCK(void); |
852 | | #define _PR_MD_IOQ_UNLOCK _MD_IOQ_UNLOCK |
853 | | |
854 | | #ifndef _PR_LOCAL_THREADS_ONLY /* not if only local threads supported */ |
855 | | /* Semaphore related -- only for native threads */ |
856 | | #ifdef HAVE_CVAR_BUILT_ON_SEM |
857 | | NSPR_API(void) _PR_MD_NEW_SEM(_MDSemaphore *md, PRUintn value); |
858 | | #define _PR_MD_NEW_SEM _MD_NEW_SEM |
859 | | |
860 | | NSPR_API(void) _PR_MD_DESTROY_SEM(_MDSemaphore *md); |
861 | | #define _PR_MD_DESTROY_SEM _MD_DESTROY_SEM |
862 | | |
863 | | NSPR_API(PRStatus) _PR_MD_TIMED_WAIT_SEM( |
864 | | _MDSemaphore *md, PRIntervalTime timeout); |
865 | | #define _PR_MD_TIMED_WAIT_SEM _MD_TIMED_WAIT_SEM |
866 | | |
867 | | NSPR_API(PRStatus) _PR_MD_WAIT_SEM(_MDSemaphore *md); |
868 | | #define _PR_MD_WAIT_SEM _MD_WAIT_SEM |
869 | | |
870 | | NSPR_API(void) _PR_MD_POST_SEM(_MDSemaphore *md); |
871 | | #define _PR_MD_POST_SEM _MD_POST_SEM |
872 | | #endif /* HAVE_CVAR_BUILT_ON_SEM */ |
873 | | |
874 | | #endif |
875 | | |
876 | | /* Condition Variables related -- only for native threads */ |
877 | | |
878 | | #ifndef _PR_LOCAL_THREADS_ONLY /* not if only local threads supported */ |
879 | | NSPR_API(PRInt32) _PR_MD_NEW_CV(_MDCVar *md); |
880 | | #define _PR_MD_NEW_CV _MD_NEW_CV |
881 | | |
882 | | NSPR_API(void) _PR_MD_FREE_CV(_MDCVar *md); |
883 | | #define _PR_MD_FREE_CV _MD_FREE_CV |
884 | | |
885 | | NSPR_API(void) _PR_MD_WAIT_CV( |
886 | | _MDCVar *mdCVar,_MDLock *mdLock,PRIntervalTime timeout); |
887 | | #define _PR_MD_WAIT_CV _MD_WAIT_CV |
888 | | |
889 | | NSPR_API(void) _PR_MD_NOTIFY_CV(_MDCVar *md, _MDLock *lock); |
890 | | #define _PR_MD_NOTIFY_CV _MD_NOTIFY_CV |
891 | | |
892 | | NSPR_API(void) _PR_MD_NOTIFYALL_CV(_MDCVar *md, _MDLock *lock); |
893 | | #define _PR_MD_NOTIFYALL_CV _MD_NOTIFYALL_CV |
894 | | #endif /* _PR_LOCAL_THREADS_ONLY */ |
895 | | |
896 | | /* Threads related */ |
897 | | NSPR_API(PRThread*) _PR_MD_CURRENT_THREAD(void); |
898 | | #define _PR_MD_CURRENT_THREAD _MD_CURRENT_THREAD |
899 | | |
900 | | NSPR_API(PRThread*) _PR_MD_GET_ATTACHED_THREAD(void); |
901 | | #define _PR_MD_GET_ATTACHED_THREAD _MD_GET_ATTACHED_THREAD |
902 | | |
903 | | NSPR_API(PRThread*) _PR_MD_LAST_THREAD(void); |
904 | | #define _PR_MD_LAST_THREAD _MD_LAST_THREAD |
905 | | |
906 | | NSPR_API(void) _PR_MD_SET_CURRENT_THREAD(PRThread *thread); |
907 | | #define _PR_MD_SET_CURRENT_THREAD _MD_SET_CURRENT_THREAD |
908 | | |
909 | | NSPR_API(void) _PR_MD_SET_LAST_THREAD(PRThread *thread); |
910 | | #define _PR_MD_SET_LAST_THREAD _MD_SET_LAST_THREAD |
911 | | |
912 | | extern PRStatus _PR_MD_INIT_THREAD(PRThread *thread); |
913 | | #define _PR_MD_INIT_THREAD _MD_INIT_THREAD |
914 | | |
915 | | extern void _PR_MD_EXIT_THREAD(PRThread *thread); |
916 | | #define _PR_MD_EXIT_THREAD _MD_EXIT_THREAD |
917 | | |
918 | | #ifndef _PR_LOCAL_THREADS_ONLY /* not if only local threads supported */ |
919 | | |
920 | | NSPR_API(PRStatus) _PR_MD_INIT_ATTACHED_THREAD(PRThread *thread); |
921 | | #define _PR_MD_INIT_ATTACHED_THREAD _MD_INIT_ATTACHED_THREAD |
922 | | |
923 | | extern void _PR_MD_SUSPEND_THREAD(PRThread *thread); |
924 | | #define _PR_MD_SUSPEND_THREAD _MD_SUSPEND_THREAD |
925 | | |
926 | | extern void _PR_MD_RESUME_THREAD(PRThread *thread); |
927 | | #define _PR_MD_RESUME_THREAD _MD_RESUME_THREAD |
928 | | |
929 | | extern void _PR_MD_SUSPEND_CPU(_PRCPU *cpu); |
930 | | #define _PR_MD_SUSPEND_CPU _MD_SUSPEND_CPU |
931 | | |
932 | | extern void _PR_MD_RESUME_CPU(_PRCPU *cpu); |
933 | | #define _PR_MD_RESUME_CPU _MD_RESUME_CPU |
934 | | |
935 | | extern void _PR_MD_BEGIN_SUSPEND_ALL(void); |
936 | | #define _PR_MD_BEGIN_SUSPEND_ALL _MD_BEGIN_SUSPEND_ALL |
937 | | |
938 | | extern void _PR_MD_END_SUSPEND_ALL(void); |
939 | | #define _PR_MD_END_SUSPEND_ALL _MD_END_SUSPEND_ALL |
940 | | |
941 | | extern void _PR_MD_BEGIN_RESUME_ALL(void); |
942 | | #define _PR_MD_BEGIN_RESUME_ALL _MD_BEGIN_RESUME_ALL |
943 | | |
944 | | extern void _PR_MD_END_RESUME_ALL(void); |
945 | | #define _PR_MD_END_RESUME_ALL _MD_END_RESUME_ALL |
946 | | |
947 | | #endif /* !_PR_LOCAL_THREADS_ONLY */ |
948 | | |
949 | | extern void _PR_MD_CLEAN_THREAD(PRThread *thread); |
950 | | #define _PR_MD_CLEAN_THREAD _MD_CLEAN_THREAD |
951 | | |
952 | | #ifdef HAVE_CUSTOM_USER_THREADS |
953 | | extern void _PR_MD_CREATE_PRIMORDIAL_USER_THREAD(PRThread *); |
954 | | #define _PR_MD_CREATE_PRIMORDIAL_USER_THREAD _MD_CREATE_PRIMORDIAL_USER_THREAD |
955 | | |
956 | | extern PRThread* _PR_MD_CREATE_USER_THREAD( |
957 | | PRUint32 stacksize, |
958 | | void (*start)(void *), |
959 | | void *arg); |
960 | | #define _PR_MD_CREATE_USER_THREAD _MD_CREATE_USER_THREAD |
961 | | #endif |
962 | | |
963 | | extern PRStatus _PR_MD_CREATE_THREAD( |
964 | | PRThread *thread, |
965 | | void (*start) (void *), |
966 | | PRThreadPriority priority, |
967 | | PRThreadScope scope, |
968 | | PRThreadState state, |
969 | | PRUint32 stackSize); |
970 | | #define _PR_MD_CREATE_THREAD _MD_CREATE_THREAD |
971 | | |
972 | | extern void _PR_MD_JOIN_THREAD(_MDThread *md); |
973 | | #define _PR_MD_JOIN_THREAD _MD_JOIN_THREAD |
974 | | |
975 | | extern void _PR_MD_END_THREAD(void); |
976 | | #define _PR_MD_END_THREAD _MD_END_THREAD |
977 | | |
978 | | extern void _PR_MD_YIELD(void); |
979 | | #define _PR_MD_YIELD _MD_YIELD |
980 | | |
981 | | extern void _PR_MD_SET_PRIORITY(_MDThread *md, PRThreadPriority newPri); |
982 | | #define _PR_MD_SET_PRIORITY _MD_SET_PRIORITY |
983 | | |
984 | | extern void _PR_MD_SET_CURRENT_THREAD_NAME(const char *name); |
985 | | #define _PR_MD_SET_CURRENT_THREAD_NAME _MD_SET_CURRENT_THREAD_NAME |
986 | | |
987 | | NSPR_API(void) _PR_MD_SUSPENDALL(void); |
988 | | #define _PR_MD_SUSPENDALL _MD_SUSPENDALL |
989 | | |
990 | | NSPR_API(void) _PR_MD_RESUMEALL(void); |
991 | | #define _PR_MD_RESUMEALL _MD_RESUMEALL |
992 | | |
993 | | extern void _PR_MD_INIT_CONTEXT( |
994 | | PRThread *thread, char *top, void (*start) (void), PRBool *status); |
995 | | #define _PR_MD_INIT_CONTEXT _MD_INIT_CONTEXT |
996 | | |
997 | | extern void _PR_MD_SWITCH_CONTEXT(PRThread *thread); |
998 | | #define _PR_MD_SWITCH_CONTEXT _MD_SWITCH_CONTEXT |
999 | | |
1000 | | extern void _PR_MD_RESTORE_CONTEXT(PRThread *thread); |
1001 | | #define _PR_MD_RESTORE_CONTEXT _MD_RESTORE_CONTEXT |
1002 | | |
1003 | | /* Segment related */ |
1004 | | extern void _PR_MD_INIT_SEGS(void); |
1005 | | #define _PR_MD_INIT_SEGS _MD_INIT_SEGS |
1006 | | |
1007 | | extern PRStatus _PR_MD_ALLOC_SEGMENT(PRSegment *seg, PRUint32 size, void *vaddr); |
1008 | | #define _PR_MD_ALLOC_SEGMENT _MD_ALLOC_SEGMENT |
1009 | | |
1010 | | extern void _PR_MD_FREE_SEGMENT(PRSegment *seg); |
1011 | | #define _PR_MD_FREE_SEGMENT _MD_FREE_SEGMENT |
1012 | | |
1013 | | /* Directory enumeration related */ |
1014 | | extern PRStatus _PR_MD_OPEN_DIR(_MDDir *md,const char *name); |
1015 | | #define _PR_MD_OPEN_DIR _MD_OPEN_DIR |
1016 | | |
1017 | | extern char * _PR_MD_READ_DIR(_MDDir *md, PRIntn flags); |
1018 | | #define _PR_MD_READ_DIR _MD_READ_DIR |
1019 | | |
1020 | | extern PRInt32 _PR_MD_CLOSE_DIR(_MDDir *md); |
1021 | | #define _PR_MD_CLOSE_DIR _MD_CLOSE_DIR |
1022 | | |
1023 | | /* Named semaphores related */ |
1024 | | extern PRSem * _PR_MD_OPEN_SEMAPHORE( |
1025 | | const char *osname, PRIntn flags, PRIntn mode, PRUintn value); |
1026 | | #define _PR_MD_OPEN_SEMAPHORE _MD_OPEN_SEMAPHORE |
1027 | | |
1028 | | extern PRStatus _PR_MD_WAIT_SEMAPHORE(PRSem *sem); |
1029 | | #define _PR_MD_WAIT_SEMAPHORE _MD_WAIT_SEMAPHORE |
1030 | | |
1031 | | extern PRStatus _PR_MD_POST_SEMAPHORE(PRSem *sem); |
1032 | | #define _PR_MD_POST_SEMAPHORE _MD_POST_SEMAPHORE |
1033 | | |
1034 | | extern PRStatus _PR_MD_CLOSE_SEMAPHORE(PRSem *sem); |
1035 | | #define _PR_MD_CLOSE_SEMAPHORE _MD_CLOSE_SEMAPHORE |
1036 | | |
1037 | | extern PRStatus _PR_MD_DELETE_SEMAPHORE(const char *osname); |
1038 | | #define _PR_MD_DELETE_SEMAPHORE _MD_DELETE_SEMAPHORE |
1039 | | |
1040 | | /* I/O related */ |
1041 | | extern void _PR_MD_INIT_FILEDESC(PRFileDesc *fd); |
1042 | | #define _PR_MD_INIT_FILEDESC _MD_INIT_FILEDESC |
1043 | | |
1044 | | extern void _PR_MD_MAKE_NONBLOCK(PRFileDesc *fd); |
1045 | | #define _PR_MD_MAKE_NONBLOCK _MD_MAKE_NONBLOCK |
1046 | | |
1047 | | /* File I/O related */ |
1048 | | extern PROsfd _PR_MD_OPEN(const char *name, PRIntn osflags, PRIntn mode); |
1049 | | #define _PR_MD_OPEN _MD_OPEN |
1050 | | |
1051 | | extern PROsfd _PR_MD_OPEN_FILE(const char *name, PRIntn osflags, PRIntn mode); |
1052 | | #define _PR_MD_OPEN_FILE _MD_OPEN_FILE |
1053 | | |
1054 | | extern PRInt32 _PR_MD_CLOSE_FILE(PROsfd osfd); |
1055 | | #define _PR_MD_CLOSE_FILE _MD_CLOSE_FILE |
1056 | | |
1057 | | extern PRInt32 _PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 amount); |
1058 | | #define _PR_MD_READ _MD_READ |
1059 | | |
1060 | | extern PRInt32 _PR_MD_WRITE(PRFileDesc *fd, const void *buf, PRInt32 amount); |
1061 | | #define _PR_MD_WRITE _MD_WRITE |
1062 | | |
1063 | | extern PRInt32 _PR_MD_WRITEV( |
1064 | | PRFileDesc *fd, const struct PRIOVec *iov, |
1065 | | PRInt32 iov_size, PRIntervalTime timeout); |
1066 | | #define _PR_MD_WRITEV _MD_WRITEV |
1067 | | |
1068 | | extern PRInt32 _PR_MD_FSYNC(PRFileDesc *fd); |
1069 | | #define _PR_MD_FSYNC _MD_FSYNC |
1070 | | |
1071 | | extern PRInt32 _PR_MD_DELETE(const char *name); |
1072 | | #define _PR_MD_DELETE _MD_DELETE |
1073 | | |
1074 | | extern PRInt32 _PR_MD_RENAME(const char *from, const char *to); |
1075 | | #define _PR_MD_RENAME _MD_RENAME |
1076 | | |
1077 | | extern PRInt32 _PR_MD_ACCESS(const char *name, PRAccessHow how); |
1078 | | #define _PR_MD_ACCESS _MD_ACCESS |
1079 | | |
1080 | | extern PRInt32 _PR_MD_STAT(const char *name, struct stat *buf); |
1081 | | #define _PR_MD_STAT _MD_STAT |
1082 | | |
1083 | | extern PRInt32 _PR_MD_MKDIR(const char *name, PRIntn mode); |
1084 | | #define _PR_MD_MKDIR _MD_MKDIR |
1085 | | |
1086 | | extern PRInt32 _PR_MD_MAKE_DIR(const char *name, PRIntn mode); |
1087 | | #define _PR_MD_MAKE_DIR _MD_MAKE_DIR |
1088 | | |
1089 | | extern PRInt32 _PR_MD_RMDIR(const char *name); |
1090 | | #define _PR_MD_RMDIR _MD_RMDIR |
1091 | | |
1092 | | #ifdef MOZ_UNICODE |
1093 | | /* UTF16 File I/O related */ |
1094 | | extern PRStatus _PR_MD_OPEN_DIR_UTF16(_MDDirUTF16 *md, const PRUnichar *name); |
1095 | | #define _PR_MD_OPEN_DIR_UTF16 _MD_OPEN_DIR_UTF16 |
1096 | | |
1097 | | extern PROsfd _PR_MD_OPEN_FILE_UTF16(const PRUnichar *name, PRIntn osflags, PRIntn mode); |
1098 | | #define _PR_MD_OPEN_FILE_UTF16 _MD_OPEN_FILE_UTF16 |
1099 | | |
1100 | | extern PRUnichar * _PR_MD_READ_DIR_UTF16(_MDDirUTF16 *md, PRIntn flags); |
1101 | | #define _PR_MD_READ_DIR_UTF16 _MD_READ_DIR_UTF16 |
1102 | | |
1103 | | extern PRInt32 _PR_MD_CLOSE_DIR_UTF16(_MDDirUTF16 *md); |
1104 | | #define _PR_MD_CLOSE_DIR_UTF16 _MD_CLOSE_DIR_UTF16 |
1105 | | |
1106 | | extern PRInt32 _PR_MD_GETFILEINFO64_UTF16(const PRUnichar *fn, PRFileInfo64 *info); |
1107 | | #define _PR_MD_GETFILEINFO64_UTF16 _MD_GETFILEINFO64_UTF16 |
1108 | | #endif /* MOZ_UNICODE */ |
1109 | | |
1110 | | /* Socket I/O related */ |
1111 | | extern void _PR_MD_INIT_IO(void); |
1112 | | #define _PR_MD_INIT_IO _MD_INIT_IO |
1113 | | |
1114 | | extern PRInt32 _PR_MD_CLOSE_SOCKET(PROsfd osfd); |
1115 | | #define _PR_MD_CLOSE_SOCKET _MD_CLOSE_SOCKET |
1116 | | |
1117 | | extern PRInt32 _PR_MD_CONNECT( |
1118 | | PRFileDesc *fd, const PRNetAddr *addr, |
1119 | | PRUint32 addrlen, PRIntervalTime timeout); |
1120 | | #define _PR_MD_CONNECT _MD_CONNECT |
1121 | | |
1122 | | extern PROsfd _PR_MD_ACCEPT( |
1123 | | PRFileDesc *fd, PRNetAddr *addr, |
1124 | | PRUint32 *addrlen, PRIntervalTime timeout); |
1125 | | #define _PR_MD_ACCEPT _MD_ACCEPT |
1126 | | |
1127 | | extern PRInt32 _PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen); |
1128 | | #define _PR_MD_BIND _MD_BIND |
1129 | | |
1130 | | extern PRInt32 _PR_MD_LISTEN(PRFileDesc *fd, PRIntn backlog); |
1131 | | #define _PR_MD_LISTEN _MD_LISTEN |
1132 | | |
1133 | | extern PRInt32 _PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how); |
1134 | | #define _PR_MD_SHUTDOWN _MD_SHUTDOWN |
1135 | | |
1136 | | extern PRInt32 _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, |
1137 | | PRIntn flags, PRIntervalTime timeout); |
1138 | | #define _PR_MD_RECV _MD_RECV |
1139 | | |
1140 | | extern PRInt32 _PR_MD_SEND( |
1141 | | PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, |
1142 | | PRIntervalTime timeout); |
1143 | | #define _PR_MD_SEND _MD_SEND |
1144 | | |
1145 | | extern PRInt32 _PR_MD_ACCEPT_READ(PRFileDesc *sd, PROsfd *newSock, |
1146 | | PRNetAddr **raddr, void *buf, PRInt32 amount, |
1147 | | PRIntervalTime timeout); |
1148 | | #define _PR_MD_ACCEPT_READ _MD_ACCEPT_READ |
1149 | | |
1150 | | #ifdef WIN32 |
1151 | | extern PROsfd _PR_MD_FAST_ACCEPT(PRFileDesc *fd, PRNetAddr *addr, |
1152 | | PRUint32 *addrlen, PRIntervalTime timeout, |
1153 | | PRBool fast, |
1154 | | _PR_AcceptTimeoutCallback callback, |
1155 | | void *callbackArg); |
1156 | | |
1157 | | extern PRInt32 _PR_MD_FAST_ACCEPT_READ(PRFileDesc *sd, PROsfd *newSock, |
1158 | | PRNetAddr **raddr, void *buf, PRInt32 amount, |
1159 | | PRIntervalTime timeout, PRBool fast, |
1160 | | _PR_AcceptTimeoutCallback callback, |
1161 | | void *callbackArg); |
1162 | | |
1163 | | extern void _PR_MD_UPDATE_ACCEPT_CONTEXT(PROsfd s, PROsfd ls); |
1164 | | #define _PR_MD_UPDATE_ACCEPT_CONTEXT _MD_UPDATE_ACCEPT_CONTEXT |
1165 | | /* |
1166 | | * The NSPR epoch (00:00:00 1 Jan 1970 UTC) in FILETIME. |
1167 | | * We store the value in a PRTime variable for convenience. |
1168 | | * This constant is used by _PR_FileTimeToPRTime(). |
1169 | | * This is defined in ntmisc.c |
1170 | | */ |
1171 | | extern const PRTime _pr_filetime_offset; |
1172 | | #endif /* WIN32 */ |
1173 | | |
1174 | | extern PRInt32 _PR_MD_SENDFILE( |
1175 | | PRFileDesc *sock, PRSendFileData *sfd, |
1176 | | PRInt32 flags, PRIntervalTime timeout); |
1177 | | #define _PR_MD_SENDFILE _MD_SENDFILE |
1178 | | |
1179 | | extern PRStatus _PR_MD_GETSOCKNAME( |
1180 | | PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen); |
1181 | | #define _PR_MD_GETSOCKNAME _MD_GETSOCKNAME |
1182 | | |
1183 | | extern PRStatus _PR_MD_GETPEERNAME( |
1184 | | PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen); |
1185 | | #define _PR_MD_GETPEERNAME _MD_GETPEERNAME |
1186 | | |
1187 | | extern PRStatus _PR_MD_GETSOCKOPT( |
1188 | | PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen); |
1189 | | #define _PR_MD_GETSOCKOPT _MD_GETSOCKOPT |
1190 | | |
1191 | | extern PRStatus _PR_MD_SETSOCKOPT( |
1192 | | PRFileDesc *fd, PRInt32 level, PRInt32 optname, |
1193 | | const char* optval, PRInt32 optlen); |
1194 | | #define _PR_MD_SETSOCKOPT _MD_SETSOCKOPT |
1195 | | |
1196 | | extern PRStatus PR_CALLBACK _PR_SocketGetSocketOption( |
1197 | | PRFileDesc *fd, PRSocketOptionData *data); |
1198 | | |
1199 | | extern PRStatus PR_CALLBACK _PR_SocketSetSocketOption( |
1200 | | PRFileDesc *fd, const PRSocketOptionData *data); |
1201 | | |
1202 | | extern PRInt32 _PR_MD_RECVFROM( |
1203 | | PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, |
1204 | | PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout); |
1205 | | #define _PR_MD_RECVFROM _MD_RECVFROM |
1206 | | |
1207 | | extern PRInt32 _PR_MD_SENDTO( |
1208 | | PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, |
1209 | | const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout); |
1210 | | #define _PR_MD_SENDTO _MD_SENDTO |
1211 | | |
1212 | | #if defined(_WIN64) && defined(WIN95) |
1213 | | extern PRInt32 _PR_MD_TCPSENDTO( |
1214 | | PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, |
1215 | | const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout); |
1216 | | #define _PR_MD_TCPSENDTO _MD_TCPSENDTO |
1217 | | #endif |
1218 | | |
1219 | | extern PRInt32 _PR_MD_SOCKETPAIR(int af, int type, int flags, PROsfd *osfd); |
1220 | | #define _PR_MD_SOCKETPAIR _MD_SOCKETPAIR |
1221 | | |
1222 | | extern PROsfd _PR_MD_SOCKET(int af, int type, int flags); |
1223 | | #define _PR_MD_SOCKET _MD_SOCKET |
1224 | | |
1225 | | extern PRInt32 _PR_MD_SOCKETAVAILABLE(PRFileDesc *fd); |
1226 | | #define _PR_MD_SOCKETAVAILABLE _MD_SOCKETAVAILABLE |
1227 | | |
1228 | | extern PRInt32 _PR_MD_PIPEAVAILABLE(PRFileDesc *fd); |
1229 | | #define _PR_MD_PIPEAVAILABLE _MD_PIPEAVAILABLE |
1230 | | |
1231 | | extern PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, |
1232 | | PRIntervalTime timeout); |
1233 | | #define _PR_MD_PR_POLL _MD_PR_POLL |
1234 | | |
1235 | | /* |
1236 | | * Initialize fd->secret->inheritable for a newly created fd. |
1237 | | * If 'imported' is false, the osfd (i.e., fd->secret->md.osfd) |
1238 | | * was created by NSPR and hence has the OS-dependent default |
1239 | | * inheritable attribute. If 'imported' is true, the osfd was |
1240 | | * not created by NSPR and hence a system call is required to |
1241 | | * query its inheritable attribute. Since we may never need to |
1242 | | * know the inheritable attribute of a fd, a platform may choose |
1243 | | * to initialize fd->secret->inheritable of an imported fd to |
1244 | | * _PR_TRI_UNKNOWN and only pay the cost of the system call |
1245 | | * (in _PR_MD_QUERY_FD_INHERITABLE) when necessary. |
1246 | | */ |
1247 | | extern void _PR_MD_INIT_FD_INHERITABLE(PRFileDesc *fd, PRBool imported); |
1248 | | #define _PR_MD_INIT_FD_INHERITABLE _MD_INIT_FD_INHERITABLE |
1249 | | |
1250 | | extern PRStatus _PR_MD_SET_FD_INHERITABLE(PRFileDesc *fd, PRBool inheritable); |
1251 | | #define _PR_MD_SET_FD_INHERITABLE _MD_SET_FD_INHERITABLE |
1252 | | |
1253 | | |
1254 | | #define _PR_PROCESS_TIMEOUT_INTERRUPT_ERRORS(me) \ |
1255 | | if (_PR_PENDING_INTERRUPT(me)) { \ |
1256 | | me->flags &= ~_PR_INTERRUPT; \ |
1257 | | PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0); \ |
1258 | | } else { \ |
1259 | | PR_SetError(PR_IO_TIMEOUT_ERROR, 0); \ |
1260 | | } |
1261 | | |
1262 | | extern void *_PR_MD_GET_SP(PRThread *thread); |
1263 | | #define _PR_MD_GET_SP _MD_GET_SP |
1264 | | |
1265 | | #endif /* defined(_PR_PTHREADS) */ |
1266 | | |
1267 | | /************************************************************************/ |
1268 | | /************************************************************************* |
1269 | | ** The remainder of the definitions are shared by pthreads and the classic |
1270 | | ** NSPR code. These too may be conditionalized. |
1271 | | *************************************************************************/ |
1272 | | /************************************************************************/ |
1273 | | |
1274 | | extern PROffset32 _PR_MD_LSEEK(PRFileDesc *fd, PROffset32 offset, PRSeekWhence whence); |
1275 | 0 | #define _PR_MD_LSEEK _MD_LSEEK |
1276 | | |
1277 | | extern PROffset64 _PR_MD_LSEEK64(PRFileDesc *fd, PROffset64 offset, PRSeekWhence whence); |
1278 | 0 | #define _PR_MD_LSEEK64 _MD_LSEEK64 |
1279 | | |
1280 | | extern PRInt32 _PR_MD_GETFILEINFO(const char *fn, PRFileInfo *info); |
1281 | 0 | #define _PR_MD_GETFILEINFO _MD_GETFILEINFO |
1282 | | |
1283 | | extern PRInt32 _PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info); |
1284 | 0 | #define _PR_MD_GETFILEINFO64 _MD_GETFILEINFO64 |
1285 | | |
1286 | | extern PRInt32 _PR_MD_GETOPENFILEINFO(const PRFileDesc *fd, PRFileInfo *info); |
1287 | 0 | #define _PR_MD_GETOPENFILEINFO _MD_GETOPENFILEINFO |
1288 | | |
1289 | | extern PRInt32 _PR_MD_GETOPENFILEINFO64(const PRFileDesc *fd, PRFileInfo64 *info); |
1290 | 0 | #define _PR_MD_GETOPENFILEINFO64 _MD_GETOPENFILEINFO64 |
1291 | | |
1292 | | |
1293 | | /*****************************************************************************/ |
1294 | | /************************** File descriptor caching **************************/ |
1295 | | /*****************************************************************************/ |
1296 | | extern void _PR_InitFdCache(void); |
1297 | | extern void _PR_CleanupFdCache(void); |
1298 | | extern PRFileDesc *_PR_Getfd(void); |
1299 | | extern void _PR_Putfd(PRFileDesc *fd); |
1300 | | |
1301 | | /* |
1302 | | * These flags are used by NSPR temporarily in the poll |
1303 | | * descriptor's out_flags field to record the mapping of |
1304 | | * NSPR's poll flags to the system poll flags. |
1305 | | * |
1306 | | * If _PR_POLL_READ_SYS_WRITE bit is set, it means the |
1307 | | * PR_POLL_READ flag specified by the topmost layer is |
1308 | | * mapped to the WRITE flag at the system layer. Similarly |
1309 | | * for the other three _PR_POLL_XXX_SYS_YYY flags. It is |
1310 | | * assumed that the PR_POLL_EXCEPT flag doesn't get mapped |
1311 | | * to other flags. |
1312 | | */ |
1313 | 0 | #define _PR_POLL_READ_SYS_READ 0x1 |
1314 | 0 | #define _PR_POLL_READ_SYS_WRITE 0x2 |
1315 | 0 | #define _PR_POLL_WRITE_SYS_READ 0x4 |
1316 | 0 | #define _PR_POLL_WRITE_SYS_WRITE 0x8 |
1317 | | |
1318 | | /* |
1319 | | ** These methods are coerced into file descriptor methods table |
1320 | | ** when the intended service is inappropriate for the particular |
1321 | | ** type of file descriptor. |
1322 | | */ |
1323 | | extern PRIntn _PR_InvalidInt(void); |
1324 | | extern PRInt16 _PR_InvalidInt16(void); |
1325 | | extern PRInt64 _PR_InvalidInt64(void); |
1326 | | extern PRStatus _PR_InvalidStatus(void); |
1327 | | extern PRFileDesc *_PR_InvalidDesc(void); |
1328 | | |
1329 | | extern PRIOMethods _pr_faulty_methods; |
1330 | | |
1331 | | /* |
1332 | | ** The PR_NETADDR_SIZE macro can only be called on a PRNetAddr union |
1333 | | ** whose 'family' field is set. It returns the size of the union |
1334 | | ** member corresponding to the specified address family. |
1335 | | */ |
1336 | | |
1337 | | extern PRUintn _PR_NetAddrSize(const PRNetAddr* addr); |
1338 | | |
1339 | | #if defined(_PR_INET6) |
1340 | | |
1341 | 0 | #define PR_NETADDR_SIZE(_addr) _PR_NetAddrSize(_addr) |
1342 | | |
1343 | | #elif defined(_PR_HAVE_MD_SOCKADDR_IN6) |
1344 | | |
1345 | | /* |
1346 | | ** Under the following conditions: |
1347 | | ** 1. _PR_INET6 is not defined; |
1348 | | ** 2. _PR_INET6_PROBE is defined; |
1349 | | ** 3. struct sockaddr_in6 has nonstandard fields at the end |
1350 | | ** (e.g., on Solaris 8), |
1351 | | ** (_addr)->ipv6 is smaller than struct sockaddr_in6, and |
1352 | | ** hence we can't pass sizeof((_addr)->ipv6) to socket |
1353 | | ** functions such as connect because they would fail with |
1354 | | ** EINVAL. |
1355 | | ** |
1356 | | ** To pass the correct socket address length to socket |
1357 | | ** functions, define the macro _PR_HAVE_MD_SOCKADDR_IN6 and |
1358 | | ** define struct _md_sockaddr_in6 to be isomorphic to |
1359 | | ** struct sockaddr_in6. |
1360 | | */ |
1361 | | |
1362 | | #if defined(XP_UNIX) |
1363 | | #define PR_NETADDR_SIZE(_addr) \ |
1364 | | ((_addr)->raw.family == PR_AF_INET \ |
1365 | | ? sizeof((_addr)->inet) \ |
1366 | | : ((_addr)->raw.family == PR_AF_INET6 \ |
1367 | | ? sizeof(struct _md_sockaddr_in6) \ |
1368 | | : sizeof((_addr)->local))) |
1369 | | #else |
1370 | | #define PR_NETADDR_SIZE(_addr) \ |
1371 | | ((_addr)->raw.family == PR_AF_INET \ |
1372 | | ? sizeof((_addr)->inet) \ |
1373 | | : sizeof(struct _md_sockaddr_in6)) |
1374 | | #endif /* defined(XP_UNIX) */ |
1375 | | |
1376 | | #else |
1377 | | |
1378 | | #if defined(XP_UNIX) |
1379 | | #define PR_NETADDR_SIZE(_addr) \ |
1380 | | ((_addr)->raw.family == PR_AF_INET \ |
1381 | | ? sizeof((_addr)->inet) \ |
1382 | | : ((_addr)->raw.family == PR_AF_INET6 \ |
1383 | | ? sizeof((_addr)->ipv6) \ |
1384 | | : sizeof((_addr)->local))) |
1385 | | #else |
1386 | | #define PR_NETADDR_SIZE(_addr) \ |
1387 | | ((_addr)->raw.family == PR_AF_INET \ |
1388 | | ? sizeof((_addr)->inet) \ |
1389 | | : sizeof((_addr)->ipv6)) |
1390 | | #endif /* defined(XP_UNIX) */ |
1391 | | |
1392 | | #endif /* defined(_PR_INET6) */ |
1393 | | |
1394 | | extern PRStatus _PR_MapOptionName( |
1395 | | PRSockOption optname, PRInt32 *level, PRInt32 *name); |
1396 | | extern void _PR_InitThreads( |
1397 | | PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs); |
1398 | | |
1399 | | struct PRLock { |
1400 | | #if defined(_PR_PTHREADS) |
1401 | | pthread_mutex_t mutex; /* the underlying lock */ |
1402 | | _PT_Notified notified; /* array of conditions notified */ |
1403 | | PRBool locked; /* whether the mutex is locked */ |
1404 | | pthread_t owner; /* if locked, current lock owner */ |
1405 | | #elif defined(_PR_BTHREADS) |
1406 | | sem_id semaphoreID; /* the underlying lock */ |
1407 | | int32 benaphoreCount; /* number of people in lock */ |
1408 | | thread_id owner; /* current lock owner */ |
1409 | | #else /* not pthreads or Be threads */ |
1410 | | PRCList links; /* linkage for PRThread.lockList */ |
1411 | | struct PRThread *owner; /* current lock owner */ |
1412 | | PRCList waitQ; /* list of threads waiting for lock */ |
1413 | | PRThreadPriority priority; /* priority of lock */ |
1414 | | PRThreadPriority boostPriority; /* boosted priority of lock owner */ |
1415 | | _MDLock ilock; /* Internal Lock to protect user-level fields */ |
1416 | | #endif |
1417 | | }; |
1418 | | |
1419 | | struct PRCondVar { |
1420 | | PRLock *lock; /* associated lock that protects the condition */ |
1421 | | #if defined(_PR_PTHREADS) |
1422 | | pthread_cond_t cv; /* underlying pthreads condition */ |
1423 | | PRInt32 notify_pending; /* CV has destroy pending notification */ |
1424 | | #elif defined(_PR_BTHREADS) |
1425 | | sem_id sem; /* the underlying lock */ |
1426 | | sem_id handshakeSem; /* the lock for 'notify'-threads waiting for confirmation */ |
1427 | | sem_id signalSem; /* the lock for threads waiting for someone to notify */ |
1428 | | volatile int32 nw; /* the number waiting */ |
1429 | | volatile int32 ns; /* the number signalling */ |
1430 | | long signalBenCount; /* the number waiting on the underlying sem */ |
1431 | | #else /* not pthreads or Be threads */ |
1432 | | PRCList condQ; /* Condition variable wait Q */ |
1433 | | _MDLock ilock; /* Internal Lock to protect condQ */ |
1434 | | _MDCVar md; |
1435 | | #endif |
1436 | | }; |
1437 | | |
1438 | | /************************************************************************/ |
1439 | | |
1440 | | struct PRMonitor { |
1441 | | const char* name; /* monitor name for debugging */ |
1442 | | #if defined(_PR_PTHREADS) |
1443 | | pthread_mutex_t lock; /* lock is only held when accessing fields |
1444 | | * of the PRMonitor, instead of being held |
1445 | | * while the monitor is entered. The only |
1446 | | * exception is notifyTimes, which is |
1447 | | * protected by the monitor. */ |
1448 | | pthread_t owner; /* the owner of the monitor or invalid */ |
1449 | | pthread_cond_t entryCV; /* for threads waiting to enter the monitor */ |
1450 | | |
1451 | | pthread_cond_t waitCV; /* for threads waiting on the monitor */ |
1452 | | PRInt32 refCount; /* reference count, an atomic variable. |
1453 | | * PR_NewMonitor adds a reference to the |
1454 | | * newly created PRMonitor, and |
1455 | | * PR_DestroyMonitor releases that reference. |
1456 | | * PR_ExitMonitor adds a reference before |
1457 | | * unlocking the internal lock if it needs to |
1458 | | * signal entryCV, and releases the reference |
1459 | | * after signaling entryCV. */ |
1460 | | #else /* defined(_PR_PTHREADS) */ |
1461 | | PRLock lock; /* lock is only held when accessing fields |
1462 | | * of the PRMonitor, instead of being held |
1463 | | * while the monitor is entered. The only |
1464 | | * exception is notifyTimes, which is |
1465 | | * protected by the monitor. */ |
1466 | | PRThread *owner; /* the owner of the monitor or invalid */ |
1467 | | PRCondVar entryCV; /* for threads waiting to enter the monitor */ |
1468 | | |
1469 | | PRCondVar waitCV; /* for threads waiting on the monitor */ |
1470 | | #endif /* defined(_PR_PTHREADS) */ |
1471 | | PRUint32 entryCount; /* # of times re-entered */ |
1472 | | PRIntn notifyTimes; /* number of pending notifies for waitCV. |
1473 | | * The special value -1 means a broadcast |
1474 | | * (PR_NotifyAll). */ |
1475 | | }; |
1476 | | |
1477 | | /************************************************************************/ |
1478 | | |
1479 | | struct PRSemaphore { |
1480 | | #if defined(_PR_BTHREADS) |
1481 | | sem_id sem; |
1482 | | int32 benaphoreCount; |
1483 | | #else |
1484 | | PRCondVar *cvar; /* associated lock and condition variable queue */ |
1485 | | PRUintn count; /* the value of the counting semaphore */ |
1486 | | PRUint32 waiters; /* threads waiting on the semaphore */ |
1487 | | #if defined(_PR_PTHREADS) |
1488 | | #else /* defined(_PR_PTHREADS) */ |
1489 | | _MDSemaphore md; |
1490 | | #endif /* defined(_PR_PTHREADS) */ |
1491 | | #endif /* defined(_PR_BTHREADS) */ |
1492 | | }; |
1493 | | |
1494 | | /*************************************************************************/ |
1495 | | |
1496 | | struct PRSem { |
1497 | | #ifdef _PR_HAVE_POSIX_SEMAPHORES |
1498 | | sem_t *sem; |
1499 | | #elif defined(_PR_HAVE_SYSV_SEMAPHORES) |
1500 | | int semid; |
1501 | | #elif defined(WIN32) |
1502 | | HANDLE sem; |
1503 | | #else |
1504 | | PRInt8 notused; |
1505 | | #endif |
1506 | | }; |
1507 | | |
1508 | | /*************************************************************************/ |
1509 | | |
1510 | | struct PRStackStr { |
1511 | | /* head MUST be at offset 0; assembly language code relies on this */ |
1512 | | #if defined(AIX) |
1513 | | volatile PRStackElem prstk_head; |
1514 | | #else |
1515 | | PRStackElem prstk_head; |
1516 | | #endif |
1517 | | |
1518 | | PRLock *prstk_lock; |
1519 | | char *prstk_name; |
1520 | | }; |
1521 | | |
1522 | | /************************************************************************/ |
1523 | | |
1524 | | /* XXX this needs to be exported (sigh) */ |
1525 | | struct PRThreadStack { |
1526 | | PRCList links; |
1527 | | PRUintn flags; |
1528 | | |
1529 | | char *allocBase; /* base of stack's allocated memory */ |
1530 | | PRUint32 allocSize; /* size of stack's allocated memory */ |
1531 | | char *stackBottom; /* bottom of stack from C's point of view */ |
1532 | | char *stackTop; /* top of stack from C's point of view */ |
1533 | | PRUint32 stackSize; /* size of usable portion of the stack */ |
1534 | | |
1535 | | PRSegment *seg; |
1536 | | PRThread* thr; /* back pointer to thread owning this stack */ |
1537 | | |
1538 | | #if defined(_PR_PTHREADS) |
1539 | | #else /* defined(_PR_PTHREADS) */ |
1540 | | _MDThreadStack md; |
1541 | | #endif /* defined(_PR_PTHREADS) */ |
1542 | | }; |
1543 | | |
1544 | | extern void _PR_DestroyThreadPrivate(PRThread*); |
1545 | | |
1546 | | typedef void (PR_CALLBACK *_PRStartFn)(void *); |
1547 | | |
1548 | | struct PRThread { |
1549 | | PRUint32 state; /* thread's creation state */ |
1550 | | PRThreadPriority priority; /* apparent priority, loosly defined */ |
1551 | | |
1552 | | void *arg; /* argument to the client's entry point */ |
1553 | | _PRStartFn startFunc; /* the root of the client's thread */ |
1554 | | |
1555 | | PRThreadStack *stack; /* info about thread's stack (for GC) */ |
1556 | | void *environment; /* pointer to execution environment */ |
1557 | | |
1558 | | PRThreadDumpProc dump; /* dump thread info out */ |
1559 | | void *dumpArg; /* argument for the dump function */ |
1560 | | |
1561 | | /* |
1562 | | ** Per thread private data |
1563 | | */ |
1564 | | PRUint32 tpdLength; /* thread's current vector length */ |
1565 | | void **privateData; /* private data vector or NULL */ |
1566 | | PRErrorCode errorCode; /* current NSPR error code | zero */ |
1567 | | PRInt32 osErrorCode; /* mapping of errorCode | zero */ |
1568 | | PRIntn errorStringLength; /* textLength from last call to PR_SetErrorText() */ |
1569 | | PRInt32 errorStringSize; /* malloc()'d size of buffer | zero */ |
1570 | | char *errorString; /* current error string | NULL */ |
1571 | | char *name; /* thread's name */ |
1572 | | |
1573 | | #if defined(_PR_PTHREADS) |
1574 | | pthread_t id; /* pthread identifier for the thread */ |
1575 | | PRBool idSet; /* whether 'id' has been set. Protected by |
1576 | | * pt_book.ml. */ |
1577 | | #ifdef _PR_NICE_PRIORITY_SCHEDULING |
1578 | | pid_t tid; /* Linux-specific kernel thread ID */ |
1579 | | #endif |
1580 | | PRBool okToDelete; /* ok to delete the PRThread struct? */ |
1581 | | PRCondVar *waiting; /* where the thread is waiting | NULL */ |
1582 | | void *sp; /* recorded sp for garbage collection */ |
1583 | | PRThread *next, *prev; /* simple linked list of all threads */ |
1584 | | PRUint32 suspend; /* used to store suspend and resume flags */ |
1585 | | #ifdef PT_NO_SIGTIMEDWAIT |
1586 | | pthread_mutex_t suspendResumeMutex; |
1587 | | pthread_cond_t suspendResumeCV; |
1588 | | #endif |
1589 | | PRUint32 interrupt_blocked; /* interrupt blocked */ |
1590 | | struct pollfd *syspoll_list; /* Unix polling list used by PR_Poll */ |
1591 | | PRUint32 syspoll_count; /* number of elements in syspoll_list */ |
1592 | | #if defined(_PR_POLL_WITH_SELECT) |
1593 | | int *selectfd_list; /* Unix fd's that PR_Poll selects on */ |
1594 | | PRUint32 selectfd_count; /* number of elements in selectfd_list */ |
1595 | | #endif |
1596 | | #elif defined(_PR_BTHREADS) |
1597 | | PRUint32 flags; |
1598 | | _MDThread md; |
1599 | | PRBool io_pending; |
1600 | | PRInt32 io_fd; |
1601 | | PRBool io_suspended; |
1602 | | #else /* not pthreads or Be threads */ |
1603 | | _MDLock threadLock; /* Lock to protect thread state variables. |
1604 | | * Protects the following fields: |
1605 | | * state |
1606 | | * priority |
1607 | | * links |
1608 | | * wait |
1609 | | * cpu |
1610 | | */ |
1611 | | PRUint32 queueCount; |
1612 | | PRUint32 waitCount; |
1613 | | |
1614 | | PRCList active; /* on list of all active threads */ |
1615 | | PRCList links; |
1616 | | PRCList waitQLinks; /* when thread is PR_Wait'ing */ |
1617 | | PRCList lockList; /* list of locks currently holding */ |
1618 | | PRIntervalTime sleep; /* sleep time when thread is sleeping */ |
1619 | | struct _wait { |
1620 | | struct PRLock *lock; |
1621 | | struct PRCondVar *cvar; |
1622 | | } wait; |
1623 | | |
1624 | | PRUint32 id; |
1625 | | PRUint32 flags; |
1626 | | PRUint32 no_sched; /* Don't schedule the thread to run. |
1627 | | * This flag has relevance only when |
1628 | | * multiple NSPR CPUs are created. |
1629 | | * When a thread is de-scheduled, there |
1630 | | * is a narrow window of time in which |
1631 | | * the thread is put on the run queue |
1632 | | * but the scheduler is actually using |
1633 | | * the stack of this thread. It is safe |
1634 | | * to run this thread on a different CPU |
1635 | | * only when its stack is not in use on |
1636 | | * any other CPU. The no_sched flag is |
1637 | | * set during this interval to prevent |
1638 | | * the thread from being scheduled on a |
1639 | | * different CPU. |
1640 | | */ |
1641 | | |
1642 | | /* thread termination condition variable for join */ |
1643 | | PRCondVar *term; |
1644 | | |
1645 | | _PRCPU *cpu; /* cpu to which this thread is bound */ |
1646 | | PRUint32 threadAllocatedOnStack;/* boolean */ |
1647 | | |
1648 | | /* When an async IO is in progress and a second async IO cannot be |
1649 | | * initiated, the io_pending flag is set to true. Some platforms will |
1650 | | * not use the io_pending flag. If the io_pending flag is true, then |
1651 | | * io_fd is the OS-file descriptor on which IO is pending. |
1652 | | */ |
1653 | | PRBool io_pending; |
1654 | | PRInt32 io_fd; |
1655 | | |
1656 | | /* If a timeout occurs or if an outstanding IO is interrupted and the |
1657 | | * OS doesn't support a real cancellation (NT or MAC), then the |
1658 | | * io_suspended flag will be set to true. The thread will be resumed |
1659 | | * but may run into trouble issuing additional IOs until the io_pending |
1660 | | * flag can be cleared |
1661 | | */ |
1662 | | PRBool io_suspended; |
1663 | | |
1664 | | _MDThread md; |
1665 | | #endif |
1666 | | }; |
1667 | | |
1668 | | struct PRProcessAttr { |
1669 | | PRFileDesc *stdinFd; |
1670 | | PRFileDesc *stdoutFd; |
1671 | | PRFileDesc *stderrFd; |
1672 | | char *currentDirectory; |
1673 | | char *fdInheritBuffer; |
1674 | | PRSize fdInheritBufferSize; |
1675 | | PRSize fdInheritBufferUsed; |
1676 | | }; |
1677 | | |
1678 | | struct PRProcess { |
1679 | | _MDProcess md; |
1680 | | }; |
1681 | | |
1682 | | struct PRFileMap { |
1683 | | PRFileDesc *fd; |
1684 | | PRFileMapProtect prot; |
1685 | | _MDFileMap md; |
1686 | | }; |
1687 | | |
1688 | | /************************************************************************/ |
1689 | | |
1690 | | /* |
1691 | | ** File descriptors of the NSPR layer can be in one of the |
1692 | | ** following states (stored in the 'state' field of struct |
1693 | | ** PRFilePrivate): |
1694 | | ** - _PR_FILEDESC_OPEN: The OS fd is open. |
1695 | | ** - _PR_FILEDESC_CLOSED: The OS fd is closed. The PRFileDesc |
1696 | | ** is still open but is unusable. The only operation allowed |
1697 | | ** on the PRFileDesc is PR_Close(). |
1698 | | ** - _PR_FILEDESC_FREED: The OS fd is closed and the PRFileDesc |
1699 | | ** structure is freed. |
1700 | | */ |
1701 | | |
1702 | 0 | #define _PR_FILEDESC_OPEN 0xaaaaaaaa /* 1010101... */ |
1703 | 0 | #define _PR_FILEDESC_CLOSED 0x55555555 /* 0101010... */ |
1704 | 0 | #define _PR_FILEDESC_FREED 0x11111111 |
1705 | | |
1706 | | /* |
1707 | | ** A boolean type with an additional "unknown" state |
1708 | | */ |
1709 | | |
1710 | | typedef enum { |
1711 | | _PR_TRI_TRUE = 1, |
1712 | | _PR_TRI_FALSE = 0, |
1713 | | _PR_TRI_UNKNOWN = -1 |
1714 | | } _PRTriStateBool; |
1715 | | |
1716 | | struct PRFilePrivate { |
1717 | | PRInt32 state; |
1718 | | PRBool nonblocking; |
1719 | | _PRTriStateBool inheritable; |
1720 | | PRFileDesc *next; |
1721 | | PRIntn lockCount; /* 0: not locked |
1722 | | * -1: a native lockfile call is in progress |
1723 | | * > 0: # times the file is locked */ |
1724 | | #ifdef _PR_HAVE_PEEK_BUFFER |
1725 | | char *peekBuffer; |
1726 | | PRInt32 peekBufSize; |
1727 | | PRInt32 peekBytes; |
1728 | | #endif |
1729 | | #if !defined(_PR_HAVE_O_APPEND) |
1730 | | PRBool appendMode; /* Some platforms don't have O_APPEND or its |
1731 | | * equivalent, so they have to seek to end of |
1732 | | * file on write if the file was opened in |
1733 | | * append mode. See Bugzilla 4090, 276330. */ |
1734 | | #endif |
1735 | | _MDFileDesc md; |
1736 | | #ifdef _PR_NEED_SECRET_AF |
1737 | | PRUint16 af; /* If the platform's implementation of accept() |
1738 | | * requires knowing the address family of the |
1739 | | * socket, we save the address family here. */ |
1740 | | #endif |
1741 | | |
1742 | | #if defined(_WIN64) |
1743 | | /* This is necessary for TCP Fast Open. TCP Fast Open in windows must |
1744 | | * use ConnectEx function which uses OVERLAPPED. TCPSendTo will call |
1745 | | * ConnectEx to send fast open data. If ConnectEx returns |
1746 | | * ERROR_IO_PENDING we need to save OVERLAPPED structure and we will |
1747 | | * use it in ConnectContinue to get the final result of ConnectEx. |
1748 | | */ |
1749 | | PRBool alreadyConnected; |
1750 | | PRBool overlappedActive; |
1751 | | OVERLAPPED ol; |
1752 | | #endif |
1753 | | }; |
1754 | | |
1755 | | #ifdef _WIN64 |
1756 | | #define PR_PRIdOSFD "lld" /* for printing PROsfd */ |
1757 | | #define PR_PRIxOSFD "llx" |
1758 | | #define PR_SCNdOSFD "lld" /* for scanning PROsfd */ |
1759 | | #define PR_SCNxOSFD "llx" |
1760 | | #else |
1761 | | #define PR_PRIdOSFD "ld" /* for printing PROsfd */ |
1762 | 0 | #define PR_PRIxOSFD "lx" |
1763 | | #define PR_SCNdOSFD "ld" /* for scanning PROsfd */ |
1764 | 0 | #define PR_SCNxOSFD "lx" |
1765 | | #endif |
1766 | | |
1767 | | struct PRDir { |
1768 | | PRDirEntry d; |
1769 | | _MDDir md; |
1770 | | }; |
1771 | | |
1772 | | #ifdef MOZ_UNICODE |
1773 | | struct PRDirUTF16 { |
1774 | | PRDirEntry d; |
1775 | | _MDDirUTF16 md; |
1776 | | }; |
1777 | | #endif /* MOZ_UNICODE */ |
1778 | | |
1779 | | extern void _PR_InitLocks(void); |
1780 | | extern void _PR_InitSegs(void); |
1781 | | extern void _PR_InitStacks(void); |
1782 | | extern void _PR_InitTPD(void); |
1783 | | extern void _PR_InitMem(void); |
1784 | | extern void _PR_InitEnv(void); |
1785 | | extern void _PR_InitCMon(void); |
1786 | | extern void _PR_InitIO(void); |
1787 | | extern void _PR_InitLog(void); |
1788 | | extern void _PR_InitNet(void); |
1789 | | extern void _PR_InitClock(void); |
1790 | | extern void _PR_InitLinker(void); |
1791 | | extern void _PR_InitAtomic(void); |
1792 | | extern void _PR_InitCPUs(void); |
1793 | | extern void _PR_InitDtoa(void); |
1794 | | extern void _PR_InitTime(void); |
1795 | | extern void _PR_InitMW(void); |
1796 | | extern void _PR_InitRWLocks(void); |
1797 | | extern void _PR_CleanupThread(PRThread *thread); |
1798 | | extern void _PR_CleanupCallOnce(void); |
1799 | | extern void _PR_CleanupMW(void); |
1800 | | extern void _PR_CleanupTime(void); |
1801 | | extern void _PR_CleanupDtoa(void); |
1802 | | extern void _PR_ShutdownLinker(void); |
1803 | | extern void _PR_CleanupEnv(void); |
1804 | | extern void _PR_CleanupIO(void); |
1805 | | extern void _PR_CleanupCMon(void); |
1806 | | extern void _PR_CleanupNet(void); |
1807 | | extern void _PR_CleanupLayerCache(void); |
1808 | | extern void _PR_CleanupStacks(void); |
1809 | | #ifdef WINNT |
1810 | | extern void _PR_CleanupCPUs(void); |
1811 | | #endif |
1812 | | extern void _PR_CleanupThreads(void); |
1813 | | extern void _PR_CleanupTPD(void); |
1814 | | extern void _PR_Cleanup(void); |
1815 | | extern void _PR_LogCleanup(void); |
1816 | | extern void _PR_InitLayerCache(void); |
1817 | | |
1818 | | extern PRBool _pr_initialized; |
1819 | | extern void _PR_ImplicitInitialization(void); |
1820 | | extern PRBool _PR_Obsolete(const char *obsolete, const char *preferred); |
1821 | | |
1822 | | /************************************************************************/ |
1823 | | |
1824 | | struct PRSegment { |
1825 | | void *vaddr; |
1826 | | PRUint32 size; |
1827 | | PRUintn flags; |
1828 | | #if defined(_PR_PTHREADS) |
1829 | | #else /* defined(_PR_PTHREADS) */ |
1830 | | _MDSegment md; |
1831 | | #endif /* defined(_PR_PTHREADS) */ |
1832 | | }; |
1833 | | |
1834 | | /* PRSegment.flags */ |
1835 | | #define _PR_SEG_VM 0x1 |
1836 | | |
1837 | | /************************************************************************/ |
1838 | | |
1839 | | extern PRInt32 _pr_pageSize; |
1840 | | extern PRInt32 _pr_pageShift; |
1841 | | |
1842 | | extern PRLogModuleInfo *_pr_clock_lm; |
1843 | | extern PRLogModuleInfo *_pr_cmon_lm; |
1844 | | extern PRLogModuleInfo *_pr_io_lm; |
1845 | | extern PRLogModuleInfo *_pr_cvar_lm; |
1846 | | extern PRLogModuleInfo *_pr_mon_lm; |
1847 | | extern PRLogModuleInfo *_pr_linker_lm; |
1848 | | extern PRLogModuleInfo *_pr_sched_lm; |
1849 | | extern PRLogModuleInfo *_pr_thread_lm; |
1850 | | extern PRLogModuleInfo *_pr_gc_lm; |
1851 | | |
1852 | | extern PRFileDesc *_pr_stdin; |
1853 | | extern PRFileDesc *_pr_stdout; |
1854 | | extern PRFileDesc *_pr_stderr; |
1855 | | |
1856 | | /* Zone allocator */ |
1857 | | /* |
1858 | | ** The zone allocator code has hardcoded pthread types and |
1859 | | ** functions, so it can only be used in the pthreads version. |
1860 | | ** This can be fixed by replacing the hardcoded pthread types |
1861 | | ** and functions with macros that expand to the native thread |
1862 | | ** types and functions on each platform. |
1863 | | */ |
1864 | | #if defined(_PR_PTHREADS) |
1865 | | #define _PR_ZONE_ALLOCATOR |
1866 | | #endif |
1867 | | |
1868 | | #ifdef _PR_ZONE_ALLOCATOR |
1869 | | extern void _PR_InitZones(void); |
1870 | | extern void _PR_DestroyZones(void); |
1871 | | #endif |
1872 | | |
1873 | | /* Overriding malloc, free, etc. */ |
1874 | | #if !defined(_PR_NO_PREEMPT) && defined(XP_UNIX) \ |
1875 | | && !defined(_PR_PTHREADS) && !defined(_PR_GLOBAL_THREADS_ONLY) \ |
1876 | | && !defined(PURIFY) \ |
1877 | | && !defined(DARWIN) \ |
1878 | | && !defined(QNX) |
1879 | | #define _PR_OVERRIDE_MALLOC |
1880 | | #endif |
1881 | | |
1882 | | /************************************************************************* |
1883 | | * External machine-dependent code provided by each OS. * * |
1884 | | *************************************************************************/ |
1885 | | |
1886 | | /* Initialization related */ |
1887 | | extern void _PR_MD_EARLY_INIT(void); |
1888 | 0 | #define _PR_MD_EARLY_INIT _MD_EARLY_INIT |
1889 | | |
1890 | | extern void _PR_MD_INTERVAL_INIT(void); |
1891 | | #define _PR_MD_INTERVAL_INIT _MD_INTERVAL_INIT |
1892 | | |
1893 | | NSPR_API(void) _PR_MD_FINAL_INIT(void); |
1894 | 0 | #define _PR_MD_FINAL_INIT _MD_FINAL_INIT |
1895 | | |
1896 | | extern void _PR_MD_EARLY_CLEANUP(void); |
1897 | 0 | #define _PR_MD_EARLY_CLEANUP _MD_EARLY_CLEANUP |
1898 | | |
1899 | | /* Process control */ |
1900 | | |
1901 | | extern PRProcess * _PR_MD_CREATE_PROCESS( |
1902 | | const char *path, |
1903 | | char *const *argv, |
1904 | | char *const *envp, |
1905 | | const PRProcessAttr *attr); |
1906 | 0 | #define _PR_MD_CREATE_PROCESS _MD_CREATE_PROCESS |
1907 | | |
1908 | | extern PRStatus _PR_MD_DETACH_PROCESS(PRProcess *process); |
1909 | 0 | #define _PR_MD_DETACH_PROCESS _MD_DETACH_PROCESS |
1910 | | |
1911 | | extern PRStatus _PR_MD_WAIT_PROCESS(PRProcess *process, PRInt32 *exitCode); |
1912 | 0 | #define _PR_MD_WAIT_PROCESS _MD_WAIT_PROCESS |
1913 | | |
1914 | | extern PRStatus _PR_MD_KILL_PROCESS(PRProcess *process); |
1915 | 0 | #define _PR_MD_KILL_PROCESS _MD_KILL_PROCESS |
1916 | | |
1917 | | /* Current Time */ |
1918 | | NSPR_API(PRTime) _PR_MD_NOW(void); |
1919 | | #define _PR_MD_NOW _MD_NOW |
1920 | | |
1921 | | /* Environment related */ |
1922 | | extern char* _PR_MD_GET_ENV(const char *name); |
1923 | 0 | #define _PR_MD_GET_ENV _MD_GET_ENV |
1924 | | |
1925 | | extern PRIntn _PR_MD_PUT_ENV(const char *name); |
1926 | 0 | #define _PR_MD_PUT_ENV _MD_PUT_ENV |
1927 | | |
1928 | | /* Atomic operations */ |
1929 | | |
1930 | | extern void _PR_MD_INIT_ATOMIC(void); |
1931 | | #define _PR_MD_INIT_ATOMIC _MD_INIT_ATOMIC |
1932 | | |
1933 | | extern PRInt32 _PR_MD_ATOMIC_INCREMENT(PRInt32 *); |
1934 | 0 | #define _PR_MD_ATOMIC_INCREMENT _MD_ATOMIC_INCREMENT |
1935 | | |
1936 | | extern PRInt32 _PR_MD_ATOMIC_ADD(PRInt32 *, PRInt32); |
1937 | 0 | #define _PR_MD_ATOMIC_ADD _MD_ATOMIC_ADD |
1938 | | |
1939 | | extern PRInt32 _PR_MD_ATOMIC_DECREMENT(PRInt32 *); |
1940 | 0 | #define _PR_MD_ATOMIC_DECREMENT _MD_ATOMIC_DECREMENT |
1941 | | |
1942 | | extern PRInt32 _PR_MD_ATOMIC_SET(PRInt32 *, PRInt32); |
1943 | 0 | #define _PR_MD_ATOMIC_SET _MD_ATOMIC_SET |
1944 | | |
1945 | | /* Garbage collection */ |
1946 | | |
1947 | | /* |
1948 | | ** Save the registers that the GC would find interesting into the thread |
1949 | | ** "t". isCurrent will be non-zero if the thread state that is being |
1950 | | ** saved is the currently executing thread. Return the address of the |
1951 | | ** first register to be scanned as well as the number of registers to |
1952 | | ** scan in "np". |
1953 | | ** |
1954 | | ** If "isCurrent" is non-zero then it is allowed for the thread context |
1955 | | ** area to be used as scratch storage to hold just the registers |
1956 | | ** necessary for scanning. |
1957 | | */ |
1958 | | extern PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np); |
1959 | | |
1960 | | /* Time intervals */ |
1961 | | |
1962 | | extern PRIntervalTime _PR_MD_GET_INTERVAL(void); |
1963 | 0 | #define _PR_MD_GET_INTERVAL _MD_GET_INTERVAL |
1964 | | |
1965 | | extern PRIntervalTime _PR_MD_INTERVAL_PER_SEC(void); |
1966 | 0 | #define _PR_MD_INTERVAL_PER_SEC _MD_INTERVAL_PER_SEC |
1967 | | |
1968 | | /* Affinity masks */ |
1969 | | |
1970 | | extern PRInt32 _PR_MD_SETTHREADAFFINITYMASK(PRThread *thread, PRUint32 mask ); |
1971 | | #define _PR_MD_SETTHREADAFFINITYMASK _MD_SETTHREADAFFINITYMASK |
1972 | | |
1973 | | extern PRInt32 _PR_MD_GETTHREADAFFINITYMASK(PRThread *thread, PRUint32 *mask); |
1974 | | #define _PR_MD_GETTHREADAFFINITYMASK _MD_GETTHREADAFFINITYMASK |
1975 | | |
1976 | | /* File locking */ |
1977 | | |
1978 | | extern PRStatus _PR_MD_LOCKFILE(PROsfd osfd); |
1979 | 0 | #define _PR_MD_LOCKFILE _MD_LOCKFILE |
1980 | | |
1981 | | extern PRStatus _PR_MD_TLOCKFILE(PROsfd osfd); |
1982 | 0 | #define _PR_MD_TLOCKFILE _MD_TLOCKFILE |
1983 | | |
1984 | | extern PRStatus _PR_MD_UNLOCKFILE(PROsfd osfd); |
1985 | 0 | #define _PR_MD_UNLOCKFILE _MD_UNLOCKFILE |
1986 | | |
1987 | | /* Memory-mapped files */ |
1988 | | |
1989 | | extern PRStatus _PR_MD_CREATE_FILE_MAP(PRFileMap *fmap, PRInt64 size); |
1990 | 0 | #define _PR_MD_CREATE_FILE_MAP _MD_CREATE_FILE_MAP |
1991 | | |
1992 | | extern PRInt32 _PR_MD_GET_MEM_MAP_ALIGNMENT(void); |
1993 | 0 | #define _PR_MD_GET_MEM_MAP_ALIGNMENT _MD_GET_MEM_MAP_ALIGNMENT |
1994 | | |
1995 | | extern void * _PR_MD_MEM_MAP( |
1996 | | PRFileMap *fmap, |
1997 | | PROffset64 offset, |
1998 | | PRUint32 len); |
1999 | 0 | #define _PR_MD_MEM_MAP _MD_MEM_MAP |
2000 | | |
2001 | | extern PRStatus _PR_MD_MEM_UNMAP(void *addr, PRUint32 size); |
2002 | 0 | #define _PR_MD_MEM_UNMAP _MD_MEM_UNMAP |
2003 | | |
2004 | | extern PRStatus _PR_MD_CLOSE_FILE_MAP(PRFileMap *fmap); |
2005 | 0 | #define _PR_MD_CLOSE_FILE_MAP _MD_CLOSE_FILE_MAP |
2006 | | |
2007 | | extern PRStatus _PR_MD_SYNC_MEM_MAP( |
2008 | | PRFileDesc *fd, |
2009 | | void *addr, |
2010 | | PRUint32 len); |
2011 | 0 | #define _PR_MD_SYNC_MEM_MAP _MD_SYNC_MEM_MAP |
2012 | | |
2013 | | /* Named Shared Memory */ |
2014 | | |
2015 | | /* |
2016 | | ** Declare PRSharedMemory. |
2017 | | */ |
2018 | | struct PRSharedMemory |
2019 | | { |
2020 | | char *ipcname; /* after conversion to native */ |
2021 | | PRSize size; /* from open */ |
2022 | | PRIntn mode; /* from open */ |
2023 | | PRIntn flags; /* from open */ |
2024 | | #if defined(PR_HAVE_POSIX_NAMED_SHARED_MEMORY) |
2025 | | int id; |
2026 | | #elif defined(PR_HAVE_SYSV_NAMED_SHARED_MEMORY) |
2027 | | int id; |
2028 | | #elif defined(PR_HAVE_WIN32_NAMED_SHARED_MEMORY) |
2029 | | HANDLE handle; |
2030 | | #else |
2031 | | PRUint32 nothing; /* placeholder, nothing behind here */ |
2032 | | #endif |
2033 | | PRUint32 ident; /* guard word at end of struct */ |
2034 | | #define _PR_SHM_IDENT 0xdeadbad |
2035 | | }; |
2036 | | |
2037 | | extern PRSharedMemory * _MD_OpenSharedMemory( |
2038 | | const char *name, |
2039 | | PRSize size, |
2040 | | PRIntn flags, |
2041 | | PRIntn mode |
2042 | | ); |
2043 | | #define _PR_MD_OPEN_SHARED_MEMORY _MD_OpenSharedMemory |
2044 | | |
2045 | | extern void * _MD_AttachSharedMemory( PRSharedMemory *shm, PRIntn flags ); |
2046 | | #define _PR_MD_ATTACH_SHARED_MEMORY _MD_AttachSharedMemory |
2047 | | |
2048 | | extern PRStatus _MD_DetachSharedMemory( PRSharedMemory *shm, void *addr ); |
2049 | | #define _PR_MD_DETACH_SHARED_MEMORY _MD_DetachSharedMemory |
2050 | | |
2051 | | extern PRStatus _MD_CloseSharedMemory( PRSharedMemory *shm ); |
2052 | | #define _PR_MD_CLOSE_SHARED_MEMORY _MD_CloseSharedMemory |
2053 | | |
2054 | | extern PRStatus _MD_DeleteSharedMemory( const char *name ); |
2055 | | #define _PR_MD_DELETE_SHARED_MEMORY _MD_DeleteSharedMemory |
2056 | | |
2057 | | extern PRFileMap* _md_OpenAnonFileMap( |
2058 | | const char *dirName, |
2059 | | PRSize size, |
2060 | | PRFileMapProtect prot |
2061 | | ); |
2062 | | #define _PR_MD_OPEN_ANON_FILE_MAP _md_OpenAnonFileMap |
2063 | | |
2064 | | extern PRStatus _md_ExportFileMapAsString( |
2065 | | PRFileMap *fm, |
2066 | | PRSize bufSize, |
2067 | | char *buf |
2068 | | ); |
2069 | | #define _PR_MD_EXPORT_FILE_MAP_AS_STRING _md_ExportFileMapAsString |
2070 | | |
2071 | | extern PRFileMap * _md_ImportFileMapFromString( |
2072 | | const char *fmstring |
2073 | | ); |
2074 | | #define _PR_MD_IMPORT_FILE_MAP_FROM_STRING _md_ImportFileMapFromString |
2075 | | |
2076 | | |
2077 | | |
2078 | | /* Interprocess communications (IPC) */ |
2079 | | |
2080 | | /* |
2081 | | * The maximum length of an NSPR IPC name, including the |
2082 | | * terminating null byte. |
2083 | | */ |
2084 | | #define PR_IPC_NAME_SIZE 1024 |
2085 | | |
2086 | | /* |
2087 | | * Types of NSPR IPC objects |
2088 | | */ |
2089 | | typedef enum { |
2090 | | _PRIPCSem, /* semaphores */ |
2091 | | _PRIPCShm /* shared memory segments */ |
2092 | | } _PRIPCType; |
2093 | | |
2094 | | /* |
2095 | | * Make a native IPC name from an NSPR IPC name. |
2096 | | */ |
2097 | | extern PRStatus _PR_MakeNativeIPCName( |
2098 | | const char *name, /* NSPR IPC name */ |
2099 | | char *result, /* result buffer */ |
2100 | | PRIntn size, /* size of result buffer */ |
2101 | | _PRIPCType type /* type of IPC object */ |
2102 | | ); |
2103 | | |
2104 | | /* Socket call error code */ |
2105 | | |
2106 | | NSPR_API(PRInt32) _PR_MD_GET_SOCKET_ERROR(void); |
2107 | | #define _PR_MD_GET_SOCKET_ERROR _MD_GET_SOCKET_ERROR |
2108 | | |
2109 | | /* Get name of current host */ |
2110 | | extern PRStatus _PR_MD_GETHOSTNAME(char *name, PRUint32 namelen); |
2111 | 0 | #define _PR_MD_GETHOSTNAME _MD_GETHOSTNAME |
2112 | | |
2113 | | extern PRStatus _PR_MD_GETSYSINFO(PRSysInfo cmd, char *name, PRUint32 namelen); |
2114 | 0 | #define _PR_MD_GETSYSINFO _MD_GETSYSINFO |
2115 | | |
2116 | | /* File descriptor inheritance */ |
2117 | | |
2118 | | /* |
2119 | | * If fd->secret->inheritable is _PR_TRI_UNKNOWN and we need to |
2120 | | * know the inheritable attribute of the fd, call this function |
2121 | | * to find that out. This typically requires a system call. |
2122 | | */ |
2123 | | extern void _PR_MD_QUERY_FD_INHERITABLE(PRFileDesc *fd); |
2124 | 0 | #define _PR_MD_QUERY_FD_INHERITABLE _MD_QUERY_FD_INHERITABLE |
2125 | | |
2126 | | /* --- PR_GetRandomNoise() related things --- */ |
2127 | | |
2128 | | extern PRSize _PR_MD_GetRandomNoise( void *buf, PRSize size ); |
2129 | | #define _PR_MD_GET_RANDOM_NOISE(buf,size) _PR_MD_GetRandomNoise((buf),(size)) |
2130 | | extern PRSize _pr_CopyLowBits( void *dest, PRSize dstlen, void *src, PRSize srclen ); |
2131 | | |
2132 | | /* end PR_GetRandomNoise() related */ |
2133 | | |
2134 | | #if defined(_WIN64) && defined(WIN95) |
2135 | | typedef struct _PRFileDescList { |
2136 | | PRFileDesc *fd; |
2137 | | struct _PRFileDescList *next; |
2138 | | } PRFileDescList; |
2139 | | |
2140 | | extern PRLock *_fd_waiting_for_overlapped_done_lock; |
2141 | | extern PRFileDescList *_fd_waiting_for_overlapped_done; |
2142 | | extern void CheckOverlappedPendingSocketsAreDone(); |
2143 | | #endif |
2144 | | |
2145 | | |
2146 | | PR_END_EXTERN_C |
2147 | | |
2148 | | #endif /* primpl_h___ */ |