tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

primpl.h (74196B)


      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 #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 #define PT_THREAD_DETACHED  0x01    /* thread can't be joined */
    139 #define PT_THREAD_GLOBAL    0x02    /* a global thread (unlikely) */
    140 #define PT_THREAD_SYSTEM    0x04    /* system (not user) thread */
    141 #define PT_THREAD_PRIMORD   0x08    /* this is the primordial thread */
    142 #define PT_THREAD_ABORTED   0x10    /* thread has been interrupted */
    143 #define PT_THREAD_GCABLE    0x20    /* thread is garbage collectible */
    144 #define PT_THREAD_SUSPENDED 0x40    /* thread has been suspended */
    145 #define PT_THREAD_FOREIGN   0x80    /* thread is not one of ours */
    146 #define PT_THREAD_BOUND     0x100    /* a bound-global thread */
    147 
    148 #define _PT_THREAD_INTERRUPTED(thr)                 \
    149        (!(thr->interrupt_blocked) && (thr->state & PT_THREAD_ABORTED))
    150 #define _PT_THREAD_BLOCK_INTERRUPT(thr)             \
    151        (thr->interrupt_blocked = 1)
    152 #define _PT_THREAD_UNBLOCK_INTERRUPT(thr)           \
    153        (thr->interrupt_blocked = 0)
    154 
    155 #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 #define PT_THREAD_RESUMED   0x80    /* thread has been resumed */
    164 #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 #define    _PR_MD_LSEEK _MD_LSEEK
   1276 
   1277 extern PROffset64 _PR_MD_LSEEK64(PRFileDesc *fd, PROffset64 offset, PRSeekWhence whence);
   1278 #define    _PR_MD_LSEEK64 _MD_LSEEK64
   1279 
   1280 extern PRInt32 _PR_MD_GETFILEINFO(const char *fn, PRFileInfo *info);
   1281 #define _PR_MD_GETFILEINFO _MD_GETFILEINFO
   1282 
   1283 extern PRInt32 _PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info);
   1284 #define _PR_MD_GETFILEINFO64 _MD_GETFILEINFO64
   1285 
   1286 extern PRInt32 _PR_MD_GETOPENFILEINFO(const PRFileDesc *fd, PRFileInfo *info);
   1287 #define _PR_MD_GETOPENFILEINFO _MD_GETOPENFILEINFO
   1288 
   1289 extern PRInt32 _PR_MD_GETOPENFILEINFO64(const PRFileDesc *fd, PRFileInfo64 *info);
   1290 #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 #define _PR_POLL_READ_SYS_READ     0x1
   1314 #define _PR_POLL_READ_SYS_WRITE    0x2
   1315 #define _PR_POLL_WRITE_SYS_READ    0x4
   1316 #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 #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 #elif defined(_PR_BTHREADS)
   1593    PRUint32 flags;
   1594    _MDThread md;
   1595    PRBool io_pending;
   1596    PRInt32 io_fd;
   1597    PRBool io_suspended;
   1598 #else /* not pthreads or Be threads */
   1599    _MDLock threadLock;             /* Lock to protect thread state variables.
   1600                                     * Protects the following fields:
   1601                                     *     state
   1602                                     *     priority
   1603                                     *     links
   1604                                     *     wait
   1605                                     *     cpu
   1606                                     */
   1607    PRUint32 queueCount;
   1608    PRUint32 waitCount;
   1609 
   1610    PRCList active;                 /* on list of all active threads        */
   1611    PRCList links;
   1612    PRCList waitQLinks;             /* when thread is PR_Wait'ing */
   1613    PRCList lockList;               /* list of locks currently holding */
   1614    PRIntervalTime sleep;           /* sleep time when thread is sleeping */
   1615    struct _wait {
   1616        struct PRLock *lock;
   1617        struct PRCondVar *cvar;
   1618    } wait;
   1619 
   1620    PRUint32 id;
   1621    PRUint32 flags;
   1622    PRUint32 no_sched;              /* Don't schedule the thread to run.
   1623                                     * This flag has relevance only when
   1624                                     * multiple NSPR CPUs are created.
   1625                                     * When a thread is de-scheduled, there
   1626                                     * is a narrow window of time in which
   1627                                     * the thread is put on the run queue
   1628                                     * but the scheduler is actually using
   1629                                     * the stack of this thread.  It is safe
   1630                                     * to run this thread on a different CPU
   1631                                     * only when its stack is not in use on
   1632                                     * any other CPU.  The no_sched flag is
   1633                                     * set during this interval to prevent
   1634                                     * the thread from being scheduled on a
   1635                                     * different CPU.
   1636                                     */
   1637 
   1638    /* thread termination condition variable for join */
   1639    PRCondVar *term;
   1640 
   1641    _PRCPU *cpu;                    /* cpu to which this thread is bound    */
   1642    PRUint32 threadAllocatedOnStack;/* boolean */
   1643 
   1644    /* When an async IO is in progress and a second async IO cannot be
   1645     * initiated, the io_pending flag is set to true.  Some platforms will
   1646     * not use the io_pending flag.  If the io_pending flag is true, then
   1647     * io_fd is the OS-file descriptor on which IO is pending.
   1648     */
   1649    PRBool io_pending;
   1650    PRInt32 io_fd;
   1651 
   1652    /* If a timeout occurs or if an outstanding IO is interrupted and the
   1653     * OS doesn't support a real cancellation (NT or MAC), then the
   1654     * io_suspended flag will be set to true.  The thread will be resumed
   1655     * but may run into trouble issuing additional IOs until the io_pending
   1656     * flag can be cleared
   1657     */
   1658    PRBool io_suspended;
   1659 
   1660    _MDThread md;
   1661 #endif
   1662 };
   1663 
   1664 struct PRProcessAttr {
   1665    PRFileDesc *stdinFd;
   1666    PRFileDesc *stdoutFd;
   1667    PRFileDesc *stderrFd;
   1668    char *currentDirectory;
   1669    char *fdInheritBuffer;
   1670    PRSize fdInheritBufferSize;
   1671    PRSize fdInheritBufferUsed;
   1672 };
   1673 
   1674 struct PRProcess {
   1675    _MDProcess md;
   1676 };
   1677 
   1678 struct PRFileMap {
   1679    PRFileDesc *fd;
   1680    PRFileMapProtect prot;
   1681    _MDFileMap md;
   1682 };
   1683 
   1684 /************************************************************************/
   1685 
   1686 /*
   1687 ** File descriptors of the NSPR layer can be in one of the
   1688 ** following states (stored in the 'state' field of struct
   1689 ** PRFilePrivate):
   1690 ** - _PR_FILEDESC_OPEN: The OS fd is open.
   1691 ** - _PR_FILEDESC_CLOSED: The OS fd is closed.  The PRFileDesc
   1692 **   is still open but is unusable.  The only operation allowed
   1693 **   on the PRFileDesc is PR_Close().
   1694 ** - _PR_FILEDESC_FREED: The OS fd is closed and the PRFileDesc
   1695 **   structure is freed.
   1696 */
   1697 
   1698 #define _PR_FILEDESC_OPEN       0xaaaaaaaa    /* 1010101... */
   1699 #define _PR_FILEDESC_CLOSED     0x55555555    /* 0101010... */
   1700 #define _PR_FILEDESC_FREED      0x11111111
   1701 
   1702 /*
   1703 ** A boolean type with an additional "unknown" state
   1704 */
   1705 
   1706 typedef enum {
   1707    _PR_TRI_TRUE = 1,
   1708    _PR_TRI_FALSE = 0,
   1709    _PR_TRI_UNKNOWN = -1
   1710 } _PRTriStateBool;
   1711 
   1712 struct PRFilePrivate {
   1713    PRInt32 state;
   1714    PRBool nonblocking;
   1715    _PRTriStateBool inheritable;
   1716    PRFileDesc *next;
   1717    PRIntn lockCount;   /*   0: not locked
   1718                         *  -1: a native lockfile call is in progress
   1719                         * > 0: # times the file is locked */
   1720 #ifdef _PR_HAVE_PEEK_BUFFER
   1721    char *peekBuffer;
   1722    PRInt32 peekBufSize;
   1723    PRInt32 peekBytes;
   1724 #endif
   1725 #if !defined(_PR_HAVE_O_APPEND)
   1726    PRBool  appendMode; /* Some platforms don't have O_APPEND or its
   1727                         * equivalent, so they have to seek to end of
   1728                         * file on write if the file was opened in
   1729                         * append mode.  See Bugzilla 4090, 276330. */
   1730 #endif
   1731    _MDFileDesc md;
   1732 #ifdef _PR_NEED_SECRET_AF
   1733    PRUint16 af;        /* If the platform's implementation of accept()
   1734                         * requires knowing the address family of the
   1735             * socket, we save the address family here. */
   1736 #endif
   1737 
   1738 #if defined(_WIN64)
   1739    /* This is necessary for TCP Fast Open. TCP Fast Open in windows must
   1740     * use ConnectEx function which uses OVERLAPPED. TCPSendTo will call
   1741     * ConnectEx to send fast open data. If ConnectEx returns
   1742     * ERROR_IO_PENDING we need to save OVERLAPPED structure and we will
   1743     * use it in ConnectContinue to get the final result of ConnectEx.
   1744     */
   1745    PRBool alreadyConnected;
   1746    PRBool overlappedActive;
   1747    OVERLAPPED ol;
   1748 #endif
   1749 };
   1750 
   1751 #ifdef _WIN64
   1752 #define PR_PRIdOSFD "lld"       /* for printing PROsfd */
   1753 #define PR_PRIxOSFD "llx"
   1754 #define PR_SCNdOSFD "lld"       /* for scanning PROsfd */
   1755 #define PR_SCNxOSFD "llx"
   1756 #else
   1757 #define PR_PRIdOSFD "ld"        /* for printing PROsfd */
   1758 #define PR_PRIxOSFD "lx"
   1759 #define PR_SCNdOSFD "ld"        /* for scanning PROsfd */
   1760 #define PR_SCNxOSFD "lx"
   1761 #endif
   1762 
   1763 struct PRDir {
   1764    PRDirEntry d;
   1765    _MDDir md;
   1766 };
   1767 
   1768 #ifdef MOZ_UNICODE
   1769 struct PRDirUTF16 {
   1770    PRDirEntry d;
   1771    _MDDirUTF16 md;
   1772 };
   1773 #endif /* MOZ_UNICODE */
   1774 
   1775 extern void _PR_InitLocks(void);
   1776 extern void _PR_InitSegs(void);
   1777 extern void _PR_InitStacks(void);
   1778 extern void _PR_InitTPD(void);
   1779 extern void _PR_InitMem(void);
   1780 extern void _PR_InitEnv(void);
   1781 extern void _PR_InitCMon(void);
   1782 extern void _PR_InitIO(void);
   1783 extern void _PR_InitLog(void);
   1784 extern void _PR_InitNet(void);
   1785 extern void _PR_InitClock(void);
   1786 extern void _PR_InitLinker(void);
   1787 extern void _PR_InitAtomic(void);
   1788 extern void _PR_InitCPUs(void);
   1789 extern void _PR_InitDtoa(void);
   1790 extern void _PR_InitTime(void);
   1791 extern void _PR_InitMW(void);
   1792 extern void _PR_InitRWLocks(void);
   1793 extern void _PR_CleanupThread(PRThread *thread);
   1794 extern void _PR_CleanupCallOnce(void);
   1795 extern void _PR_CleanupMW(void);
   1796 extern void _PR_CleanupTime(void);
   1797 extern void _PR_CleanupDtoa(void);
   1798 extern void _PR_ShutdownLinker(void);
   1799 extern void _PR_CleanupEnv(void);
   1800 extern void _PR_CleanupIO(void);
   1801 extern void _PR_CleanupCMon(void);
   1802 extern void _PR_CleanupNet(void);
   1803 extern void _PR_CleanupLayerCache(void);
   1804 extern void _PR_CleanupStacks(void);
   1805 #ifdef WINNT
   1806 extern void _PR_CleanupCPUs(void);
   1807 #endif
   1808 extern void _PR_CleanupThreads(void);
   1809 extern void _PR_CleanupTPD(void);
   1810 extern void _PR_Cleanup(void);
   1811 extern void _PR_LogCleanup(void);
   1812 extern void _PR_InitLayerCache(void);
   1813 
   1814 extern PRBool _pr_initialized;
   1815 extern void _PR_ImplicitInitialization(void);
   1816 extern PRBool _PR_Obsolete(const char *obsolete, const char *preferred);
   1817 
   1818 /************************************************************************/
   1819 
   1820 struct PRSegment {
   1821    void *vaddr;
   1822    PRUint32 size;
   1823    PRUintn flags;
   1824 #if defined(_PR_PTHREADS)
   1825 #else  /* defined(_PR_PTHREADS) */
   1826    _MDSegment md;
   1827 #endif /* defined(_PR_PTHREADS) */
   1828 };
   1829 
   1830 /* PRSegment.flags */
   1831 #define _PR_SEG_VM    0x1
   1832 
   1833 /************************************************************************/
   1834 
   1835 extern PRInt32 _pr_pageSize;
   1836 extern PRInt32 _pr_pageShift;
   1837 
   1838 extern PRLogModuleInfo *_pr_clock_lm;
   1839 extern PRLogModuleInfo *_pr_cmon_lm;
   1840 extern PRLogModuleInfo *_pr_io_lm;
   1841 extern PRLogModuleInfo *_pr_cvar_lm;
   1842 extern PRLogModuleInfo *_pr_mon_lm;
   1843 extern PRLogModuleInfo *_pr_linker_lm;
   1844 extern PRLogModuleInfo *_pr_sched_lm;
   1845 extern PRLogModuleInfo *_pr_thread_lm;
   1846 extern PRLogModuleInfo *_pr_gc_lm;
   1847 
   1848 extern PRFileDesc *_pr_stdin;
   1849 extern PRFileDesc *_pr_stdout;
   1850 extern PRFileDesc *_pr_stderr;
   1851 
   1852 /* Zone allocator */
   1853 /*
   1854 ** The zone allocator code has hardcoded pthread types and
   1855 ** functions, so it can only be used in the pthreads version.
   1856 ** This can be fixed by replacing the hardcoded pthread types
   1857 ** and functions with macros that expand to the native thread
   1858 ** types and functions on each platform.
   1859 */
   1860 #if defined(_PR_PTHREADS)
   1861 #define _PR_ZONE_ALLOCATOR
   1862 #endif
   1863 
   1864 #ifdef _PR_ZONE_ALLOCATOR
   1865 extern void _PR_InitZones(void);
   1866 extern void _PR_DestroyZones(void);
   1867 #endif
   1868 
   1869 /* Overriding malloc, free, etc. */
   1870 #if !defined(_PR_NO_PREEMPT) && defined(XP_UNIX) \
   1871        && !defined(_PR_PTHREADS) && !defined(_PR_GLOBAL_THREADS_ONLY) \
   1872        && !defined(PURIFY) \
   1873        && !defined(DARWIN) \
   1874        && !defined(QNX)
   1875 #define _PR_OVERRIDE_MALLOC
   1876 #endif
   1877 
   1878 /*************************************************************************
   1879 * External machine-dependent code provided by each OS.                     *                                                                     *
   1880 *************************************************************************/
   1881 
   1882 /* Initialization related */
   1883 extern void _PR_MD_EARLY_INIT(void);
   1884 #define    _PR_MD_EARLY_INIT _MD_EARLY_INIT
   1885 
   1886 extern void _PR_MD_INTERVAL_INIT(void);
   1887 #define    _PR_MD_INTERVAL_INIT _MD_INTERVAL_INIT
   1888 
   1889 NSPR_API(void) _PR_MD_FINAL_INIT(void);
   1890 #define    _PR_MD_FINAL_INIT _MD_FINAL_INIT
   1891 
   1892 extern void _PR_MD_EARLY_CLEANUP(void);
   1893 #define    _PR_MD_EARLY_CLEANUP _MD_EARLY_CLEANUP
   1894 
   1895 /* Process control */
   1896 
   1897 extern PRProcess * _PR_MD_CREATE_PROCESS(
   1898    const char *path,
   1899    char *const *argv,
   1900    char *const *envp,
   1901    const PRProcessAttr *attr);
   1902 #define    _PR_MD_CREATE_PROCESS _MD_CREATE_PROCESS
   1903 
   1904 extern PRStatus _PR_MD_DETACH_PROCESS(PRProcess *process);
   1905 #define    _PR_MD_DETACH_PROCESS _MD_DETACH_PROCESS
   1906 
   1907 extern PRStatus _PR_MD_WAIT_PROCESS(PRProcess *process, PRInt32 *exitCode);
   1908 #define    _PR_MD_WAIT_PROCESS _MD_WAIT_PROCESS
   1909 
   1910 extern PRStatus _PR_MD_KILL_PROCESS(PRProcess *process);
   1911 #define    _PR_MD_KILL_PROCESS _MD_KILL_PROCESS
   1912 
   1913 /* Current Time */
   1914 NSPR_API(PRTime) _PR_MD_NOW(void);
   1915 #define    _PR_MD_NOW _MD_NOW
   1916 
   1917 /* Environment related */
   1918 extern char* _PR_MD_GET_ENV(const char *name);
   1919 #define    _PR_MD_GET_ENV _MD_GET_ENV
   1920 
   1921 extern PRIntn _PR_MD_PUT_ENV(const char *name);
   1922 #define    _PR_MD_PUT_ENV _MD_PUT_ENV
   1923 
   1924 /* Atomic operations */
   1925 
   1926 extern void _PR_MD_INIT_ATOMIC(void);
   1927 #define    _PR_MD_INIT_ATOMIC _MD_INIT_ATOMIC
   1928 
   1929 extern PRInt32 _PR_MD_ATOMIC_INCREMENT(PRInt32 *);
   1930 #define    _PR_MD_ATOMIC_INCREMENT _MD_ATOMIC_INCREMENT
   1931 
   1932 extern PRInt32 _PR_MD_ATOMIC_ADD(PRInt32 *, PRInt32);
   1933 #define    _PR_MD_ATOMIC_ADD _MD_ATOMIC_ADD
   1934 
   1935 extern PRInt32 _PR_MD_ATOMIC_DECREMENT(PRInt32 *);
   1936 #define    _PR_MD_ATOMIC_DECREMENT _MD_ATOMIC_DECREMENT
   1937 
   1938 extern PRInt32 _PR_MD_ATOMIC_SET(PRInt32 *, PRInt32);
   1939 #define    _PR_MD_ATOMIC_SET _MD_ATOMIC_SET
   1940 
   1941 /* Garbage collection */
   1942 
   1943 /*
   1944 ** Save the registers that the GC would find interesting into the thread
   1945 ** "t". isCurrent will be non-zero if the thread state that is being
   1946 ** saved is the currently executing thread. Return the address of the
   1947 ** first register to be scanned as well as the number of registers to
   1948 ** scan in "np".
   1949 **
   1950 ** If "isCurrent" is non-zero then it is allowed for the thread context
   1951 ** area to be used as scratch storage to hold just the registers
   1952 ** necessary for scanning.
   1953 */
   1954 extern PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np);
   1955 
   1956 /* Time intervals */
   1957 
   1958 extern PRIntervalTime _PR_MD_GET_INTERVAL(void);
   1959 #define _PR_MD_GET_INTERVAL _MD_GET_INTERVAL
   1960 
   1961 extern PRIntervalTime _PR_MD_INTERVAL_PER_SEC(void);
   1962 #define _PR_MD_INTERVAL_PER_SEC _MD_INTERVAL_PER_SEC
   1963 
   1964 /* Affinity masks */
   1965 
   1966 extern PRInt32 _PR_MD_SETTHREADAFFINITYMASK(PRThread *thread, PRUint32 mask );
   1967 #define _PR_MD_SETTHREADAFFINITYMASK _MD_SETTHREADAFFINITYMASK
   1968 
   1969 extern PRInt32 _PR_MD_GETTHREADAFFINITYMASK(PRThread *thread, PRUint32 *mask);
   1970 #define _PR_MD_GETTHREADAFFINITYMASK _MD_GETTHREADAFFINITYMASK
   1971 
   1972 /* File locking */
   1973 
   1974 extern PRStatus _PR_MD_LOCKFILE(PROsfd osfd);
   1975 #define    _PR_MD_LOCKFILE _MD_LOCKFILE
   1976 
   1977 extern PRStatus _PR_MD_TLOCKFILE(PROsfd osfd);
   1978 #define    _PR_MD_TLOCKFILE _MD_TLOCKFILE
   1979 
   1980 extern PRStatus _PR_MD_UNLOCKFILE(PROsfd osfd);
   1981 #define    _PR_MD_UNLOCKFILE _MD_UNLOCKFILE
   1982 
   1983 /* Memory-mapped files */
   1984 
   1985 extern PRStatus _PR_MD_CREATE_FILE_MAP(PRFileMap *fmap, PRInt64 size);
   1986 #define _PR_MD_CREATE_FILE_MAP _MD_CREATE_FILE_MAP
   1987 
   1988 extern PRInt32 _PR_MD_GET_MEM_MAP_ALIGNMENT(void);
   1989 #define _PR_MD_GET_MEM_MAP_ALIGNMENT _MD_GET_MEM_MAP_ALIGNMENT
   1990 
   1991 extern void * _PR_MD_MEM_MAP(
   1992    PRFileMap *fmap,
   1993    PROffset64 offset,
   1994    PRUint32 len);
   1995 #define _PR_MD_MEM_MAP _MD_MEM_MAP
   1996 
   1997 extern PRStatus _PR_MD_MEM_UNMAP(void *addr, PRUint32 size);
   1998 #define _PR_MD_MEM_UNMAP _MD_MEM_UNMAP
   1999 
   2000 extern PRStatus _PR_MD_CLOSE_FILE_MAP(PRFileMap *fmap);
   2001 #define _PR_MD_CLOSE_FILE_MAP _MD_CLOSE_FILE_MAP
   2002 
   2003 extern PRStatus _PR_MD_SYNC_MEM_MAP(
   2004    PRFileDesc *fd,
   2005    void *addr,
   2006    PRUint32 len);
   2007 #define _PR_MD_SYNC_MEM_MAP _MD_SYNC_MEM_MAP
   2008 
   2009 /* Named Shared Memory */
   2010 
   2011 /*
   2012 ** Declare PRSharedMemory.
   2013 */
   2014 struct PRSharedMemory
   2015 {
   2016    char        *ipcname; /* after conversion to native */
   2017    PRSize      size;  /* from open */
   2018    PRIntn      mode;  /* from open */
   2019    PRIntn      flags; /* from open */
   2020 #if defined(PR_HAVE_POSIX_NAMED_SHARED_MEMORY)
   2021    int         id;
   2022 #elif defined(PR_HAVE_SYSV_NAMED_SHARED_MEMORY)
   2023    int         id;
   2024 #elif defined(PR_HAVE_WIN32_NAMED_SHARED_MEMORY)
   2025    HANDLE      handle;
   2026 #else
   2027    PRUint32    nothing; /* placeholder, nothing behind here */
   2028 #endif
   2029    PRUint32    ident; /* guard word at end of struct */
   2030 #define _PR_SHM_IDENT 0xdeadbad
   2031 };
   2032 
   2033 extern PRSharedMemory * _MD_OpenSharedMemory(
   2034    const char *name,
   2035    PRSize      size,
   2036    PRIntn      flags,
   2037    PRIntn      mode
   2038 );
   2039 #define _PR_MD_OPEN_SHARED_MEMORY _MD_OpenSharedMemory
   2040 
   2041 extern void * _MD_AttachSharedMemory( PRSharedMemory *shm, PRIntn flags );
   2042 #define _PR_MD_ATTACH_SHARED_MEMORY _MD_AttachSharedMemory
   2043 
   2044 extern PRStatus _MD_DetachSharedMemory( PRSharedMemory *shm, void *addr );
   2045 #define _PR_MD_DETACH_SHARED_MEMORY _MD_DetachSharedMemory
   2046 
   2047 extern PRStatus _MD_CloseSharedMemory( PRSharedMemory *shm );
   2048 #define _PR_MD_CLOSE_SHARED_MEMORY _MD_CloseSharedMemory
   2049 
   2050 extern PRStatus _MD_DeleteSharedMemory( const char *name );
   2051 #define _PR_MD_DELETE_SHARED_MEMORY  _MD_DeleteSharedMemory
   2052 
   2053 extern PRFileMap* _md_OpenAnonFileMap(
   2054    const char *dirName,
   2055    PRSize      size,
   2056    PRFileMapProtect prot
   2057 );
   2058 #define _PR_MD_OPEN_ANON_FILE_MAP _md_OpenAnonFileMap
   2059 
   2060 extern PRStatus _md_ExportFileMapAsString(
   2061    PRFileMap *fm,
   2062    PRSize    bufSize,
   2063    char      *buf
   2064 );
   2065 #define _PR_MD_EXPORT_FILE_MAP_AS_STRING _md_ExportFileMapAsString
   2066 
   2067 extern PRFileMap * _md_ImportFileMapFromString(
   2068    const char *fmstring
   2069 );
   2070 #define _PR_MD_IMPORT_FILE_MAP_FROM_STRING _md_ImportFileMapFromString
   2071 
   2072 
   2073 
   2074 /* Interprocess communications (IPC) */
   2075 
   2076 /*
   2077 * The maximum length of an NSPR IPC name, including the
   2078 * terminating null byte.
   2079 */
   2080 #define PR_IPC_NAME_SIZE 1024
   2081 
   2082 /*
   2083 * Types of NSPR IPC objects
   2084 */
   2085 typedef enum {
   2086    _PRIPCSem,  /* semaphores */
   2087    _PRIPCShm   /* shared memory segments */
   2088 } _PRIPCType;
   2089 
   2090 /*
   2091 * Make a native IPC name from an NSPR IPC name.
   2092 */
   2093 extern PRStatus _PR_MakeNativeIPCName(
   2094    const char *name,  /* NSPR IPC name */
   2095    char *result,      /* result buffer */
   2096    PRIntn size,       /* size of result buffer */
   2097    _PRIPCType type    /* type of IPC object */
   2098 );
   2099 
   2100 /* Socket call error code */
   2101 
   2102 NSPR_API(PRInt32) _PR_MD_GET_SOCKET_ERROR(void);
   2103 #define    _PR_MD_GET_SOCKET_ERROR _MD_GET_SOCKET_ERROR
   2104 
   2105 /* Get name of current host */
   2106 extern PRStatus _PR_MD_GETHOSTNAME(char *name, PRUint32 namelen);
   2107 #define    _PR_MD_GETHOSTNAME _MD_GETHOSTNAME
   2108 
   2109 extern PRStatus _PR_MD_GETSYSINFO(PRSysInfo cmd, char *name, PRUint32 namelen);
   2110 #define    _PR_MD_GETSYSINFO _MD_GETSYSINFO
   2111 
   2112 /* File descriptor inheritance */
   2113 
   2114 /*
   2115 * If fd->secret->inheritable is _PR_TRI_UNKNOWN and we need to
   2116 * know the inheritable attribute of the fd, call this function
   2117 * to find that out.  This typically requires a system call.
   2118 */
   2119 extern void _PR_MD_QUERY_FD_INHERITABLE(PRFileDesc *fd);
   2120 #define    _PR_MD_QUERY_FD_INHERITABLE _MD_QUERY_FD_INHERITABLE
   2121 
   2122 /* --- PR_GetRandomNoise() related things --- */
   2123 
   2124 extern PRSize _PR_MD_GetRandomNoise( void *buf, PRSize size );
   2125 #define _PR_MD_GET_RANDOM_NOISE(buf,size) _PR_MD_GetRandomNoise((buf),(size))
   2126 extern PRSize _pr_CopyLowBits( void *dest, PRSize dstlen, void *src, PRSize srclen );
   2127 
   2128 /* end PR_GetRandomNoise() related */
   2129 
   2130 #if defined(_WIN64) && defined(WIN95)
   2131 typedef struct _PRFileDescList {
   2132    PRFileDesc *fd;
   2133    struct _PRFileDescList *next;
   2134 } PRFileDescList;
   2135 
   2136 extern PRLock *_fd_waiting_for_overlapped_done_lock;
   2137 extern PRFileDescList *_fd_waiting_for_overlapped_done;
   2138 extern void CheckOverlappedPendingSocketsAreDone();
   2139 #endif
   2140 
   2141 
   2142 PR_END_EXTERN_C
   2143 
   2144 #endif /* primpl_h___ */