andre@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ andre@0: /* This Source Code Form is subject to the terms of the Mozilla Public andre@0: * License, v. 2.0. If a copy of the MPL was not distributed with this andre@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ andre@0: andre@0: #ifndef primpl_h___ andre@0: #define primpl_h___ andre@0: andre@0: /* andre@0: * HP-UX 10.10's pthread.h (DCE threads) includes dce/cma.h, which andre@0: * has: andre@0: * #define sigaction _sigaction_sys andre@0: * This macro causes chaos if signal.h gets included before pthread.h. andre@0: * To be safe, we include pthread.h first. andre@0: */ andre@0: andre@0: #if defined(_PR_PTHREADS) andre@0: #include andre@0: #endif andre@0: andre@0: #if defined(_PR_BTHREADS) andre@0: #include andre@0: #endif andre@0: andre@0: #ifdef WIN32 andre@0: /* andre@0: * Allow use of functions and symbols first defined in Win2k. andre@0: */ andre@0: #if !defined(WINVER) || (WINVER < 0x0500) andre@0: #undef WINVER andre@0: #define WINVER 0x0500 andre@0: #endif andre@0: #if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) andre@0: #undef _WIN32_WINNT andre@0: #define _WIN32_WINNT 0x0500 andre@0: #endif andre@0: #endif /* WIN32 */ andre@0: andre@0: #include "nspr.h" andre@0: #include "prpriv.h" andre@0: andre@0: typedef struct PRSegment PRSegment; andre@0: andre@0: #include "md/prosdep.h" andre@0: #include "obsolete/probslet.h" andre@0: andre@0: #ifdef _PR_HAVE_POSIX_SEMAPHORES andre@0: #include andre@0: #elif defined(_PR_HAVE_SYSV_SEMAPHORES) andre@0: #include andre@0: #endif andre@0: andre@0: #ifdef HAVE_SYSCALL andre@0: #include andre@0: #endif andre@0: andre@0: /************************************************************************* andre@0: ***** A Word about Model Dependent Function Naming Convention *********** andre@0: *************************************************************************/ andre@0: andre@0: /* andre@0: NSPR 2.0 must implement its function across a range of platforms andre@0: including: MAC, Windows/16, Windows/95, Windows/NT, and several andre@0: variants of Unix. Each implementation shares common code as well andre@0: as having platform dependent portions. This standard describes how andre@0: the model dependent portions are to be implemented. andre@0: andre@0: In header file pr/include/primpl.h, each publicly declared andre@0: platform dependent function is declared as: andre@0: andre@0: NSPR_API void _PR_MD_FUNCTION( long arg1, long arg2 ); andre@0: #define _PR_MD_FUNCTION _MD_FUNCTION andre@0: andre@0: In header file pr/include/md//_.h, andre@0: each #define'd macro is redefined as one of: andre@0: andre@0: #define _MD_FUNCTION andre@0: #define _MD_FUNCTION andre@0: #define _MD_FUNCTION andre@0: #define _MD_FUNCTION <_MD_Function> andre@0: andre@0: Where: andre@0: andre@0: is no definition at all. In this case, the function is not implemented andre@0: and is never called for this platform. andre@0: For example: andre@0: #define _MD_INIT_CPUS() andre@0: andre@0: is a C language macro expansion. andre@0: For example: andre@0: #define _MD_CLEAN_THREAD(_thread) \ andre@0: PR_BEGIN_MACRO \ andre@0: PR_DestroyCondVar(_thread->md.asyncIOCVar); \ andre@0: PR_DestroyLock(_thread->md.asyncIOLock); \ andre@0: PR_END_MACRO andre@0: andre@0: is some function implemented by the host operating system. andre@0: For example: andre@0: #define _MD_EXIT exit andre@0: andre@0: <_MD_function> is the name of a function implemented for this platform in andre@0: pr/src/md//.c file. andre@0: For example: andre@0: #define _MD_GETFILEINFO _MD_GetFileInfo andre@0: andre@0: In .c, the implementation is: andre@0: PR_IMPLEMENT(PRInt32) _MD_GetFileInfo(const char *fn, PRFileInfo *info); andre@0: */ andre@0: andre@0: PR_BEGIN_EXTERN_C andre@0: andre@0: typedef struct _MDLock _MDLock; andre@0: typedef struct _MDCVar _MDCVar; andre@0: typedef struct _MDSegment _MDSegment; andre@0: typedef struct _MDThread _MDThread; andre@0: typedef struct _MDThreadStack _MDThreadStack; andre@0: typedef struct _MDSemaphore _MDSemaphore; andre@0: typedef struct _MDDir _MDDir; andre@0: #ifdef MOZ_UNICODE andre@0: typedef struct _MDDirUTF16 _MDDirUTF16; andre@0: #endif /* MOZ_UNICODE */ andre@0: typedef struct _MDFileDesc _MDFileDesc; andre@0: typedef struct _MDProcess _MDProcess; andre@0: typedef struct _MDFileMap _MDFileMap; andre@0: andre@0: #if defined(_PR_PTHREADS) andre@0: andre@0: /* andre@0: ** The following definitions are unique to implementing NSPR using pthreads. andre@0: ** Since pthreads defines most of the thread and thread synchronization andre@0: ** stuff, this is a pretty small set. andre@0: */ andre@0: andre@0: #define PT_CV_NOTIFIED_LENGTH 6 andre@0: typedef struct _PT_Notified _PT_Notified; andre@0: struct _PT_Notified andre@0: { andre@0: PRIntn length; /* # of used entries in this structure */ andre@0: struct andre@0: { andre@0: PRCondVar *cv; /* the condition variable notified */ andre@0: PRIntn times; /* and the number of times notified */ andre@0: } cv[PT_CV_NOTIFIED_LENGTH]; andre@0: _PT_Notified *link; /* link to another of these | NULL */ andre@0: }; andre@0: andre@0: /* andre@0: * bits defined for pthreads 'state' field andre@0: */ andre@0: #define PT_THREAD_DETACHED 0x01 /* thread can't be joined */ andre@0: #define PT_THREAD_GLOBAL 0x02 /* a global thread (unlikely) */ andre@0: #define PT_THREAD_SYSTEM 0x04 /* system (not user) thread */ andre@0: #define PT_THREAD_PRIMORD 0x08 /* this is the primordial thread */ andre@0: #define PT_THREAD_ABORTED 0x10 /* thread has been interrupted */ andre@0: #define PT_THREAD_GCABLE 0x20 /* thread is garbage collectible */ andre@0: #define PT_THREAD_SUSPENDED 0x40 /* thread has been suspended */ andre@0: #define PT_THREAD_FOREIGN 0x80 /* thread is not one of ours */ andre@0: #define PT_THREAD_BOUND 0x100 /* a bound-global thread */ andre@0: andre@0: #define _PT_THREAD_INTERRUPTED(thr) \ andre@0: (!(thr->interrupt_blocked) && (thr->state & PT_THREAD_ABORTED)) andre@0: #define _PT_THREAD_BLOCK_INTERRUPT(thr) \ andre@0: (thr->interrupt_blocked = 1) andre@0: #define _PT_THREAD_UNBLOCK_INTERRUPT(thr) \ andre@0: (thr->interrupt_blocked = 0) andre@0: andre@0: #define _PT_IS_GCABLE_THREAD(thr) ((thr)->state & PT_THREAD_GCABLE) andre@0: andre@0: /* andre@0: ** Possible values for thread's suspend field andre@0: ** Note that the first two can be the same as they are really mutually exclusive, andre@0: ** i.e. both cannot be happening at the same time. We have two symbolic names andre@0: ** just as a mnemonic. andre@0: **/ andre@0: #define PT_THREAD_RESUMED 0x80 /* thread has been resumed */ andre@0: #define PT_THREAD_SETGCABLE 0x100 /* set the GCAble flag */ andre@0: andre@0: #if defined(DEBUG) andre@0: andre@0: typedef struct PTDebug andre@0: { andre@0: PRTime timeStarted; andre@0: PRUintn locks_created, locks_destroyed; andre@0: PRUintn locks_acquired, locks_released; andre@0: PRUintn cvars_created, cvars_destroyed; andre@0: PRUintn cvars_notified, delayed_cv_deletes; andre@0: } PTDebug; andre@0: andre@0: #endif /* defined(DEBUG) */ andre@0: andre@0: NSPR_API(void) PT_FPrintStats(PRFileDesc *fd, const char *msg); andre@0: andre@0: /* andre@0: * On Linux and its derivatives POSIX priority scheduling works only for andre@0: * real-time threads. On those platforms we set thread's nice values andre@0: * instead which requires us to track kernel thread IDs for each POSIX andre@0: * thread we create. andre@0: */ andre@0: #if defined(LINUX) && defined(HAVE_SETPRIORITY) && \ andre@0: ((defined(HAVE_SYSCALL) && defined(SYS_gettid)) || defined(HAVE_GETTID)) andre@0: #define _PR_NICE_PRIORITY_SCHEDULING andre@0: #endif andre@0: andre@0: #else /* defined(_PR_PTHREADS) */ andre@0: andre@0: NSPR_API(void) PT_FPrintStats(PRFileDesc *fd, const char *msg); andre@0: andre@0: /* andre@0: ** This section is contains those parts needed to implement NSPR on andre@0: ** platforms in general. One would assume that the pthreads implementation andre@0: ** included lots of the same types, at least conceptually. andre@0: */ andre@0: andre@0: /* andre@0: * Local threads only. No multiple CPU support and hence all the andre@0: * following routines are no-op. andre@0: */ andre@0: #ifdef _PR_LOCAL_THREADS_ONLY andre@0: andre@0: #define _PR_MD_SUSPEND_THREAD(thread) andre@0: #define _PR_MD_RESUME_THREAD(thread) andre@0: #define _PR_MD_SUSPEND_CPU(cpu) andre@0: #define _PR_MD_RESUME_CPU(cpu) andre@0: #define _PR_MD_BEGIN_SUSPEND_ALL() andre@0: #define _PR_MD_END_SUSPEND_ALL() andre@0: #define _PR_MD_BEGIN_RESUME_ALL() andre@0: #define _PR_MD_END_RESUME_ALL() andre@0: #define _PR_MD_INIT_ATTACHED_THREAD(thread) PR_FAILURE andre@0: andre@0: #endif andre@0: andre@0: typedef struct _PRCPUQueue _PRCPUQueue; andre@0: typedef struct _PRCPU _PRCPU; andre@0: typedef struct _MDCPU _MDCPU; andre@0: andre@0: struct _PRCPUQueue { andre@0: _MDLock runQLock; /* lock for the run + wait queues */ andre@0: _MDLock sleepQLock; /* lock for the run + wait queues */ andre@0: _MDLock miscQLock; /* lock for the run + wait queues */ andre@0: andre@0: PRCList runQ[PR_PRIORITY_LAST + 1]; /* run queue for this CPU */ andre@0: PRUint32 runQReadyMask; andre@0: PRCList sleepQ; andre@0: PRIntervalTime sleepQmax; andre@0: PRCList pauseQ; andre@0: PRCList suspendQ; andre@0: PRCList waitingToJoinQ; andre@0: andre@0: PRUintn numCPUs; /* number of CPUs using this Q */ andre@0: }; andre@0: andre@0: struct _PRCPU { andre@0: PRCList links; /* link list of CPUs */ andre@0: PRUint32 id; /* id for this CPU */ andre@0: andre@0: union { andre@0: PRInt32 bits; andre@0: PRUint8 missed[4]; andre@0: } u; andre@0: PRIntn where; /* index into u.missed */ andre@0: PRPackedBool paused; /* cpu is paused */ andre@0: PRPackedBool exit; /* cpu should exit */ andre@0: andre@0: PRThread *thread; /* native thread for this CPUThread */ andre@0: PRThread *idle_thread; /* user-level idle thread for this CPUThread */ andre@0: andre@0: PRIntervalTime last_clock; /* the last time we went into andre@0: * _PR_ClockInterrupt() on this CPU andre@0: */ andre@0: andre@0: _PRCPUQueue *queue; andre@0: andre@0: _MDCPU md; andre@0: }; andre@0: andre@0: typedef struct _PRInterruptTable { andre@0: const char *name; andre@0: PRUintn missed_bit; andre@0: void (*handler)(void); andre@0: } _PRInterruptTable; andre@0: andre@0: #define _PR_CPU_PTR(_qp) \ andre@0: ((_PRCPU*) ((char*) (_qp) - offsetof(_PRCPU,links))) andre@0: andre@0: #if !defined(IRIX) && !defined(WIN32) && !defined(XP_OS2) \ andre@0: && !(defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY)) andre@0: #define _MD_GET_ATTACHED_THREAD() (_PR_MD_CURRENT_THREAD()) andre@0: #endif andre@0: andre@0: #ifdef _PR_LOCAL_THREADS_ONLY andre@0: andre@0: NSPR_API(struct _PRCPU *) _pr_currentCPU; andre@0: NSPR_API(PRThread *) _pr_currentThread; andre@0: NSPR_API(PRThread *) _pr_lastThread; andre@0: NSPR_API(PRInt32) _pr_intsOff; andre@0: andre@0: #define _MD_CURRENT_CPU() (_pr_currentCPU) andre@0: #define _MD_SET_CURRENT_CPU(_cpu) (_pr_currentCPU = (_cpu)) andre@0: #define _MD_CURRENT_THREAD() (_pr_currentThread) andre@0: #define _MD_SET_CURRENT_THREAD(_thread) (_pr_currentThread = (_thread)) andre@0: #define _MD_LAST_THREAD() (_pr_lastThread) andre@0: #define _MD_SET_LAST_THREAD(t) (_pr_lastThread = t) andre@0: andre@0: #define _MD_GET_INTSOFF() (_pr_intsOff) andre@0: #define _MD_SET_INTSOFF(_val) (_pr_intsOff = _val) andre@0: andre@0: andre@0: /* The unbalanced curly braces in these two macros are intentional */ andre@0: #define _PR_LOCK_HEAP() { PRIntn _is; if (_pr_currentCPU) _PR_INTSOFF(_is); andre@0: #define _PR_UNLOCK_HEAP() if (_pr_currentCPU) _PR_INTSON(_is); } andre@0: andre@0: #endif /* _PR_LOCAL_THREADS_ONLY */ andre@0: andre@0: extern PRInt32 _native_threads_only; andre@0: andre@0: #if defined(_PR_GLOBAL_THREADS_ONLY) andre@0: andre@0: #define _MD_GET_INTSOFF() 0 andre@0: #define _MD_SET_INTSOFF(_val) andre@0: #define _PR_INTSOFF(_is) andre@0: #define _PR_FAST_INTSON(_is) andre@0: #define _PR_INTSON(_is) andre@0: #define _PR_THREAD_LOCK(_thread) andre@0: #define _PR_THREAD_UNLOCK(_thread) andre@0: #define _PR_RUNQ_LOCK(cpu) andre@0: #define _PR_RUNQ_UNLOCK(cpu) andre@0: #define _PR_SLEEPQ_LOCK(thread) andre@0: #define _PR_SLEEPQ_UNLOCK(thread) andre@0: #define _PR_MISCQ_LOCK(thread) andre@0: #define _PR_MISCQ_UNLOCK(thread) andre@0: #define _PR_CPU_LIST_LOCK() andre@0: #define _PR_CPU_LIST_UNLOCK() andre@0: andre@0: #define _PR_ADD_RUNQ(_thread, _cpu, _pri) andre@0: #define _PR_DEL_RUNQ(_thread) andre@0: #define _PR_ADD_SLEEPQ(_thread, _timeout) andre@0: #define _PR_DEL_SLEEPQ(_thread, _propogate) andre@0: #define _PR_ADD_JOINQ(_thread, _cpu) andre@0: #define _PR_DEL_JOINQ(_thread) andre@0: #define _PR_ADD_SUSPENDQ(_thread, _cpu) andre@0: #define _PR_DEL_SUSPENDQ(_thread) andre@0: andre@0: #define _PR_THREAD_SWITCH_CPU(_thread, _newCPU) andre@0: andre@0: #define _PR_IS_NATIVE_THREAD(thread) 1 andre@0: #define _PR_IS_NATIVE_THREAD_SUPPORTED() 1 andre@0: andre@0: #else andre@0: andre@0: #define _PR_INTSOFF(_is) \ andre@0: PR_BEGIN_MACRO \ andre@0: (_is) = _PR_MD_GET_INTSOFF(); \ andre@0: _PR_MD_SET_INTSOFF(1); \ andre@0: PR_END_MACRO andre@0: andre@0: #define _PR_FAST_INTSON(_is) \ andre@0: PR_BEGIN_MACRO \ andre@0: _PR_MD_SET_INTSOFF(_is); \ andre@0: PR_END_MACRO andre@0: andre@0: #define _PR_INTSON(_is) \ andre@0: PR_BEGIN_MACRO \ andre@0: if ((_is == 0) && (_PR_MD_CURRENT_CPU())->u.bits) \ andre@0: _PR_IntsOn((_PR_MD_CURRENT_CPU())); \ andre@0: _PR_MD_SET_INTSOFF(_is); \ andre@0: PR_END_MACRO andre@0: andre@0: #ifdef _PR_LOCAL_THREADS_ONLY andre@0: andre@0: #define _PR_IS_NATIVE_THREAD(thread) 0 andre@0: #define _PR_THREAD_LOCK(_thread) andre@0: #define _PR_THREAD_UNLOCK(_thread) andre@0: #define _PR_RUNQ_LOCK(cpu) andre@0: #define _PR_RUNQ_UNLOCK(cpu) andre@0: #define _PR_SLEEPQ_LOCK(thread) andre@0: #define _PR_SLEEPQ_UNLOCK(thread) andre@0: #define _PR_MISCQ_LOCK(thread) andre@0: #define _PR_MISCQ_UNLOCK(thread) andre@0: #define _PR_CPU_LIST_LOCK() andre@0: #define _PR_CPU_LIST_UNLOCK() andre@0: andre@0: #define _PR_ADD_RUNQ(_thread, _cpu, _pri) \ andre@0: PR_BEGIN_MACRO \ andre@0: PR_APPEND_LINK(&(_thread)->links, &_PR_RUNQ(_cpu)[_pri]); \ andre@0: _PR_RUNQREADYMASK(_cpu) |= (1L << _pri); \ andre@0: PR_END_MACRO andre@0: andre@0: #define _PR_DEL_RUNQ(_thread) \ andre@0: PR_BEGIN_MACRO \ andre@0: _PRCPU *_cpu = _thread->cpu; \ andre@0: PRInt32 _pri = _thread->priority; \ andre@0: PR_REMOVE_LINK(&(_thread)->links); \ andre@0: if (PR_CLIST_IS_EMPTY(&_PR_RUNQ(_cpu)[_pri])) \ andre@0: _PR_RUNQREADYMASK(_cpu) &= ~(1L << _pri); \ andre@0: PR_END_MACRO andre@0: andre@0: #define _PR_ADD_SLEEPQ(_thread, _timeout) \ andre@0: _PR_AddSleepQ(_thread, _timeout); andre@0: andre@0: #define _PR_DEL_SLEEPQ(_thread, _propogate) \ andre@0: _PR_DelSleepQ(_thread, _propogate); andre@0: andre@0: #define _PR_ADD_JOINQ(_thread, _cpu) \ andre@0: PR_APPEND_LINK(&(_thread)->links, &_PR_WAITINGTOJOINQ(_cpu)); andre@0: andre@0: #define _PR_DEL_JOINQ(_thread) \ andre@0: PR_REMOVE_LINK(&(_thread)->links); andre@0: andre@0: #define _PR_ADD_SUSPENDQ(_thread, _cpu) \ andre@0: PR_APPEND_LINK(&(_thread)->links, &_PR_SUSPENDQ(_cpu)); andre@0: andre@0: #define _PR_DEL_SUSPENDQ(_thread) \ andre@0: PR_REMOVE_LINK(&(_thread)->links); andre@0: andre@0: #define _PR_THREAD_SWITCH_CPU(_thread, _newCPU) andre@0: andre@0: #define _PR_IS_NATIVE_THREAD_SUPPORTED() 0 andre@0: andre@0: #else /* _PR_LOCAL_THREADS_ONLY */ andre@0: andre@0: /* These are for the "combined" thread model */ andre@0: andre@0: #define _PR_THREAD_LOCK(_thread) \ andre@0: _PR_MD_LOCK(&(_thread)->threadLock); andre@0: andre@0: #define _PR_THREAD_UNLOCK(_thread) \ andre@0: _PR_MD_UNLOCK(&(_thread)->threadLock); andre@0: andre@0: #define _PR_RUNQ_LOCK(_cpu) \ andre@0: PR_BEGIN_MACRO \ andre@0: _PR_MD_LOCK(&(_cpu)->queue->runQLock );\ andre@0: PR_END_MACRO andre@0: andre@0: #define _PR_RUNQ_UNLOCK(_cpu) \ andre@0: PR_BEGIN_MACRO \ andre@0: _PR_MD_UNLOCK(&(_cpu)->queue->runQLock );\ andre@0: PR_END_MACRO andre@0: andre@0: #define _PR_SLEEPQ_LOCK(_cpu) \ andre@0: _PR_MD_LOCK(&(_cpu)->queue->sleepQLock ); andre@0: andre@0: #define _PR_SLEEPQ_UNLOCK(_cpu) \ andre@0: _PR_MD_UNLOCK(&(_cpu)->queue->sleepQLock ); andre@0: andre@0: #define _PR_MISCQ_LOCK(_cpu) \ andre@0: _PR_MD_LOCK(&(_cpu)->queue->miscQLock ); andre@0: andre@0: #define _PR_MISCQ_UNLOCK(_cpu) \ andre@0: _PR_MD_UNLOCK(&(_cpu)->queue->miscQLock ); andre@0: andre@0: #define _PR_CPU_LIST_LOCK() _PR_MD_LOCK(&_pr_cpuLock) andre@0: #define _PR_CPU_LIST_UNLOCK() _PR_MD_UNLOCK(&_pr_cpuLock) andre@0: andre@0: #define QUEUE_RUN 0x1 andre@0: #define QUEUE_SLEEP 0x2 andre@0: #define QUEUE_JOIN 0x4 andre@0: #define QUEUE_SUSPEND 0x8 andre@0: #define QUEUE_LOCK 0x10 andre@0: andre@0: #define _PR_ADD_RUNQ(_thread, _cpu, _pri) \ andre@0: PR_BEGIN_MACRO \ andre@0: PR_APPEND_LINK(&(_thread)->links, &_PR_RUNQ(_cpu)[_pri]); \ andre@0: _PR_RUNQREADYMASK(_cpu) |= (1L << _pri); \ andre@0: PR_ASSERT((_thread)->queueCount == 0); \ andre@0: (_thread)->queueCount = QUEUE_RUN; \ andre@0: PR_END_MACRO andre@0: andre@0: #define _PR_DEL_RUNQ(_thread) \ andre@0: PR_BEGIN_MACRO \ andre@0: _PRCPU *_cpu = _thread->cpu; \ andre@0: PRInt32 _pri = _thread->priority; \ andre@0: PR_REMOVE_LINK(&(_thread)->links); \ andre@0: if (PR_CLIST_IS_EMPTY(&_PR_RUNQ(_cpu)[_pri])) \ andre@0: _PR_RUNQREADYMASK(_cpu) &= ~(1L << _pri); \ andre@0: PR_ASSERT((_thread)->queueCount == QUEUE_RUN);\ andre@0: (_thread)->queueCount = 0; \ andre@0: PR_END_MACRO andre@0: andre@0: #define _PR_ADD_SLEEPQ(_thread, _timeout) \ andre@0: PR_ASSERT((_thread)->queueCount == 0); \ andre@0: (_thread)->queueCount = QUEUE_SLEEP; \ andre@0: _PR_AddSleepQ(_thread, _timeout); andre@0: andre@0: #define _PR_DEL_SLEEPQ(_thread, _propogate) \ andre@0: PR_ASSERT((_thread)->queueCount == QUEUE_SLEEP);\ andre@0: (_thread)->queueCount = 0; \ andre@0: _PR_DelSleepQ(_thread, _propogate); andre@0: andre@0: #define _PR_ADD_JOINQ(_thread, _cpu) \ andre@0: PR_ASSERT((_thread)->queueCount == 0); \ andre@0: (_thread)->queueCount = QUEUE_JOIN; \ andre@0: PR_APPEND_LINK(&(_thread)->links, &_PR_WAITINGTOJOINQ(_cpu)); andre@0: andre@0: #define _PR_DEL_JOINQ(_thread) \ andre@0: PR_ASSERT((_thread)->queueCount == QUEUE_JOIN);\ andre@0: (_thread)->queueCount = 0; \ andre@0: PR_REMOVE_LINK(&(_thread)->links); andre@0: andre@0: #define _PR_ADD_SUSPENDQ(_thread, _cpu) \ andre@0: PR_ASSERT((_thread)->queueCount == 0); \ andre@0: (_thread)->queueCount = QUEUE_SUSPEND; \ andre@0: PR_APPEND_LINK(&(_thread)->links, &_PR_SUSPENDQ(_cpu)); andre@0: andre@0: #define _PR_DEL_SUSPENDQ(_thread) \ andre@0: PR_ASSERT((_thread)->queueCount == QUEUE_SUSPEND);\ andre@0: (_thread)->queueCount = 0; \ andre@0: PR_REMOVE_LINK(&(_thread)->links); andre@0: andre@0: #define _PR_THREAD_SWITCH_CPU(_thread, _newCPU) \ andre@0: (_thread)->cpu = (_newCPU); andre@0: andre@0: #define _PR_IS_NATIVE_THREAD(thread) (thread->flags & _PR_GLOBAL_SCOPE) andre@0: #define _PR_IS_NATIVE_THREAD_SUPPORTED() 1 andre@0: andre@0: #endif /* _PR_LOCAL_THREADS_ONLY */ andre@0: andre@0: #endif /* _PR_GLOBAL_THREADS_ONLY */ andre@0: andre@0: #define _PR_SET_RESCHED_FLAG() _PR_MD_CURRENT_CPU()->u.missed[3] = 1 andre@0: #define _PR_CLEAR_RESCHED_FLAG() _PR_MD_CURRENT_CPU()->u.missed[3] = 0 andre@0: andre@0: extern _PRInterruptTable _pr_interruptTable[]; andre@0: andre@0: /* Bits for _pr_interruptState.u.missed[0,1] */ andre@0: #define _PR_MISSED_CLOCK 0x1 andre@0: #define _PR_MISSED_IO 0x2 andre@0: #define _PR_MISSED_CHILD 0x4 andre@0: andre@0: extern void _PR_IntsOn(_PRCPU *cpu); andre@0: andre@0: NSPR_API(void) _PR_WakeupCPU(void); andre@0: NSPR_API(void) _PR_PauseCPU(void); andre@0: andre@0: /************************************************************************/ andre@0: andre@0: #define _PR_LOCK_LOCK(_lock) \ andre@0: _PR_MD_LOCK(&(_lock)->ilock); andre@0: #define _PR_LOCK_UNLOCK(_lock) \ andre@0: _PR_MD_UNLOCK(&(_lock)->ilock); andre@0: andre@0: extern void _PR_UnblockLockWaiter(PRLock *lock); andre@0: extern PRStatus _PR_InitLock(PRLock *lock); andre@0: extern void _PR_FreeLock(PRLock *lock); andre@0: andre@0: #define _PR_LOCK_PTR(_qp) \ andre@0: ((PRLock*) ((char*) (_qp) - offsetof(PRLock,links))) andre@0: andre@0: /************************************************************************/ andre@0: andre@0: #define _PR_CVAR_LOCK(_cvar) \ andre@0: _PR_MD_LOCK(&(_cvar)->ilock); andre@0: #define _PR_CVAR_UNLOCK(_cvar) \ andre@0: _PR_MD_UNLOCK(&(_cvar)->ilock); andre@0: andre@0: extern PRStatus _PR_InitCondVar(PRCondVar *cvar, PRLock *lock); andre@0: extern void _PR_FreeCondVar(PRCondVar *cvar); andre@0: extern PRStatus _PR_WaitCondVar( andre@0: PRThread *thread, PRCondVar *cvar, PRLock *lock, PRIntervalTime timeout); andre@0: extern void _PR_NotifyCondVar(PRCondVar *cvar, PRThread *me); andre@0: extern PRUint32 _PR_CondVarToString(PRCondVar *cvar, char *buf, PRUint32 buflen); andre@0: andre@0: NSPR_API(void) _PR_Notify(PRMonitor *mon, PRBool all, PRBool sticky); andre@0: andre@0: /* PRThread.flags */ andre@0: #define _PR_SYSTEM 0x01 andre@0: #define _PR_INTERRUPT 0x02 andre@0: #define _PR_ATTACHED 0x04 /* created via PR_AttachThread */ andre@0: #define _PR_PRIMORDIAL 0x08 /* the thread that called PR_Init */ andre@0: #define _PR_ON_SLEEPQ 0x10 /* thread is on the sleepQ */ andre@0: #define _PR_ON_PAUSEQ 0x20 /* thread is on the pauseQ */ andre@0: #define _PR_SUSPENDING 0x40 /* thread wants to suspend */ andre@0: #define _PR_GLOBAL_SCOPE 0x80 /* thread is global scope */ andre@0: #define _PR_IDLE_THREAD 0x200 /* this is an idle thread */ andre@0: #define _PR_GCABLE_THREAD 0x400 /* this is a collectable thread */ andre@0: #define _PR_BOUND_THREAD 0x800 /* a bound thread */ andre@0: #define _PR_INTERRUPT_BLOCKED 0x1000 /* interrupts blocked */ andre@0: andre@0: /* PRThread.state */ andre@0: #define _PR_UNBORN 0 andre@0: #define _PR_RUNNABLE 1 andre@0: #define _PR_RUNNING 2 andre@0: #define _PR_LOCK_WAIT 3 andre@0: #define _PR_COND_WAIT 4 andre@0: #define _PR_JOIN_WAIT 5 andre@0: #define _PR_IO_WAIT 6 andre@0: #define _PR_SUSPENDED 7 andre@0: #define _PR_DEAD_STATE 8 /* for debugging */ andre@0: andre@0: /* PRThreadStack.flags */ andre@0: #define _PR_STACK_VM 0x1 /* using vm instead of malloc */ andre@0: #define _PR_STACK_MAPPED 0x2 /* vm is mapped */ andre@0: #define _PR_STACK_PRIMORDIAL 0x4 /* stack for primordial thread */ andre@0: andre@0: /* andre@0: ** If the default stcksize from the client is zero, we need to pick a machine andre@0: ** dependent value. This is only for standard user threads. For custom threads, andre@0: ** 0 has a special meaning. andre@0: ** Adjust stackSize. Round up to a page boundary. andre@0: */ andre@0: andre@0: #ifndef _MD_MINIMUM_STACK_SIZE andre@0: #define _MD_MINIMUM_STACK_SIZE 0 andre@0: #endif andre@0: andre@0: #if (!defined(HAVE_CUSTOM_USER_THREADS)) andre@0: #define _PR_ADJUST_STACKSIZE(stackSize) \ andre@0: PR_BEGIN_MACRO \ andre@0: if (stackSize == 0) \ andre@0: stackSize = _MD_DEFAULT_STACK_SIZE; \ andre@0: if (stackSize < _MD_MINIMUM_STACK_SIZE) \ andre@0: stackSize = _MD_MINIMUM_STACK_SIZE; \ andre@0: stackSize = (stackSize + (1 << _pr_pageShift) - 1) >> _pr_pageShift; \ andre@0: stackSize <<= _pr_pageShift; \ andre@0: PR_END_MACRO andre@0: #else andre@0: #define _PR_ADJUST_STACKSIZE(stackSize) andre@0: #endif andre@0: andre@0: #define _PR_IS_GCABLE_THREAD(thr) ((thr)->flags & _PR_GCABLE_THREAD) andre@0: andre@0: #define _PR_PENDING_INTERRUPT(thr) \ andre@0: (!((thr)->flags & _PR_INTERRUPT_BLOCKED) && ((thr)->flags & _PR_INTERRUPT)) andre@0: #define _PR_THREAD_BLOCK_INTERRUPT(thr) \ andre@0: (thr->flags |= _PR_INTERRUPT_BLOCKED) andre@0: #define _PR_THREAD_UNBLOCK_INTERRUPT(thr) \ andre@0: (thr->flags &= ~_PR_INTERRUPT_BLOCKED) andre@0: andre@0: #define _PR_THREAD_PTR(_qp) \ andre@0: ((PRThread*) ((char*) (_qp) - offsetof(PRThread,links))) andre@0: andre@0: #define _PR_ACTIVE_THREAD_PTR(_qp) \ andre@0: ((PRThread*) ((char*) (_qp) - offsetof(PRThread,active))) andre@0: andre@0: #define _PR_THREAD_CONDQ_PTR(_qp) \ andre@0: ((PRThread*) ((char*) (_qp) - offsetof(PRThread,waitQLinks))) andre@0: andre@0: #define _PR_THREAD_MD_TO_PTR(_md) \ andre@0: ((PRThread*) ((char*) (_md) - offsetof(PRThread,md))) andre@0: andre@0: #define _PR_THREAD_STACK_TO_PTR(_stack) \ andre@0: ((PRThread*) (_stack->thr)) andre@0: andre@0: extern PRCList _pr_active_local_threadQ; andre@0: extern PRCList _pr_active_global_threadQ; andre@0: extern PRCList _pr_cpuQ; andre@0: extern _MDLock _pr_cpuLock; andre@0: extern PRInt32 _pr_md_idle_cpus; andre@0: andre@0: #define _PR_ACTIVE_LOCAL_THREADQ() _pr_active_local_threadQ andre@0: #define _PR_ACTIVE_GLOBAL_THREADQ() _pr_active_global_threadQ andre@0: #define _PR_CPUQ() _pr_cpuQ andre@0: #define _PR_RUNQ(_cpu) ((_cpu)->queue->runQ) andre@0: #define _PR_RUNQREADYMASK(_cpu) ((_cpu)->queue->runQReadyMask) andre@0: #define _PR_SLEEPQ(_cpu) ((_cpu)->queue->sleepQ) andre@0: #define _PR_SLEEPQMAX(_cpu) ((_cpu)->queue->sleepQmax) andre@0: #define _PR_PAUSEQ(_cpu) ((_cpu)->queue->pauseQ) andre@0: #define _PR_SUSPENDQ(_cpu) ((_cpu)->queue->suspendQ) andre@0: #define _PR_WAITINGTOJOINQ(_cpu) ((_cpu)->queue->waitingToJoinQ) andre@0: andre@0: extern PRUint32 _pr_recycleThreads; /* Flag for behavior on thread cleanup */ andre@0: extern PRLock *_pr_deadQLock; andre@0: extern PRUint32 _pr_numNativeDead; andre@0: extern PRUint32 _pr_numUserDead; andre@0: extern PRCList _pr_deadNativeQ; andre@0: extern PRCList _pr_deadUserQ; andre@0: #define _PR_DEADNATIVEQ _pr_deadNativeQ andre@0: #define _PR_DEADUSERQ _pr_deadUserQ andre@0: #define _PR_DEADQ_LOCK PR_Lock(_pr_deadQLock); andre@0: #define _PR_DEADQ_UNLOCK PR_Unlock(_pr_deadQLock); andre@0: #define _PR_INC_DEADNATIVE (_pr_numNativeDead++) andre@0: #define _PR_DEC_DEADNATIVE (_pr_numNativeDead--) andre@0: #define _PR_NUM_DEADNATIVE (_pr_numNativeDead) andre@0: #define _PR_INC_DEADUSER (_pr_numUserDead++) andre@0: #define _PR_DEC_DEADUSER (_pr_numUserDead--) andre@0: #define _PR_NUM_DEADUSER (_pr_numUserDead) andre@0: andre@0: extern PRUint32 _pr_utid; andre@0: andre@0: extern struct _PRCPU *_pr_primordialCPU; andre@0: andre@0: extern PRLock *_pr_activeLock; /* lock for userActive and systemActive */ andre@0: extern PRInt32 _pr_userActive; /* number of active user threads */ andre@0: extern PRInt32 _pr_systemActive; /* number of active system threads */ andre@0: extern PRInt32 _pr_primordialExitCount; /* number of user threads left andre@0: * before the primordial thread andre@0: * can exit. */ andre@0: extern PRCondVar *_pr_primordialExitCVar; /* the condition variable for andre@0: * notifying the primordial thread andre@0: * when all other user threads andre@0: * have terminated. */ andre@0: andre@0: extern PRUintn _pr_maxPTDs; andre@0: andre@0: extern PRLock *_pr_terminationCVLock; andre@0: andre@0: /************************************************************************* andre@0: * Internal routines either called by PR itself or from machine-dependent * andre@0: * code. * andre@0: *************************************************************************/ andre@0: andre@0: extern void _PR_ClockInterrupt(void); andre@0: andre@0: extern void _PR_Schedule(void); andre@0: extern void _PR_SetThreadPriority( andre@0: PRThread* thread, PRThreadPriority priority); andre@0: andre@0: /*********************************************************************** andre@0: ** FUNCTION: _PR_NewSegment() andre@0: ** DESCRIPTION: andre@0: ** Allocate a memory segment. The "size" value is rounded up to the andre@0: ** native system page size and a page aligned portion of memory is andre@0: ** returned. This memory is not part of the malloc heap. If "vaddr" is andre@0: ** not NULL then PR tries to allocate the segment at the desired virtual andre@0: ** address. andre@0: ** INPUTS: size: size of the desired memory segment andre@0: ** vaddr: address at which the newly aquired segment is to be andre@0: ** mapped into memory. andre@0: ** OUTPUTS: a memory segment is allocated, a PRSegment is allocated andre@0: ** RETURN: pointer to PRSegment andre@0: ***********************************************************************/ andre@0: extern PRSegment* _PR_NewSegment(PRUint32 size, void *vaddr); andre@0: andre@0: /*********************************************************************** andre@0: ** FUNCTION: _PR_DestroySegment() andre@0: ** DESCRIPTION: andre@0: ** The memory segment and the PRSegment are freed andre@0: ** INPUTS: seg: pointer to PRSegment to be freed andre@0: ** OUTPUTS: the the PRSegment and its associated memory segment are freed andre@0: ** RETURN: void andre@0: ***********************************************************************/ andre@0: extern void _PR_DestroySegment(PRSegment *seg); andre@0: andre@0: extern PRThreadStack * _PR_NewStack(PRUint32 stackSize); andre@0: extern void _PR_FreeStack(PRThreadStack *stack); andre@0: extern PRBool _PR_NotifyThread (PRThread *thread, PRThread *me); andre@0: extern void _PR_NotifyLockedThread (PRThread *thread); andre@0: andre@0: NSPR_API(void) _PR_AddSleepQ(PRThread *thread, PRIntervalTime timeout); andre@0: NSPR_API(void) _PR_DelSleepQ(PRThread *thread, PRBool propogate_time); andre@0: andre@0: extern void _PR_AddThreadToRunQ(PRThread *me, PRThread *thread); andre@0: andre@0: NSPR_API(PRThread*) _PR_CreateThread(PRThreadType type, andre@0: void (*start)(void *arg), andre@0: void *arg, andre@0: PRThreadPriority priority, andre@0: PRThreadScope scope, andre@0: PRThreadState state, andre@0: PRUint32 stackSize, andre@0: PRUint32 flags); andre@0: andre@0: extern void _PR_NativeDestroyThread(PRThread *thread); andre@0: extern void _PR_UserDestroyThread(PRThread *thread); andre@0: andre@0: extern PRThread* _PRI_AttachThread( andre@0: PRThreadType type, PRThreadPriority priority, andre@0: PRThreadStack *stack, PRUint32 flags); andre@0: andre@0: extern void _PRI_DetachThread(void); andre@0: andre@0: andre@0: #define _PR_IO_PENDING(_thread) ((_thread)->io_pending) andre@0: andre@0: NSPR_API(void) _PR_MD_INIT_CPUS(); andre@0: #define _PR_MD_INIT_CPUS _MD_INIT_CPUS andre@0: andre@0: NSPR_API(void) _PR_MD_WAKEUP_CPUS(); andre@0: #define _PR_MD_WAKEUP_CPUS _MD_WAKEUP_CPUS andre@0: andre@0: /* Interrupts related */ andre@0: andre@0: NSPR_API(void) _PR_MD_START_INTERRUPTS(void); andre@0: #define _PR_MD_START_INTERRUPTS _MD_START_INTERRUPTS andre@0: andre@0: NSPR_API(void) _PR_MD_STOP_INTERRUPTS(void); andre@0: #define _PR_MD_STOP_INTERRUPTS _MD_STOP_INTERRUPTS andre@0: andre@0: NSPR_API(void) _PR_MD_ENABLE_CLOCK_INTERRUPTS(void); andre@0: #define _PR_MD_ENABLE_CLOCK_INTERRUPTS _MD_ENABLE_CLOCK_INTERRUPTS andre@0: andre@0: NSPR_API(void) _PR_MD_DISABLE_CLOCK_INTERRUPTS(void); andre@0: #define _PR_MD_DISABLE_CLOCK_INTERRUPTS _MD_DISABLE_CLOCK_INTERRUPTS andre@0: andre@0: NSPR_API(void) _PR_MD_BLOCK_CLOCK_INTERRUPTS(void); andre@0: #define _PR_MD_BLOCK_CLOCK_INTERRUPTS _MD_BLOCK_CLOCK_INTERRUPTS andre@0: andre@0: NSPR_API(void) _PR_MD_UNBLOCK_CLOCK_INTERRUPTS(void); andre@0: #define _PR_MD_UNBLOCK_CLOCK_INTERRUPTS _MD_UNBLOCK_CLOCK_INTERRUPTS andre@0: andre@0: /* The _PR_MD_WAIT_LOCK and _PR_MD_WAKEUP_WAITER functions put to sleep and andre@0: * awaken a thread which is waiting on a lock or cvar. andre@0: */ andre@0: extern PRStatus _PR_MD_WAIT(PRThread *, PRIntervalTime timeout); andre@0: #define _PR_MD_WAIT _MD_WAIT andre@0: andre@0: extern PRStatus _PR_MD_WAKEUP_WAITER(PRThread *); andre@0: #define _PR_MD_WAKEUP_WAITER _MD_WAKEUP_WAITER andre@0: andre@0: #ifndef _PR_LOCAL_THREADS_ONLY /* not if only local threads supported */ andre@0: NSPR_API(void) _PR_MD_CLOCK_INTERRUPT(void); andre@0: #define _PR_MD_CLOCK_INTERRUPT _MD_CLOCK_INTERRUPT andre@0: #endif andre@0: andre@0: /* Stack debugging */ andre@0: NSPR_API(void) _PR_MD_INIT_STACK(PRThreadStack *ts, PRIntn redzone); andre@0: #define _PR_MD_INIT_STACK _MD_INIT_STACK andre@0: andre@0: NSPR_API(void) _PR_MD_CLEAR_STACK(PRThreadStack* ts); andre@0: #define _PR_MD_CLEAR_STACK _MD_CLEAR_STACK andre@0: andre@0: /* CPU related */ andre@0: NSPR_API(PRInt32) _PR_MD_GET_INTSOFF(void); andre@0: #define _PR_MD_GET_INTSOFF _MD_GET_INTSOFF andre@0: andre@0: NSPR_API(void) _PR_MD_SET_INTSOFF(PRInt32 _val); andre@0: #define _PR_MD_SET_INTSOFF _MD_SET_INTSOFF andre@0: andre@0: NSPR_API(_PRCPU*) _PR_MD_CURRENT_CPU(void); andre@0: #define _PR_MD_CURRENT_CPU _MD_CURRENT_CPU andre@0: andre@0: NSPR_API(void) _PR_MD_SET_CURRENT_CPU(_PRCPU *cpu); andre@0: #define _PR_MD_SET_CURRENT_CPU _MD_SET_CURRENT_CPU andre@0: andre@0: NSPR_API(void) _PR_MD_INIT_RUNNING_CPU(_PRCPU *cpu); andre@0: #define _PR_MD_INIT_RUNNING_CPU _MD_INIT_RUNNING_CPU andre@0: andre@0: /* andre@0: * Returns the number of threads awoken or 0 if a timeout occurred; andre@0: */ andre@0: extern PRInt32 _PR_MD_PAUSE_CPU(PRIntervalTime timeout); andre@0: #define _PR_MD_PAUSE_CPU _MD_PAUSE_CPU andre@0: andre@0: extern void _PR_MD_CLEANUP_BEFORE_EXIT(void); andre@0: #define _PR_MD_CLEANUP_BEFORE_EXIT _MD_CLEANUP_BEFORE_EXIT andre@0: andre@0: extern void _PR_MD_EXIT(PRIntn status); andre@0: #define _PR_MD_EXIT _MD_EXIT andre@0: andre@0: /* Locks related */ andre@0: andre@0: NSPR_API(void) _PR_MD_INIT_LOCKS(void); andre@0: #define _PR_MD_INIT_LOCKS _MD_INIT_LOCKS andre@0: andre@0: NSPR_API(PRStatus) _PR_MD_NEW_LOCK(_MDLock *md); andre@0: #define _PR_MD_NEW_LOCK _MD_NEW_LOCK andre@0: andre@0: NSPR_API(void) _PR_MD_FREE_LOCK(_MDLock *md); andre@0: #define _PR_MD_FREE_LOCK _MD_FREE_LOCK andre@0: andre@0: NSPR_API(void) _PR_MD_LOCK(_MDLock *md); andre@0: #define _PR_MD_LOCK _MD_LOCK andre@0: andre@0: /* Return 0 on success, a nonzero value on failure. */ andre@0: NSPR_API(PRIntn) _PR_MD_TEST_AND_LOCK(_MDLock *md); andre@0: #define _PR_MD_TEST_AND_LOCK _MD_TEST_AND_LOCK andre@0: andre@0: NSPR_API(void) _PR_MD_UNLOCK(_MDLock *md); andre@0: #define _PR_MD_UNLOCK _MD_UNLOCK andre@0: andre@0: NSPR_API(void) _PR_MD_IOQ_LOCK(void); andre@0: #define _PR_MD_IOQ_LOCK _MD_IOQ_LOCK andre@0: andre@0: NSPR_API(void) _PR_MD_IOQ_UNLOCK(void); andre@0: #define _PR_MD_IOQ_UNLOCK _MD_IOQ_UNLOCK andre@0: andre@0: #ifndef _PR_LOCAL_THREADS_ONLY /* not if only local threads supported */ andre@0: /* Semaphore related -- only for native threads */ andre@0: #ifdef HAVE_CVAR_BUILT_ON_SEM andre@0: NSPR_API(void) _PR_MD_NEW_SEM(_MDSemaphore *md, PRUintn value); andre@0: #define _PR_MD_NEW_SEM _MD_NEW_SEM andre@0: andre@0: NSPR_API(void) _PR_MD_DESTROY_SEM(_MDSemaphore *md); andre@0: #define _PR_MD_DESTROY_SEM _MD_DESTROY_SEM andre@0: andre@0: NSPR_API(PRStatus) _PR_MD_TIMED_WAIT_SEM( andre@0: _MDSemaphore *md, PRIntervalTime timeout); andre@0: #define _PR_MD_TIMED_WAIT_SEM _MD_TIMED_WAIT_SEM andre@0: andre@0: NSPR_API(PRStatus) _PR_MD_WAIT_SEM(_MDSemaphore *md); andre@0: #define _PR_MD_WAIT_SEM _MD_WAIT_SEM andre@0: andre@0: NSPR_API(void) _PR_MD_POST_SEM(_MDSemaphore *md); andre@0: #define _PR_MD_POST_SEM _MD_POST_SEM andre@0: #endif /* HAVE_CVAR_BUILT_ON_SEM */ andre@0: andre@0: #endif andre@0: andre@0: /* Condition Variables related -- only for native threads */ andre@0: andre@0: #ifndef _PR_LOCAL_THREADS_ONLY /* not if only local threads supported */ andre@0: NSPR_API(PRInt32) _PR_MD_NEW_CV(_MDCVar *md); andre@0: #define _PR_MD_NEW_CV _MD_NEW_CV andre@0: andre@0: NSPR_API(void) _PR_MD_FREE_CV(_MDCVar *md); andre@0: #define _PR_MD_FREE_CV _MD_FREE_CV andre@0: andre@0: NSPR_API(void) _PR_MD_WAIT_CV( andre@0: _MDCVar *mdCVar,_MDLock *mdLock,PRIntervalTime timeout); andre@0: #define _PR_MD_WAIT_CV _MD_WAIT_CV andre@0: andre@0: NSPR_API(void) _PR_MD_NOTIFY_CV(_MDCVar *md, _MDLock *lock); andre@0: #define _PR_MD_NOTIFY_CV _MD_NOTIFY_CV andre@0: andre@0: NSPR_API(void) _PR_MD_NOTIFYALL_CV(_MDCVar *md, _MDLock *lock); andre@0: #define _PR_MD_NOTIFYALL_CV _MD_NOTIFYALL_CV andre@0: #endif /* _PR_LOCAL_THREADS_ONLY */ andre@0: andre@0: /* Threads related */ andre@0: NSPR_API(PRThread*) _PR_MD_CURRENT_THREAD(void); andre@0: #define _PR_MD_CURRENT_THREAD _MD_CURRENT_THREAD andre@0: andre@0: NSPR_API(PRThread*) _PR_MD_GET_ATTACHED_THREAD(void); andre@0: #define _PR_MD_GET_ATTACHED_THREAD _MD_GET_ATTACHED_THREAD andre@0: andre@0: NSPR_API(PRThread*) _PR_MD_LAST_THREAD(void); andre@0: #define _PR_MD_LAST_THREAD _MD_LAST_THREAD andre@0: andre@0: NSPR_API(void) _PR_MD_SET_CURRENT_THREAD(PRThread *thread); andre@0: #define _PR_MD_SET_CURRENT_THREAD _MD_SET_CURRENT_THREAD andre@0: andre@0: NSPR_API(void) _PR_MD_SET_LAST_THREAD(PRThread *thread); andre@0: #define _PR_MD_SET_LAST_THREAD _MD_SET_LAST_THREAD andre@0: andre@0: extern PRStatus _PR_MD_INIT_THREAD(PRThread *thread); andre@0: #define _PR_MD_INIT_THREAD _MD_INIT_THREAD andre@0: andre@0: extern void _PR_MD_EXIT_THREAD(PRThread *thread); andre@0: #define _PR_MD_EXIT_THREAD _MD_EXIT_THREAD andre@0: andre@0: #ifndef _PR_LOCAL_THREADS_ONLY /* not if only local threads supported */ andre@0: andre@0: NSPR_API(PRStatus) _PR_MD_INIT_ATTACHED_THREAD(PRThread *thread); andre@0: #define _PR_MD_INIT_ATTACHED_THREAD _MD_INIT_ATTACHED_THREAD andre@0: andre@0: extern void _PR_MD_SUSPEND_THREAD(PRThread *thread); andre@0: #define _PR_MD_SUSPEND_THREAD _MD_SUSPEND_THREAD andre@0: andre@0: extern void _PR_MD_RESUME_THREAD(PRThread *thread); andre@0: #define _PR_MD_RESUME_THREAD _MD_RESUME_THREAD andre@0: andre@0: extern void _PR_MD_SUSPEND_CPU(_PRCPU *cpu); andre@0: #define _PR_MD_SUSPEND_CPU _MD_SUSPEND_CPU andre@0: andre@0: extern void _PR_MD_RESUME_CPU(_PRCPU *cpu); andre@0: #define _PR_MD_RESUME_CPU _MD_RESUME_CPU andre@0: andre@0: extern void _PR_MD_BEGIN_SUSPEND_ALL(void); andre@0: #define _PR_MD_BEGIN_SUSPEND_ALL _MD_BEGIN_SUSPEND_ALL andre@0: andre@0: extern void _PR_MD_END_SUSPEND_ALL(void); andre@0: #define _PR_MD_END_SUSPEND_ALL _MD_END_SUSPEND_ALL andre@0: andre@0: extern void _PR_MD_BEGIN_RESUME_ALL(void); andre@0: #define _PR_MD_BEGIN_RESUME_ALL _MD_BEGIN_RESUME_ALL andre@0: andre@0: extern void _PR_MD_END_RESUME_ALL(void); andre@0: #define _PR_MD_END_RESUME_ALL _MD_END_RESUME_ALL andre@0: andre@0: #if defined(IRIX) andre@0: NSPR_API(void) _PR_IRIX_CHILD_PROCESS(void); andre@0: #endif /* IRIX */ andre@0: andre@0: #endif /* !_PR_LOCAL_THREADS_ONLY */ andre@0: andre@0: extern void _PR_MD_CLEAN_THREAD(PRThread *thread); andre@0: #define _PR_MD_CLEAN_THREAD _MD_CLEAN_THREAD andre@0: andre@0: #ifdef HAVE_CUSTOM_USER_THREADS andre@0: extern void _PR_MD_CREATE_PRIMORDIAL_USER_THREAD(PRThread *); andre@0: #define _PR_MD_CREATE_PRIMORDIAL_USER_THREAD _MD_CREATE_PRIMORDIAL_USER_THREAD andre@0: andre@0: extern PRThread* _PR_MD_CREATE_USER_THREAD( andre@0: PRUint32 stacksize, andre@0: void (*start)(void *), andre@0: void *arg); andre@0: #define _PR_MD_CREATE_USER_THREAD _MD_CREATE_USER_THREAD andre@0: #endif andre@0: andre@0: extern PRStatus _PR_MD_CREATE_THREAD( andre@0: PRThread *thread, andre@0: void (*start) (void *), andre@0: PRThreadPriority priority, andre@0: PRThreadScope scope, andre@0: PRThreadState state, andre@0: PRUint32 stackSize); andre@0: #define _PR_MD_CREATE_THREAD _MD_CREATE_THREAD andre@0: andre@0: extern void _PR_MD_JOIN_THREAD(_MDThread *md); andre@0: #define _PR_MD_JOIN_THREAD _MD_JOIN_THREAD andre@0: andre@0: extern void _PR_MD_END_THREAD(void); andre@0: #define _PR_MD_END_THREAD _MD_END_THREAD andre@0: andre@0: extern void _PR_MD_YIELD(void); andre@0: #define _PR_MD_YIELD _MD_YIELD andre@0: andre@0: extern void _PR_MD_SET_PRIORITY(_MDThread *md, PRThreadPriority newPri); andre@0: #define _PR_MD_SET_PRIORITY _MD_SET_PRIORITY andre@0: andre@0: extern void _PR_MD_SET_CURRENT_THREAD_NAME(const char *name); andre@0: #define _PR_MD_SET_CURRENT_THREAD_NAME _MD_SET_CURRENT_THREAD_NAME andre@0: andre@0: NSPR_API(void) _PR_MD_SUSPENDALL(void); andre@0: #define _PR_MD_SUSPENDALL _MD_SUSPENDALL andre@0: andre@0: NSPR_API(void) _PR_MD_RESUMEALL(void); andre@0: #define _PR_MD_RESUMEALL _MD_RESUMEALL andre@0: andre@0: extern void _PR_MD_INIT_CONTEXT( andre@0: PRThread *thread, char *top, void (*start) (void), PRBool *status); andre@0: #define _PR_MD_INIT_CONTEXT _MD_INIT_CONTEXT andre@0: andre@0: extern void _PR_MD_SWITCH_CONTEXT(PRThread *thread); andre@0: #define _PR_MD_SWITCH_CONTEXT _MD_SWITCH_CONTEXT andre@0: andre@0: extern void _PR_MD_RESTORE_CONTEXT(PRThread *thread); andre@0: #define _PR_MD_RESTORE_CONTEXT _MD_RESTORE_CONTEXT andre@0: andre@0: /* Segment related */ andre@0: extern void _PR_MD_INIT_SEGS(void); andre@0: #define _PR_MD_INIT_SEGS _MD_INIT_SEGS andre@0: andre@0: extern PRStatus _PR_MD_ALLOC_SEGMENT(PRSegment *seg, PRUint32 size, void *vaddr); andre@0: #define _PR_MD_ALLOC_SEGMENT _MD_ALLOC_SEGMENT andre@0: andre@0: extern void _PR_MD_FREE_SEGMENT(PRSegment *seg); andre@0: #define _PR_MD_FREE_SEGMENT _MD_FREE_SEGMENT andre@0: andre@0: /* Directory enumeration related */ andre@0: extern PRStatus _PR_MD_OPEN_DIR(_MDDir *md,const char *name); andre@0: #define _PR_MD_OPEN_DIR _MD_OPEN_DIR andre@0: andre@0: extern char * _PR_MD_READ_DIR(_MDDir *md, PRIntn flags); andre@0: #define _PR_MD_READ_DIR _MD_READ_DIR andre@0: andre@0: extern PRInt32 _PR_MD_CLOSE_DIR(_MDDir *md); andre@0: #define _PR_MD_CLOSE_DIR _MD_CLOSE_DIR andre@0: andre@0: /* Named semaphores related */ andre@0: extern PRSem * _PR_MD_OPEN_SEMAPHORE( andre@0: const char *osname, PRIntn flags, PRIntn mode, PRUintn value); andre@0: #define _PR_MD_OPEN_SEMAPHORE _MD_OPEN_SEMAPHORE andre@0: andre@0: extern PRStatus _PR_MD_WAIT_SEMAPHORE(PRSem *sem); andre@0: #define _PR_MD_WAIT_SEMAPHORE _MD_WAIT_SEMAPHORE andre@0: andre@0: extern PRStatus _PR_MD_POST_SEMAPHORE(PRSem *sem); andre@0: #define _PR_MD_POST_SEMAPHORE _MD_POST_SEMAPHORE andre@0: andre@0: extern PRStatus _PR_MD_CLOSE_SEMAPHORE(PRSem *sem); andre@0: #define _PR_MD_CLOSE_SEMAPHORE _MD_CLOSE_SEMAPHORE andre@0: andre@0: extern PRStatus _PR_MD_DELETE_SEMAPHORE(const char *osname); andre@0: #define _PR_MD_DELETE_SEMAPHORE _MD_DELETE_SEMAPHORE andre@0: andre@0: /* I/O related */ andre@0: extern void _PR_MD_INIT_FILEDESC(PRFileDesc *fd); andre@0: #define _PR_MD_INIT_FILEDESC _MD_INIT_FILEDESC andre@0: andre@0: extern void _PR_MD_MAKE_NONBLOCK(PRFileDesc *fd); andre@0: #define _PR_MD_MAKE_NONBLOCK _MD_MAKE_NONBLOCK andre@0: andre@0: /* File I/O related */ andre@0: extern PROsfd _PR_MD_OPEN(const char *name, PRIntn osflags, PRIntn mode); andre@0: #define _PR_MD_OPEN _MD_OPEN andre@0: andre@0: extern PROsfd _PR_MD_OPEN_FILE(const char *name, PRIntn osflags, PRIntn mode); andre@0: #define _PR_MD_OPEN_FILE _MD_OPEN_FILE andre@0: andre@0: extern PRInt32 _PR_MD_CLOSE_FILE(PROsfd osfd); andre@0: #define _PR_MD_CLOSE_FILE _MD_CLOSE_FILE andre@0: andre@0: extern PRInt32 _PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 amount); andre@0: #define _PR_MD_READ _MD_READ andre@0: andre@0: extern PRInt32 _PR_MD_WRITE(PRFileDesc *fd, const void *buf, PRInt32 amount); andre@0: #define _PR_MD_WRITE _MD_WRITE andre@0: andre@0: extern PRInt32 _PR_MD_WRITEV( andre@0: PRFileDesc *fd, const struct PRIOVec *iov, andre@0: PRInt32 iov_size, PRIntervalTime timeout); andre@0: #define _PR_MD_WRITEV _MD_WRITEV andre@0: andre@0: extern PRInt32 _PR_MD_FSYNC(PRFileDesc *fd); andre@0: #define _PR_MD_FSYNC _MD_FSYNC andre@0: andre@0: extern PRInt32 _PR_MD_DELETE(const char *name); andre@0: #define _PR_MD_DELETE _MD_DELETE andre@0: andre@0: extern PRInt32 _PR_MD_RENAME(const char *from, const char *to); andre@0: #define _PR_MD_RENAME _MD_RENAME andre@0: andre@0: extern PRInt32 _PR_MD_ACCESS(const char *name, PRAccessHow how); andre@0: #define _PR_MD_ACCESS _MD_ACCESS andre@0: andre@0: extern PRInt32 _PR_MD_STAT(const char *name, struct stat *buf); andre@0: #define _PR_MD_STAT _MD_STAT andre@0: andre@0: extern PRInt32 _PR_MD_MKDIR(const char *name, PRIntn mode); andre@0: #define _PR_MD_MKDIR _MD_MKDIR andre@0: andre@0: extern PRInt32 _PR_MD_MAKE_DIR(const char *name, PRIntn mode); andre@0: #define _PR_MD_MAKE_DIR _MD_MAKE_DIR andre@0: andre@0: extern PRInt32 _PR_MD_RMDIR(const char *name); andre@0: #define _PR_MD_RMDIR _MD_RMDIR andre@0: andre@0: #ifdef MOZ_UNICODE andre@0: /* UTF16 File I/O related */ andre@0: extern PRStatus _PR_MD_OPEN_DIR_UTF16(_MDDirUTF16 *md, const PRUnichar *name); andre@0: #define _PR_MD_OPEN_DIR_UTF16 _MD_OPEN_DIR_UTF16 andre@0: andre@0: extern PROsfd _PR_MD_OPEN_FILE_UTF16(const PRUnichar *name, PRIntn osflags, PRIntn mode); andre@0: #define _PR_MD_OPEN_FILE_UTF16 _MD_OPEN_FILE_UTF16 andre@0: andre@0: extern PRUnichar * _PR_MD_READ_DIR_UTF16(_MDDirUTF16 *md, PRIntn flags); andre@0: #define _PR_MD_READ_DIR_UTF16 _MD_READ_DIR_UTF16 andre@0: andre@0: extern PRInt32 _PR_MD_CLOSE_DIR_UTF16(_MDDirUTF16 *md); andre@0: #define _PR_MD_CLOSE_DIR_UTF16 _MD_CLOSE_DIR_UTF16 andre@0: andre@0: extern PRInt32 _PR_MD_GETFILEINFO64_UTF16(const PRUnichar *fn, PRFileInfo64 *info); andre@0: #define _PR_MD_GETFILEINFO64_UTF16 _MD_GETFILEINFO64_UTF16 andre@0: #endif /* MOZ_UNICODE */ andre@0: andre@0: /* Socket I/O related */ andre@0: extern void _PR_MD_INIT_IO(void); andre@0: #define _PR_MD_INIT_IO _MD_INIT_IO andre@0: andre@0: extern PRInt32 _PR_MD_CLOSE_SOCKET(PROsfd osfd); andre@0: #define _PR_MD_CLOSE_SOCKET _MD_CLOSE_SOCKET andre@0: andre@0: extern PRInt32 _PR_MD_CONNECT( andre@0: PRFileDesc *fd, const PRNetAddr *addr, andre@0: PRUint32 addrlen, PRIntervalTime timeout); andre@0: #define _PR_MD_CONNECT _MD_CONNECT andre@0: andre@0: extern PROsfd _PR_MD_ACCEPT( andre@0: PRFileDesc *fd, PRNetAddr *addr, andre@0: PRUint32 *addrlen, PRIntervalTime timeout); andre@0: #define _PR_MD_ACCEPT _MD_ACCEPT andre@0: andre@0: extern PRInt32 _PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen); andre@0: #define _PR_MD_BIND _MD_BIND andre@0: andre@0: extern PRInt32 _PR_MD_LISTEN(PRFileDesc *fd, PRIntn backlog); andre@0: #define _PR_MD_LISTEN _MD_LISTEN andre@0: andre@0: extern PRInt32 _PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how); andre@0: #define _PR_MD_SHUTDOWN _MD_SHUTDOWN andre@0: andre@0: extern PRInt32 _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, andre@0: PRIntn flags, PRIntervalTime timeout); andre@0: #define _PR_MD_RECV _MD_RECV andre@0: andre@0: extern PRInt32 _PR_MD_SEND( andre@0: PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, andre@0: PRIntervalTime timeout); andre@0: #define _PR_MD_SEND _MD_SEND andre@0: andre@0: extern PRInt32 _PR_MD_ACCEPT_READ(PRFileDesc *sd, PROsfd *newSock, andre@0: PRNetAddr **raddr, void *buf, PRInt32 amount, andre@0: PRIntervalTime timeout); andre@0: #define _PR_MD_ACCEPT_READ _MD_ACCEPT_READ andre@0: andre@0: #ifdef WIN32 andre@0: extern PROsfd _PR_MD_FAST_ACCEPT(PRFileDesc *fd, PRNetAddr *addr, andre@0: PRUint32 *addrlen, PRIntervalTime timeout, andre@0: PRBool fast, andre@0: _PR_AcceptTimeoutCallback callback, andre@0: void *callbackArg); andre@0: andre@0: extern PRInt32 _PR_MD_FAST_ACCEPT_READ(PRFileDesc *sd, PROsfd *newSock, andre@0: PRNetAddr **raddr, void *buf, PRInt32 amount, andre@0: PRIntervalTime timeout, PRBool fast, andre@0: _PR_AcceptTimeoutCallback callback, andre@0: void *callbackArg); andre@0: andre@0: extern void _PR_MD_UPDATE_ACCEPT_CONTEXT(PROsfd s, PROsfd ls); andre@0: #define _PR_MD_UPDATE_ACCEPT_CONTEXT _MD_UPDATE_ACCEPT_CONTEXT andre@0: /* andre@0: * The NSPR epoch (00:00:00 1 Jan 1970 UTC) in FILETIME. andre@0: * We store the value in a PRTime variable for convenience. andre@0: * This constant is used by _PR_FileTimeToPRTime(). andre@0: * This is defined in ntmisc.c andre@0: */ andre@0: extern const PRTime _pr_filetime_offset; andre@0: #endif /* WIN32 */ andre@0: andre@0: extern PRInt32 _PR_MD_SENDFILE( andre@0: PRFileDesc *sock, PRSendFileData *sfd, andre@0: PRInt32 flags, PRIntervalTime timeout); andre@0: #define _PR_MD_SENDFILE _MD_SENDFILE andre@0: andre@0: extern PRStatus _PR_MD_GETSOCKNAME( andre@0: PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen); andre@0: #define _PR_MD_GETSOCKNAME _MD_GETSOCKNAME andre@0: andre@0: extern PRStatus _PR_MD_GETPEERNAME( andre@0: PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen); andre@0: #define _PR_MD_GETPEERNAME _MD_GETPEERNAME andre@0: andre@0: extern PRStatus _PR_MD_GETSOCKOPT( andre@0: PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen); andre@0: #define _PR_MD_GETSOCKOPT _MD_GETSOCKOPT andre@0: andre@0: extern PRStatus _PR_MD_SETSOCKOPT( andre@0: PRFileDesc *fd, PRInt32 level, PRInt32 optname, andre@0: const char* optval, PRInt32 optlen); andre@0: #define _PR_MD_SETSOCKOPT _MD_SETSOCKOPT andre@0: andre@0: extern PRStatus PR_CALLBACK _PR_SocketGetSocketOption( andre@0: PRFileDesc *fd, PRSocketOptionData *data); andre@0: andre@0: extern PRStatus PR_CALLBACK _PR_SocketSetSocketOption( andre@0: PRFileDesc *fd, const PRSocketOptionData *data); andre@0: andre@0: extern PRInt32 _PR_MD_RECVFROM( andre@0: PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, andre@0: PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout); andre@0: #define _PR_MD_RECVFROM _MD_RECVFROM andre@0: andre@0: extern PRInt32 _PR_MD_SENDTO( andre@0: PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, andre@0: const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout); andre@0: #define _PR_MD_SENDTO _MD_SENDTO andre@0: andre@0: extern PRInt32 _PR_MD_SOCKETPAIR(int af, int type, int flags, PROsfd *osfd); andre@0: #define _PR_MD_SOCKETPAIR _MD_SOCKETPAIR andre@0: andre@0: extern PROsfd _PR_MD_SOCKET(int af, int type, int flags); andre@0: #define _PR_MD_SOCKET _MD_SOCKET andre@0: andre@0: extern PRInt32 _PR_MD_SOCKETAVAILABLE(PRFileDesc *fd); andre@0: #define _PR_MD_SOCKETAVAILABLE _MD_SOCKETAVAILABLE andre@0: andre@0: extern PRInt32 _PR_MD_PIPEAVAILABLE(PRFileDesc *fd); andre@0: #define _PR_MD_PIPEAVAILABLE _MD_PIPEAVAILABLE andre@0: andre@0: extern PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, andre@0: PRIntervalTime timeout); andre@0: #define _PR_MD_PR_POLL _MD_PR_POLL andre@0: andre@0: /* andre@0: * Initialize fd->secret->inheritable for a newly created fd. andre@0: * If 'imported' is false, the osfd (i.e., fd->secret->md.osfd) andre@0: * was created by NSPR and hence has the OS-dependent default andre@0: * inheritable attribute. If 'imported' is true, the osfd was andre@0: * not created by NSPR and hence a system call is required to andre@0: * query its inheritable attribute. Since we may never need to andre@0: * know the inheritable attribute of a fd, a platform may choose andre@0: * to initialize fd->secret->inheritable of an imported fd to andre@0: * _PR_TRI_UNKNOWN and only pay the cost of the system call andre@0: * (in _PR_MD_QUERY_FD_INHERITABLE) when necessary. andre@0: */ andre@0: extern void _PR_MD_INIT_FD_INHERITABLE(PRFileDesc *fd, PRBool imported); andre@0: #define _PR_MD_INIT_FD_INHERITABLE _MD_INIT_FD_INHERITABLE andre@0: andre@0: extern PRStatus _PR_MD_SET_FD_INHERITABLE(PRFileDesc *fd, PRBool inheritable); andre@0: #define _PR_MD_SET_FD_INHERITABLE _MD_SET_FD_INHERITABLE andre@0: andre@0: andre@0: #define _PR_PROCESS_TIMEOUT_INTERRUPT_ERRORS(me) \ andre@0: if (_PR_PENDING_INTERRUPT(me)) { \ andre@0: me->flags &= ~_PR_INTERRUPT; \ andre@0: PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0); \ andre@0: } else { \ andre@0: PR_SetError(PR_IO_TIMEOUT_ERROR, 0); \ andre@0: } andre@0: andre@0: extern void *_PR_MD_GET_SP(PRThread *thread); andre@0: #define _PR_MD_GET_SP _MD_GET_SP andre@0: andre@0: #endif /* defined(_PR_PTHREADS) */ andre@0: andre@0: /************************************************************************/ andre@0: /************************************************************************* andre@0: ** The remainder of the definitions are shared by pthreads and the classic andre@0: ** NSPR code. These too may be conditionalized. andre@0: *************************************************************************/ andre@0: /************************************************************************/ andre@0: andre@0: extern PROffset32 _PR_MD_LSEEK(PRFileDesc *fd, PROffset32 offset, PRSeekWhence whence); andre@0: #define _PR_MD_LSEEK _MD_LSEEK andre@0: andre@0: extern PROffset64 _PR_MD_LSEEK64(PRFileDesc *fd, PROffset64 offset, PRSeekWhence whence); andre@0: #define _PR_MD_LSEEK64 _MD_LSEEK64 andre@0: andre@0: extern PRInt32 _PR_MD_GETFILEINFO(const char *fn, PRFileInfo *info); andre@0: #define _PR_MD_GETFILEINFO _MD_GETFILEINFO andre@0: andre@0: extern PRInt32 _PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info); andre@0: #define _PR_MD_GETFILEINFO64 _MD_GETFILEINFO64 andre@0: andre@0: extern PRInt32 _PR_MD_GETOPENFILEINFO(const PRFileDesc *fd, PRFileInfo *info); andre@0: #define _PR_MD_GETOPENFILEINFO _MD_GETOPENFILEINFO andre@0: andre@0: extern PRInt32 _PR_MD_GETOPENFILEINFO64(const PRFileDesc *fd, PRFileInfo64 *info); andre@0: #define _PR_MD_GETOPENFILEINFO64 _MD_GETOPENFILEINFO64 andre@0: andre@0: andre@0: /*****************************************************************************/ andre@0: /************************** File descriptor caching **************************/ andre@0: /*****************************************************************************/ andre@0: extern void _PR_InitFdCache(void); andre@0: extern void _PR_CleanupFdCache(void); andre@0: extern PRFileDesc *_PR_Getfd(void); andre@0: extern void _PR_Putfd(PRFileDesc *fd); andre@0: andre@0: /* andre@0: * These flags are used by NSPR temporarily in the poll andre@0: * descriptor's out_flags field to record the mapping of andre@0: * NSPR's poll flags to the system poll flags. andre@0: * andre@0: * If _PR_POLL_READ_SYS_WRITE bit is set, it means the andre@0: * PR_POLL_READ flag specified by the topmost layer is andre@0: * mapped to the WRITE flag at the system layer. Similarly andre@0: * for the other three _PR_POLL_XXX_SYS_YYY flags. It is andre@0: * assumed that the PR_POLL_EXCEPT flag doesn't get mapped andre@0: * to other flags. andre@0: */ andre@0: #define _PR_POLL_READ_SYS_READ 0x1 andre@0: #define _PR_POLL_READ_SYS_WRITE 0x2 andre@0: #define _PR_POLL_WRITE_SYS_READ 0x4 andre@0: #define _PR_POLL_WRITE_SYS_WRITE 0x8 andre@0: andre@0: /* andre@0: ** These methods are coerced into file descriptor methods table andre@0: ** when the intended service is inappropriate for the particular andre@0: ** type of file descriptor. andre@0: */ andre@0: extern PRIntn _PR_InvalidInt(void); andre@0: extern PRInt16 _PR_InvalidInt16(void); andre@0: extern PRInt64 _PR_InvalidInt64(void); andre@0: extern PRStatus _PR_InvalidStatus(void); andre@0: extern PRFileDesc *_PR_InvalidDesc(void); andre@0: andre@0: extern PRIOMethods _pr_faulty_methods; andre@0: andre@0: /* andre@0: ** The PR_NETADDR_SIZE macro can only be called on a PRNetAddr union andre@0: ** whose 'family' field is set. It returns the size of the union andre@0: ** member corresponding to the specified address family. andre@0: */ andre@0: andre@0: extern PRUintn _PR_NetAddrSize(const PRNetAddr* addr); andre@0: andre@0: #if defined(_PR_INET6) andre@0: andre@0: #define PR_NETADDR_SIZE(_addr) _PR_NetAddrSize(_addr) andre@0: andre@0: #elif defined(_PR_HAVE_MD_SOCKADDR_IN6) andre@0: andre@0: /* andre@0: ** Under the following conditions: andre@0: ** 1. _PR_INET6 is not defined; andre@0: ** 2. _PR_INET6_PROBE is defined; andre@0: ** 3. struct sockaddr_in6 has nonstandard fields at the end andre@0: ** (e.g., on Solaris 8), andre@0: ** (_addr)->ipv6 is smaller than struct sockaddr_in6, and andre@0: ** hence we can't pass sizeof((_addr)->ipv6) to socket andre@0: ** functions such as connect because they would fail with andre@0: ** EINVAL. andre@0: ** andre@0: ** To pass the correct socket address length to socket andre@0: ** functions, define the macro _PR_HAVE_MD_SOCKADDR_IN6 and andre@0: ** define struct _md_sockaddr_in6 to be isomorphic to andre@0: ** struct sockaddr_in6. andre@0: */ andre@0: andre@0: #if defined(XP_UNIX) || defined(XP_OS2) andre@0: #define PR_NETADDR_SIZE(_addr) \ andre@0: ((_addr)->raw.family == PR_AF_INET \ andre@0: ? sizeof((_addr)->inet) \ andre@0: : ((_addr)->raw.family == PR_AF_INET6 \ andre@0: ? sizeof(struct _md_sockaddr_in6) \ andre@0: : sizeof((_addr)->local))) andre@0: #else andre@0: #define PR_NETADDR_SIZE(_addr) \ andre@0: ((_addr)->raw.family == PR_AF_INET \ andre@0: ? sizeof((_addr)->inet) \ andre@0: : sizeof(struct _md_sockaddr_in6)) andre@0: #endif /* defined(XP_UNIX) */ andre@0: andre@0: #else andre@0: andre@0: #if defined(XP_UNIX) || defined(XP_OS2) andre@0: #define PR_NETADDR_SIZE(_addr) \ andre@0: ((_addr)->raw.family == PR_AF_INET \ andre@0: ? sizeof((_addr)->inet) \ andre@0: : ((_addr)->raw.family == PR_AF_INET6 \ andre@0: ? sizeof((_addr)->ipv6) \ andre@0: : sizeof((_addr)->local))) andre@0: #else andre@0: #define PR_NETADDR_SIZE(_addr) \ andre@0: ((_addr)->raw.family == PR_AF_INET \ andre@0: ? sizeof((_addr)->inet) \ andre@0: : sizeof((_addr)->ipv6)) andre@0: #endif /* defined(XP_UNIX) */ andre@0: andre@0: #endif /* defined(_PR_INET6) */ andre@0: andre@0: extern PRStatus _PR_MapOptionName( andre@0: PRSockOption optname, PRInt32 *level, PRInt32 *name); andre@0: extern void _PR_InitThreads( andre@0: PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs); andre@0: andre@0: struct PRLock { andre@0: #if defined(_PR_PTHREADS) andre@0: pthread_mutex_t mutex; /* the underlying lock */ andre@0: _PT_Notified notified; /* array of conditions notified */ andre@0: PRBool locked; /* whether the mutex is locked */ andre@0: pthread_t owner; /* if locked, current lock owner */ andre@0: #elif defined(_PR_BTHREADS) andre@0: sem_id semaphoreID; /* the underlying lock */ andre@0: int32 benaphoreCount; /* number of people in lock */ andre@0: thread_id owner; /* current lock owner */ andre@0: #else /* not pthreads or Be threads */ andre@0: PRCList links; /* linkage for PRThread.lockList */ andre@0: struct PRThread *owner; /* current lock owner */ andre@0: PRCList waitQ; /* list of threads waiting for lock */ andre@0: PRThreadPriority priority; /* priority of lock */ andre@0: PRThreadPriority boostPriority; /* boosted priority of lock owner */ andre@0: _MDLock ilock; /* Internal Lock to protect user-level fields */ andre@0: #endif andre@0: }; andre@0: andre@0: struct PRCondVar { andre@0: PRLock *lock; /* associated lock that protects the condition */ andre@0: #if defined(_PR_PTHREADS) andre@0: pthread_cond_t cv; /* underlying pthreads condition */ andre@0: PRInt32 notify_pending; /* CV has destroy pending notification */ andre@0: #elif defined(_PR_BTHREADS) andre@0: sem_id sem; /* the underlying lock */ andre@0: sem_id handshakeSem; /* the lock for 'notify'-threads waiting for confirmation */ andre@0: sem_id signalSem; /* the lock for threads waiting for someone to notify */ andre@0: volatile int32 nw; /* the number waiting */ andre@0: volatile int32 ns; /* the number signalling */ andre@0: long signalBenCount; /* the number waiting on the underlying sem */ andre@0: #else /* not pthreads or Be threads */ andre@0: PRCList condQ; /* Condition variable wait Q */ andre@0: _MDLock ilock; /* Internal Lock to protect condQ */ andre@0: _MDCVar md; andre@0: #endif andre@0: }; andre@0: andre@0: /************************************************************************/ andre@0: andre@0: struct PRMonitor { andre@0: const char* name; /* monitor name for debugging */ andre@0: #if defined(_PR_PTHREADS) andre@0: pthread_mutex_t lock; /* lock is only held when accessing fields andre@0: * of the PRMonitor, instead of being held andre@0: * while the monitor is entered. The only andre@0: * exception is notifyTimes, which is andre@0: * protected by the monitor. */ andre@0: pthread_t owner; /* the owner of the monitor or invalid */ andre@0: pthread_cond_t entryCV; /* for threads waiting to enter the monitor */ andre@0: andre@0: pthread_cond_t waitCV; /* for threads waiting on the monitor */ andre@0: PRInt32 refCount; /* reference count, an atomic variable. andre@0: * PR_NewMonitor adds a reference to the andre@0: * newly created PRMonitor, and andre@0: * PR_DestroyMonitor releases that reference. andre@0: * PR_ExitMonitor adds a reference before andre@0: * unlocking the internal lock if it needs to andre@0: * signal entryCV, and releases the reference andre@0: * after signaling entryCV. */ andre@0: #else /* defined(_PR_PTHREADS) */ andre@0: PRLock lock; /* lock is only held when accessing fields andre@0: * of the PRMonitor, instead of being held andre@0: * while the monitor is entered. The only andre@0: * exception is notifyTimes, which is andre@0: * protected by the monitor. */ andre@0: PRThread *owner; /* the owner of the monitor or invalid */ andre@0: PRCondVar entryCV; /* for threads waiting to enter the monitor */ andre@0: andre@0: PRCondVar waitCV; /* for threads waiting on the monitor */ andre@0: #endif /* defined(_PR_PTHREADS) */ andre@0: PRUint32 entryCount; /* # of times re-entered */ andre@0: PRIntn notifyTimes; /* number of pending notifies for waitCV. andre@0: * The special value -1 means a broadcast andre@0: * (PR_NotifyAll). */ andre@0: }; andre@0: andre@0: /************************************************************************/ andre@0: andre@0: struct PRSemaphore { andre@0: #if defined(_PR_BTHREADS) andre@0: sem_id sem; andre@0: int32 benaphoreCount; andre@0: #else andre@0: PRCondVar *cvar; /* associated lock and condition variable queue */ andre@0: PRUintn count; /* the value of the counting semaphore */ andre@0: PRUint32 waiters; /* threads waiting on the semaphore */ andre@0: #if defined(_PR_PTHREADS) andre@0: #else /* defined(_PR_PTHREADS) */ andre@0: _MDSemaphore md; andre@0: #endif /* defined(_PR_PTHREADS) */ andre@0: #endif /* defined(_PR_BTHREADS) */ andre@0: }; andre@0: andre@0: /*************************************************************************/ andre@0: andre@0: struct PRSem { andre@0: #ifdef _PR_HAVE_POSIX_SEMAPHORES andre@0: sem_t *sem; andre@0: #elif defined(_PR_HAVE_SYSV_SEMAPHORES) andre@0: int semid; andre@0: #elif defined(WIN32) andre@0: HANDLE sem; andre@0: #else andre@0: PRInt8 notused; andre@0: #endif andre@0: }; andre@0: andre@0: /*************************************************************************/ andre@0: andre@0: struct PRStackStr { andre@0: /* head MUST be at offset 0; assembly language code relies on this */ andre@0: #if defined(AIX) andre@0: volatile PRStackElem prstk_head; andre@0: #else andre@0: PRStackElem prstk_head; andre@0: #endif andre@0: andre@0: PRLock *prstk_lock; andre@0: char *prstk_name; andre@0: }; andre@0: andre@0: /************************************************************************/ andre@0: andre@0: /* XXX this needs to be exported (sigh) */ andre@0: struct PRThreadStack { andre@0: PRCList links; andre@0: PRUintn flags; andre@0: andre@0: char *allocBase; /* base of stack's allocated memory */ andre@0: PRUint32 allocSize; /* size of stack's allocated memory */ andre@0: char *stackBottom; /* bottom of stack from C's point of view */ andre@0: char *stackTop; /* top of stack from C's point of view */ andre@0: PRUint32 stackSize; /* size of usable portion of the stack */ andre@0: andre@0: PRSegment *seg; andre@0: PRThread* thr; /* back pointer to thread owning this stack */ andre@0: andre@0: #if defined(_PR_PTHREADS) andre@0: #else /* defined(_PR_PTHREADS) */ andre@0: _MDThreadStack md; andre@0: #endif /* defined(_PR_PTHREADS) */ andre@0: }; andre@0: andre@0: extern void _PR_DestroyThreadPrivate(PRThread*); andre@0: andre@0: typedef void (PR_CALLBACK *_PRStartFn)(void *); andre@0: andre@0: struct PRThread { andre@0: PRUint32 state; /* thread's creation state */ andre@0: PRThreadPriority priority; /* apparent priority, loosly defined */ andre@0: andre@0: void *arg; /* argument to the client's entry point */ andre@0: _PRStartFn startFunc; /* the root of the client's thread */ andre@0: andre@0: PRThreadStack *stack; /* info about thread's stack (for GC) */ andre@0: void *environment; /* pointer to execution environment */ andre@0: andre@0: PRThreadDumpProc dump; /* dump thread info out */ andre@0: void *dumpArg; /* argument for the dump function */ andre@0: andre@0: /* andre@0: ** Per thread private data andre@0: */ andre@0: PRUint32 tpdLength; /* thread's current vector length */ andre@0: void **privateData; /* private data vector or NULL */ andre@0: PRErrorCode errorCode; /* current NSPR error code | zero */ andre@0: PRInt32 osErrorCode; /* mapping of errorCode | zero */ andre@0: PRIntn errorStringLength; /* textLength from last call to PR_SetErrorText() */ andre@0: PRInt32 errorStringSize; /* malloc()'d size of buffer | zero */ andre@0: char *errorString; /* current error string | NULL */ andre@0: char *name; /* thread's name */ andre@0: andre@0: #if defined(_PR_PTHREADS) andre@0: pthread_t id; /* pthread identifier for the thread */ andre@0: PRBool idSet; /* whether 'id' has been set. Protected by andre@0: * pt_book.ml. */ andre@0: #ifdef _PR_NICE_PRIORITY_SCHEDULING andre@0: pid_t tid; /* Linux-specific kernel thread ID */ andre@0: #endif andre@0: PRBool okToDelete; /* ok to delete the PRThread struct? */ andre@0: PRCondVar *waiting; /* where the thread is waiting | NULL */ andre@0: void *sp; /* recorded sp for garbage collection */ andre@0: PRThread *next, *prev; /* simple linked list of all threads */ andre@0: PRUint32 suspend; /* used to store suspend and resume flags */ andre@0: #ifdef PT_NO_SIGTIMEDWAIT andre@0: pthread_mutex_t suspendResumeMutex; andre@0: pthread_cond_t suspendResumeCV; andre@0: #endif andre@0: PRUint32 interrupt_blocked; /* interrupt blocked */ andre@0: struct pollfd *syspoll_list; /* Unix polling list used by PR_Poll */ andre@0: PRUint32 syspoll_count; /* number of elements in syspoll_list */ andre@0: #if defined(_PR_POLL_WITH_SELECT) andre@0: int *selectfd_list; /* Unix fd's that PR_Poll selects on */ andre@0: PRUint32 selectfd_count; /* number of elements in selectfd_list */ andre@0: #endif andre@0: #elif defined(_PR_BTHREADS) andre@0: PRUint32 flags; andre@0: _MDThread md; andre@0: PRBool io_pending; andre@0: PRInt32 io_fd; andre@0: PRBool io_suspended; andre@0: #else /* not pthreads or Be threads */ andre@0: _MDLock threadLock; /* Lock to protect thread state variables. andre@0: * Protects the following fields: andre@0: * state andre@0: * priority andre@0: * links andre@0: * wait andre@0: * cpu andre@0: */ andre@0: PRUint32 queueCount; andre@0: PRUint32 waitCount; andre@0: andre@0: PRCList active; /* on list of all active threads */ andre@0: PRCList links; andre@0: PRCList waitQLinks; /* when thread is PR_Wait'ing */ andre@0: PRCList lockList; /* list of locks currently holding */ andre@0: PRIntervalTime sleep; /* sleep time when thread is sleeping */ andre@0: struct _wait { andre@0: struct PRLock *lock; andre@0: struct PRCondVar *cvar; andre@0: } wait; andre@0: andre@0: PRUint32 id; andre@0: PRUint32 flags; andre@0: PRUint32 no_sched; /* Don't schedule the thread to run. andre@0: * This flag has relevance only when andre@0: * multiple NSPR CPUs are created. andre@0: * When a thread is de-scheduled, there andre@0: * is a narrow window of time in which andre@0: * the thread is put on the run queue andre@0: * but the scheduler is actually using andre@0: * the stack of this thread. It is safe andre@0: * to run this thread on a different CPU andre@0: * only when its stack is not in use on andre@0: * any other CPU. The no_sched flag is andre@0: * set during this interval to prevent andre@0: * the thread from being scheduled on a andre@0: * different CPU. andre@0: */ andre@0: andre@0: /* thread termination condition variable for join */ andre@0: PRCondVar *term; andre@0: andre@0: _PRCPU *cpu; /* cpu to which this thread is bound */ andre@0: PRUint32 threadAllocatedOnStack;/* boolean */ andre@0: andre@0: /* When an async IO is in progress and a second async IO cannot be andre@0: * initiated, the io_pending flag is set to true. Some platforms will andre@0: * not use the io_pending flag. If the io_pending flag is true, then andre@0: * io_fd is the OS-file descriptor on which IO is pending. andre@0: */ andre@0: PRBool io_pending; andre@0: PRInt32 io_fd; andre@0: andre@0: /* If a timeout occurs or if an outstanding IO is interrupted and the andre@0: * OS doesn't support a real cancellation (NT or MAC), then the andre@0: * io_suspended flag will be set to true. The thread will be resumed andre@0: * but may run into trouble issuing additional IOs until the io_pending andre@0: * flag can be cleared andre@0: */ andre@0: PRBool io_suspended; andre@0: andre@0: _MDThread md; andre@0: #endif andre@0: }; andre@0: andre@0: struct PRProcessAttr { andre@0: PRFileDesc *stdinFd; andre@0: PRFileDesc *stdoutFd; andre@0: PRFileDesc *stderrFd; andre@0: char *currentDirectory; andre@0: char *fdInheritBuffer; andre@0: PRSize fdInheritBufferSize; andre@0: PRSize fdInheritBufferUsed; andre@0: }; andre@0: andre@0: struct PRProcess { andre@0: _MDProcess md; andre@0: }; andre@0: andre@0: struct PRFileMap { andre@0: PRFileDesc *fd; andre@0: PRFileMapProtect prot; andre@0: _MDFileMap md; andre@0: }; andre@0: andre@0: /************************************************************************/ andre@0: andre@0: /* andre@0: ** File descriptors of the NSPR layer can be in one of the andre@0: ** following states (stored in the 'state' field of struct andre@0: ** PRFilePrivate): andre@0: ** - _PR_FILEDESC_OPEN: The OS fd is open. andre@0: ** - _PR_FILEDESC_CLOSED: The OS fd is closed. The PRFileDesc andre@0: ** is still open but is unusable. The only operation allowed andre@0: ** on the PRFileDesc is PR_Close(). andre@0: ** - _PR_FILEDESC_FREED: The OS fd is closed and the PRFileDesc andre@0: ** structure is freed. andre@0: */ andre@0: andre@0: #define _PR_FILEDESC_OPEN 0xaaaaaaaa /* 1010101... */ andre@0: #define _PR_FILEDESC_CLOSED 0x55555555 /* 0101010... */ andre@0: #define _PR_FILEDESC_FREED 0x11111111 andre@0: andre@0: /* andre@0: ** A boolean type with an additional "unknown" state andre@0: */ andre@0: andre@0: typedef enum { andre@0: _PR_TRI_TRUE = 1, andre@0: _PR_TRI_FALSE = 0, andre@0: _PR_TRI_UNKNOWN = -1 andre@0: } _PRTriStateBool; andre@0: andre@0: struct PRFilePrivate { andre@0: PRInt32 state; andre@0: PRBool nonblocking; andre@0: _PRTriStateBool inheritable; andre@0: PRFileDesc *next; andre@0: PRIntn lockCount; /* 0: not locked andre@0: * -1: a native lockfile call is in progress andre@0: * > 0: # times the file is locked */ andre@0: #ifdef _PR_HAVE_PEEK_BUFFER andre@0: char *peekBuffer; andre@0: PRInt32 peekBufSize; andre@0: PRInt32 peekBytes; andre@0: #endif andre@0: #if !defined(_PR_HAVE_O_APPEND) andre@0: PRBool appendMode; /* Some platforms don't have O_APPEND or its andre@0: * equivalent, so they have to seek to end of andre@0: * file on write if the file was opened in andre@0: * append mode. See Bugzilla 4090, 276330. */ andre@0: #endif andre@0: _MDFileDesc md; andre@0: #ifdef _PR_NEED_SECRET_AF andre@0: PRUint16 af; /* If the platform's implementation of accept() andre@0: * requires knowing the address family of the andre@0: * socket, we save the address family here. */ andre@0: #endif andre@0: }; andre@0: andre@0: #ifdef _WIN64 andre@0: #define PR_PRIdOSFD "lld" /* for printing PROsfd */ andre@0: #define PR_PRIxOSFD "llx" andre@0: #define PR_SCNdOSFD "lld" /* for scanning PROsfd */ andre@0: #define PR_SCNxOSFD "llx" andre@0: #else andre@0: #define PR_PRIdOSFD "ld" /* for printing PROsfd */ andre@0: #define PR_PRIxOSFD "lx" andre@0: #define PR_SCNdOSFD "ld" /* for scanning PROsfd */ andre@0: #define PR_SCNxOSFD "lx" andre@0: #endif andre@0: andre@0: struct PRDir { andre@0: PRDirEntry d; andre@0: _MDDir md; andre@0: }; andre@0: andre@0: #ifdef MOZ_UNICODE andre@0: struct PRDirUTF16 { andre@0: PRDirEntry d; andre@0: _MDDirUTF16 md; andre@0: }; andre@0: #endif /* MOZ_UNICODE */ andre@0: andre@0: extern void _PR_InitLocks(void); andre@0: extern void _PR_InitSegs(void); andre@0: extern void _PR_InitStacks(void); andre@0: extern void _PR_InitTPD(void); andre@0: extern void _PR_InitMem(void); andre@0: extern void _PR_InitEnv(void); andre@0: extern void _PR_InitCMon(void); andre@0: extern void _PR_InitIO(void); andre@0: extern void _PR_InitLog(void); andre@0: extern void _PR_InitNet(void); andre@0: extern void _PR_InitClock(void); andre@0: extern void _PR_InitLinker(void); andre@0: extern void _PR_InitAtomic(void); andre@0: extern void _PR_InitCPUs(void); andre@0: extern void _PR_InitDtoa(void); andre@0: extern void _PR_InitTime(void); andre@0: extern void _PR_InitMW(void); andre@0: extern void _PR_InitRWLocks(void); andre@0: extern void _PR_CleanupThread(PRThread *thread); andre@0: extern void _PR_CleanupCallOnce(void); andre@0: extern void _PR_CleanupMW(void); andre@0: extern void _PR_CleanupTime(void); andre@0: extern void _PR_CleanupDtoa(void); andre@0: extern void _PR_ShutdownLinker(void); andre@0: extern void _PR_CleanupEnv(void); andre@0: extern void _PR_CleanupIO(void); andre@0: extern void _PR_CleanupCMon(void); andre@0: extern void _PR_CleanupNet(void); andre@0: extern void _PR_CleanupLayerCache(void); andre@0: extern void _PR_CleanupStacks(void); andre@0: #ifdef WINNT andre@0: extern void _PR_CleanupCPUs(void); andre@0: #endif andre@0: extern void _PR_CleanupThreads(void); andre@0: extern void _PR_CleanupTPD(void); andre@0: extern void _PR_Cleanup(void); andre@0: extern void _PR_LogCleanup(void); andre@0: extern void _PR_InitLayerCache(void); andre@0: andre@0: extern PRBool _pr_initialized; andre@0: extern void _PR_ImplicitInitialization(void); andre@0: extern PRBool _PR_Obsolete(const char *obsolete, const char *preferred); andre@0: andre@0: /************************************************************************/ andre@0: andre@0: struct PRSegment { andre@0: void *vaddr; andre@0: PRUint32 size; andre@0: PRUintn flags; andre@0: #if defined(_PR_PTHREADS) andre@0: #else /* defined(_PR_PTHREADS) */ andre@0: _MDSegment md; andre@0: #endif /* defined(_PR_PTHREADS) */ andre@0: }; andre@0: andre@0: /* PRSegment.flags */ andre@0: #define _PR_SEG_VM 0x1 andre@0: andre@0: /************************************************************************/ andre@0: andre@0: extern PRInt32 _pr_pageSize; andre@0: extern PRInt32 _pr_pageShift; andre@0: andre@0: extern PRLogModuleInfo *_pr_clock_lm; andre@0: extern PRLogModuleInfo *_pr_cmon_lm; andre@0: extern PRLogModuleInfo *_pr_io_lm; andre@0: extern PRLogModuleInfo *_pr_cvar_lm; andre@0: extern PRLogModuleInfo *_pr_mon_lm; andre@0: extern PRLogModuleInfo *_pr_linker_lm; andre@0: extern PRLogModuleInfo *_pr_sched_lm; andre@0: extern PRLogModuleInfo *_pr_thread_lm; andre@0: extern PRLogModuleInfo *_pr_gc_lm; andre@0: andre@0: extern PRFileDesc *_pr_stdin; andre@0: extern PRFileDesc *_pr_stdout; andre@0: extern PRFileDesc *_pr_stderr; andre@0: andre@0: /* Zone allocator */ andre@0: /* andre@0: ** The zone allocator code has hardcoded pthread types and andre@0: ** functions, so it can only be used in the pthreads version. andre@0: ** This can be fixed by replacing the hardcoded pthread types andre@0: ** and functions with macros that expand to the native thread andre@0: ** types and functions on each platform. andre@0: */ andre@0: #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) andre@0: #define _PR_ZONE_ALLOCATOR andre@0: #endif andre@0: andre@0: #ifdef _PR_ZONE_ALLOCATOR andre@0: extern void _PR_InitZones(void); andre@0: extern void _PR_DestroyZones(void); andre@0: #endif andre@0: andre@0: /* Overriding malloc, free, etc. */ andre@0: #if !defined(_PR_NO_PREEMPT) && defined(XP_UNIX) \ andre@0: && !defined(_PR_PTHREADS) && !defined(_PR_GLOBAL_THREADS_ONLY) \ andre@0: && !defined(PURIFY) \ andre@0: && !defined(DARWIN) \ andre@0: && !defined(QNX) \ andre@0: && !(defined (UNIXWARE) && defined (USE_SVR4_THREADS)) andre@0: #define _PR_OVERRIDE_MALLOC andre@0: #endif andre@0: andre@0: /************************************************************************* andre@0: * External machine-dependent code provided by each OS. * * andre@0: *************************************************************************/ andre@0: andre@0: /* Initialization related */ andre@0: extern void _PR_MD_EARLY_INIT(void); andre@0: #define _PR_MD_EARLY_INIT _MD_EARLY_INIT andre@0: andre@0: extern void _PR_MD_INTERVAL_INIT(void); andre@0: #define _PR_MD_INTERVAL_INIT _MD_INTERVAL_INIT andre@0: andre@0: NSPR_API(void) _PR_MD_FINAL_INIT(void); andre@0: #define _PR_MD_FINAL_INIT _MD_FINAL_INIT andre@0: andre@0: extern void _PR_MD_EARLY_CLEANUP(void); andre@0: #define _PR_MD_EARLY_CLEANUP _MD_EARLY_CLEANUP andre@0: andre@0: /* Process control */ andre@0: andre@0: extern PRProcess * _PR_MD_CREATE_PROCESS( andre@0: const char *path, andre@0: char *const *argv, andre@0: char *const *envp, andre@0: const PRProcessAttr *attr); andre@0: #define _PR_MD_CREATE_PROCESS _MD_CREATE_PROCESS andre@0: andre@0: extern PRStatus _PR_MD_DETACH_PROCESS(PRProcess *process); andre@0: #define _PR_MD_DETACH_PROCESS _MD_DETACH_PROCESS andre@0: andre@0: extern PRStatus _PR_MD_WAIT_PROCESS(PRProcess *process, PRInt32 *exitCode); andre@0: #define _PR_MD_WAIT_PROCESS _MD_WAIT_PROCESS andre@0: andre@0: extern PRStatus _PR_MD_KILL_PROCESS(PRProcess *process); andre@0: #define _PR_MD_KILL_PROCESS _MD_KILL_PROCESS andre@0: andre@0: /* Current Time */ andre@0: NSPR_API(PRTime) _PR_MD_NOW(void); andre@0: #define _PR_MD_NOW _MD_NOW andre@0: andre@0: /* Environment related */ andre@0: extern char* _PR_MD_GET_ENV(const char *name); andre@0: #define _PR_MD_GET_ENV _MD_GET_ENV andre@0: andre@0: extern PRIntn _PR_MD_PUT_ENV(const char *name); andre@0: #define _PR_MD_PUT_ENV _MD_PUT_ENV andre@0: andre@0: /* Atomic operations */ andre@0: andre@0: extern void _PR_MD_INIT_ATOMIC(void); andre@0: #define _PR_MD_INIT_ATOMIC _MD_INIT_ATOMIC andre@0: andre@0: extern PRInt32 _PR_MD_ATOMIC_INCREMENT(PRInt32 *); andre@0: #define _PR_MD_ATOMIC_INCREMENT _MD_ATOMIC_INCREMENT andre@0: andre@0: extern PRInt32 _PR_MD_ATOMIC_ADD(PRInt32 *, PRInt32); andre@0: #define _PR_MD_ATOMIC_ADD _MD_ATOMIC_ADD andre@0: andre@0: extern PRInt32 _PR_MD_ATOMIC_DECREMENT(PRInt32 *); andre@0: #define _PR_MD_ATOMIC_DECREMENT _MD_ATOMIC_DECREMENT andre@0: andre@0: extern PRInt32 _PR_MD_ATOMIC_SET(PRInt32 *, PRInt32); andre@0: #define _PR_MD_ATOMIC_SET _MD_ATOMIC_SET andre@0: andre@0: /* Garbage collection */ andre@0: andre@0: /* andre@0: ** Save the registers that the GC would find interesting into the thread andre@0: ** "t". isCurrent will be non-zero if the thread state that is being andre@0: ** saved is the currently executing thread. Return the address of the andre@0: ** first register to be scanned as well as the number of registers to andre@0: ** scan in "np". andre@0: ** andre@0: ** If "isCurrent" is non-zero then it is allowed for the thread context andre@0: ** area to be used as scratch storage to hold just the registers andre@0: ** necessary for scanning. andre@0: */ andre@0: extern PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np); andre@0: andre@0: /* Time intervals */ andre@0: andre@0: extern PRIntervalTime _PR_MD_GET_INTERVAL(void); andre@0: #define _PR_MD_GET_INTERVAL _MD_GET_INTERVAL andre@0: andre@0: extern PRIntervalTime _PR_MD_INTERVAL_PER_SEC(void); andre@0: #define _PR_MD_INTERVAL_PER_SEC _MD_INTERVAL_PER_SEC andre@0: andre@0: /* Affinity masks */ andre@0: andre@0: extern PRInt32 _PR_MD_SETTHREADAFFINITYMASK(PRThread *thread, PRUint32 mask ); andre@0: #define _PR_MD_SETTHREADAFFINITYMASK _MD_SETTHREADAFFINITYMASK andre@0: andre@0: extern PRInt32 _PR_MD_GETTHREADAFFINITYMASK(PRThread *thread, PRUint32 *mask); andre@0: #define _PR_MD_GETTHREADAFFINITYMASK _MD_GETTHREADAFFINITYMASK andre@0: andre@0: /* File locking */ andre@0: andre@0: extern PRStatus _PR_MD_LOCKFILE(PROsfd osfd); andre@0: #define _PR_MD_LOCKFILE _MD_LOCKFILE andre@0: andre@0: extern PRStatus _PR_MD_TLOCKFILE(PROsfd osfd); andre@0: #define _PR_MD_TLOCKFILE _MD_TLOCKFILE andre@0: andre@0: extern PRStatus _PR_MD_UNLOCKFILE(PROsfd osfd); andre@0: #define _PR_MD_UNLOCKFILE _MD_UNLOCKFILE andre@0: andre@0: /* Memory-mapped files */ andre@0: andre@0: extern PRStatus _PR_MD_CREATE_FILE_MAP(PRFileMap *fmap, PRInt64 size); andre@0: #define _PR_MD_CREATE_FILE_MAP _MD_CREATE_FILE_MAP andre@0: andre@0: extern PRInt32 _PR_MD_GET_MEM_MAP_ALIGNMENT(void); andre@0: #define _PR_MD_GET_MEM_MAP_ALIGNMENT _MD_GET_MEM_MAP_ALIGNMENT andre@0: andre@0: extern void * _PR_MD_MEM_MAP( andre@0: PRFileMap *fmap, andre@0: PROffset64 offset, andre@0: PRUint32 len); andre@0: #define _PR_MD_MEM_MAP _MD_MEM_MAP andre@0: andre@0: extern PRStatus _PR_MD_MEM_UNMAP(void *addr, PRUint32 size); andre@0: #define _PR_MD_MEM_UNMAP _MD_MEM_UNMAP andre@0: andre@0: extern PRStatus _PR_MD_CLOSE_FILE_MAP(PRFileMap *fmap); andre@0: #define _PR_MD_CLOSE_FILE_MAP _MD_CLOSE_FILE_MAP andre@0: andre@0: extern PRStatus _PR_MD_SYNC_MEM_MAP( andre@0: PRFileDesc *fd, andre@0: void *addr, andre@0: PRUint32 len); andre@0: #define _PR_MD_SYNC_MEM_MAP _MD_SYNC_MEM_MAP andre@0: andre@0: /* Named Shared Memory */ andre@0: andre@0: /* andre@0: ** Declare PRSharedMemory. andre@0: */ andre@0: struct PRSharedMemory andre@0: { andre@0: char *ipcname; /* after conversion to native */ andre@0: PRSize size; /* from open */ andre@0: PRIntn mode; /* from open */ andre@0: PRIntn flags; /* from open */ andre@0: #if defined(PR_HAVE_POSIX_NAMED_SHARED_MEMORY) andre@0: int id; andre@0: #elif defined(PR_HAVE_SYSV_NAMED_SHARED_MEMORY) andre@0: int id; andre@0: #elif defined(PR_HAVE_WIN32_NAMED_SHARED_MEMORY) andre@0: HANDLE handle; andre@0: #else andre@0: PRUint32 nothing; /* placeholder, nothing behind here */ andre@0: #endif andre@0: PRUint32 ident; /* guard word at end of struct */ andre@0: #define _PR_SHM_IDENT 0xdeadbad andre@0: }; andre@0: andre@0: extern PRSharedMemory * _MD_OpenSharedMemory( andre@0: const char *name, andre@0: PRSize size, andre@0: PRIntn flags, andre@0: PRIntn mode andre@0: ); andre@0: #define _PR_MD_OPEN_SHARED_MEMORY _MD_OpenSharedMemory andre@0: andre@0: extern void * _MD_AttachSharedMemory( PRSharedMemory *shm, PRIntn flags ); andre@0: #define _PR_MD_ATTACH_SHARED_MEMORY _MD_AttachSharedMemory andre@0: andre@0: extern PRStatus _MD_DetachSharedMemory( PRSharedMemory *shm, void *addr ); andre@0: #define _PR_MD_DETACH_SHARED_MEMORY _MD_DetachSharedMemory andre@0: andre@0: extern PRStatus _MD_CloseSharedMemory( PRSharedMemory *shm ); andre@0: #define _PR_MD_CLOSE_SHARED_MEMORY _MD_CloseSharedMemory andre@0: andre@0: extern PRStatus _MD_DeleteSharedMemory( const char *name ); andre@0: #define _PR_MD_DELETE_SHARED_MEMORY _MD_DeleteSharedMemory andre@0: andre@0: extern PRFileMap* _md_OpenAnonFileMap( andre@0: const char *dirName, andre@0: PRSize size, andre@0: PRFileMapProtect prot andre@0: ); andre@0: #define _PR_MD_OPEN_ANON_FILE_MAP _md_OpenAnonFileMap andre@0: andre@0: extern PRStatus _md_ExportFileMapAsString( andre@0: PRFileMap *fm, andre@0: PRSize bufSize, andre@0: char *buf andre@0: ); andre@0: #define _PR_MD_EXPORT_FILE_MAP_AS_STRING _md_ExportFileMapAsString andre@0: andre@0: extern PRFileMap * _md_ImportFileMapFromString( andre@0: const char *fmstring andre@0: ); andre@0: #define _PR_MD_IMPORT_FILE_MAP_FROM_STRING _md_ImportFileMapFromString andre@0: andre@0: andre@0: andre@0: /* Interprocess communications (IPC) */ andre@0: andre@0: /* andre@0: * The maximum length of an NSPR IPC name, including the andre@0: * terminating null byte. andre@0: */ andre@0: #define PR_IPC_NAME_SIZE 1024 andre@0: andre@0: /* andre@0: * Types of NSPR IPC objects andre@0: */ andre@0: typedef enum { andre@0: _PRIPCSem, /* semaphores */ andre@0: _PRIPCShm /* shared memory segments */ andre@0: } _PRIPCType; andre@0: andre@0: /* andre@0: * Make a native IPC name from an NSPR IPC name. andre@0: */ andre@0: extern PRStatus _PR_MakeNativeIPCName( andre@0: const char *name, /* NSPR IPC name */ andre@0: char *result, /* result buffer */ andre@0: PRIntn size, /* size of result buffer */ andre@0: _PRIPCType type /* type of IPC object */ andre@0: ); andre@0: andre@0: /* Socket call error code */ andre@0: andre@0: NSPR_API(PRInt32) _PR_MD_GET_SOCKET_ERROR(void); andre@0: #define _PR_MD_GET_SOCKET_ERROR _MD_GET_SOCKET_ERROR andre@0: andre@0: /* Get name of current host */ andre@0: extern PRStatus _PR_MD_GETHOSTNAME(char *name, PRUint32 namelen); andre@0: #define _PR_MD_GETHOSTNAME _MD_GETHOSTNAME andre@0: andre@0: extern PRStatus _PR_MD_GETSYSINFO(PRSysInfo cmd, char *name, PRUint32 namelen); andre@0: #define _PR_MD_GETSYSINFO _MD_GETSYSINFO andre@0: andre@0: /* File descriptor inheritance */ andre@0: andre@0: /* andre@0: * If fd->secret->inheritable is _PR_TRI_UNKNOWN and we need to andre@0: * know the inheritable attribute of the fd, call this function andre@0: * to find that out. This typically requires a system call. andre@0: */ andre@0: extern void _PR_MD_QUERY_FD_INHERITABLE(PRFileDesc *fd); andre@0: #define _PR_MD_QUERY_FD_INHERITABLE _MD_QUERY_FD_INHERITABLE andre@0: andre@0: /* --- PR_GetRandomNoise() related things --- */ andre@0: andre@0: extern PRSize _PR_MD_GetRandomNoise( void *buf, PRSize size ); andre@0: #define _PR_MD_GET_RANDOM_NOISE(buf,size) _PR_MD_GetRandomNoise((buf),(size)) andre@0: extern PRSize _pr_CopyLowBits( void *dest, PRSize dstlen, void *src, PRSize srclen ); andre@0: andre@0: /* end PR_GetRandomNoise() related */ andre@0: andre@0: #ifdef XP_BEOS andre@0: andre@0: extern PRLock *_connectLock; andre@0: andre@0: typedef struct _ConnectListNode { andre@0: PRInt32 osfd; andre@0: PRNetAddr addr; andre@0: PRUint32 addrlen; andre@0: PRIntervalTime timeout; andre@0: } ConnectListNode; andre@0: andre@0: extern ConnectListNode connectList[64]; andre@0: andre@0: extern PRUint32 connectCount; andre@0: andre@0: #endif /* XP_BEOS */ andre@0: andre@0: PR_END_EXTERN_C andre@0: andre@0: #endif /* primpl_h___ */