VirtualBox

Ignore:
Timestamp:
Nov 6, 2023 8:10:50 PM (15 months ago)
Author:
vboxsync
Message:

libs/xpcom: Remove more unused code in nsprpub, bugref:10545

Location:
trunk/src/libs/xpcom18a4/nsprpub/pr
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/libs/xpcom18a4/nsprpub/pr/include/private/pprthred.h

    r101877 r101899  
    5353
    5454#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
    55 #define PR_AttachThread VBoxNsprPR_AttachThread
    5655#define PR_DetachThread VBoxNsprPR_DetachThread
    5756#define PR_GetThreadID VBoxNsprPR_GetThreadID
     
    6160#define PR_SetCPUAffinityMask VBoxNsprPR_SetCPUAffinityMask
    6261#define PR_ShowStatus VBoxNsprPR_ShowStatus
    63 #define PR_SetThreadRecycleMode VBoxNsprPR_SetThreadRecycleMode
    64 #define PR_CreateThreadGCAble VBoxNsprPR_CreateThreadGCAble
    65 #define PR_AttachThreadGCAble VBoxNsprPR_AttachThreadGCAble
    66 #define PR_SetThreadGCAble VBoxNsprPR_SetThreadGCAble
    67 #define PR_ClearThreadGCAble VBoxNsprPR_ClearThreadGCAble
    68 #define PR_SuspendAll VBoxNsprPR_SuspendAll
    69 #define PR_ResumeAll VBoxNsprPR_ResumeAll
    70 #define PR_GetSP VBoxNsprPR_GetSP
    71 #define GetExecutionEnvironment VBoxNsprGetExecutionEnvironment
    72 #define SetExecutionEnvironment VBoxNsprSetExecutionEnvironment
    73 #define PR_EnumerateThreads VBoxNsprPR_EnumerateThreads
    7462#define PR_ThreadScanStackPointers VBoxNsprPR_ThreadScanStackPointers
    7563#define PR_ScanStackPointers VBoxNsprPR_ScanStackPointers
     
    7967#define PR_TestAndEnterMonitor VBoxNsprPR_TestAndEnterMonitor
    8068#define PR_GetMonitorEntryCount VBoxNsprPR_GetMonitorEntryCount
    81 #define PR_CTestAndEnterMonitor VBoxNsprPR_CTestAndEnterMonitor
    82 #define PR_Mac_WaitForAsyncNotify VBoxNsprPR_Mac_WaitForAsyncNotify
    83 #define PR_Mac_PostAsyncNotify VBoxNsprPR_Mac_PostAsyncNotify
    84 #define PR_OS2_SetFloatExcpHandler VBoxNsprPR_OS2_SetFloatExcpHandler
    85 #define PR_OS2_UnsetFloatExcpHandler VBoxNsprPR_OS2_UnsetFloatExcpHandler
    8669#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
    8770
     
    9174** THREAD PRIVATE FUNCTIONS
    9275---------------------------------------------------------------------------*/
    93 
    94 /*
    95 ** Associate a thread object with an existing native thread.
    96 **      "type" is the type of thread object to attach
    97 **      "priority" is the priority to assign to the thread
    98 **      "stack" defines the shape of the threads stack
    99 **
    100 ** This can return NULL if some kind of error occurs, or if memory is
    101 ** tight. This call invokes "start(obj,arg)" and returns when the
    102 ** function returns. The thread object is automatically destroyed.
    103 **
    104 ** This call is not normally needed unless you create your own native
    105 ** thread. PR_Init does this automatically for the primordial thread.
    106 */
    107 NSPR_API(PRThread*) PR_AttachThread(PRThreadType type,
    108                                      PRThreadPriority priority,
    109                                      PRThreadStack *stack);
    110 
    111 /*
    112 ** Detach the nspr thread from the currently executing native thread.
    113 ** The thread object will be destroyed and all related data attached
    114 ** to it. The exit procs will be invoked.
    115 **
    116 ** This call is not normally needed unless you create your own native
    117 ** thread. PR_Exit will automatially detach the nspr thread object
    118 ** created by PR_Init for the primordial thread.
    119 **
    120 ** This call returns after the nspr thread object is destroyed.
    121 */
    122 NSPR_API(void) PR_DetachThread(void);
    12376
    12477/*
     
    160113NSPR_API(PRInt32) PR_SetCPUAffinityMask(PRUint32 mask);
    161114
    162 /*
    163 ** Show status of all threads to standard error output.
    164 */
    165 NSPR_API(void) PR_ShowStatus(void);
    166 
    167 /*
    168 ** Set thread recycle mode to on (1) or off (0)
    169 */
    170 NSPR_API(void) PR_SetThreadRecycleMode(PRUint32 flag);
    171 
    172 
    173 /*---------------------------------------------------------------------------
    174 ** THREAD PRIVATE FUNCTIONS FOR GARBAGE COLLECTIBLE THREADS           
    175 ---------------------------------------------------------------------------*/
    176 
    177 /*
    178 ** Only Garbage collectible threads participate in resume all, suspend all and
    179 ** enumeration operations.  They are also different during creation when
    180 ** platform specific action may be needed (For example, all Solaris GC able
    181 ** threads are bound threads).
    182 */
    183 
    184 /*
    185 ** Same as PR_CreateThread except that the thread is marked as garbage
    186 ** collectible.
    187 */
    188 NSPR_API(PRThread*) PR_CreateThreadGCAble(PRThreadType type,
    189                                      void (*start)(void *arg),
    190                                      void *arg,
    191                                      PRThreadPriority priority,
    192                                      PRThreadScope scope,
    193                                      PRThreadState state,
    194                                      PRUint32 stackSize);
    195 
    196 /*
    197 ** Same as PR_AttachThread except that the thread being attached is marked as
    198 ** garbage collectible.
    199 */
    200 NSPR_API(PRThread*) PR_AttachThreadGCAble(PRThreadType type,
    201                                         PRThreadPriority priority,
    202                                         PRThreadStack *stack);
    203 
    204 /*
    205 ** Mark the thread as garbage collectible.
    206 */
    207 NSPR_API(void) PR_SetThreadGCAble(void);
    208 
    209 /*
    210 ** Unmark the thread as garbage collectible.
    211 */
    212 NSPR_API(void) PR_ClearThreadGCAble(void);
    213 
    214 /*
    215 ** This routine prevents all other GC able threads from running. This call is needed by
    216 ** the garbage collector.
    217 */
    218 NSPR_API(void) PR_SuspendAll(void);
    219 
    220 /*
    221 ** This routine unblocks all other GC able threads that were suspended from running by
    222 ** PR_SuspendAll(). This call is needed by the garbage collector.
    223 */
    224 NSPR_API(void) PR_ResumeAll(void);
    225 
    226 /*
    227 ** Return the thread stack pointer of the given thread.
    228 ** Needed by the garbage collector.
    229 */
    230 NSPR_API(void *) PR_GetSP(PRThread *thread);
    231 
    232 /*
    233 ** (Get|Set)ExecutionEnvironent
    234 **
    235 ** Used by Java to associate it's execution environment so garbage collector
    236 ** can find it. If return is NULL, then it's probably not a collectable thread.
    237 **
    238 ** There's no locking required around these calls.
    239 */
    240 NSPR_API(void*) GetExecutionEnvironment(PRThread *thread);
    241 NSPR_API(void) SetExecutionEnvironment(PRThread* thread, void *environment);
    242 
    243 /*
    244 ** Enumeration function that applies "func(thread,i,arg)" to each active
    245 ** thread in the process. The enumerator returns PR_SUCCESS if the enumeration
    246 ** should continue, any other value is considered failure, and enumeration
    247 ** stops, returning the failure value from PR_EnumerateThreads.
    248 ** Needed by the garbage collector.
    249 */
    250 typedef PRStatus (PR_CALLBACK *PREnumerator)(PRThread *t, int i, void *arg);
    251 NSPR_API(PRStatus) PR_EnumerateThreads(PREnumerator func, void *arg);
    252 
    253 /*---------------------------------------------------------------------------
    254 ** THREAD CPU PRIVATE FUNCTIONS             
    255 ---------------------------------------------------------------------------*/
    256 
    257 /*
    258 ** Get a pointer to the primordial CPU.
    259 */
    260 NSPR_API(struct _PRCPU *) _PR_GetPrimordialCPU(void);
    261115
    262116/*---------------------------------------------------------------------------
     
    293147NSPR_API(PRIntn) PR_GetMonitorEntryCount(PRMonitor *mon);
    294148
    295 /*
    296 ** Just like PR_CEnterMonitor except that if the monitor is owned by
    297 ** another thread NULL is returned.
    298 */
    299 NSPR_API(PRMonitor*) PR_CTestAndEnterMonitor(void *address);
    300 
    301149/*---------------------------------------------------------------------------
    302150** PLATFORM-SPECIFIC INITIALIZATION FUNCTIONS
  • trunk/src/libs/xpcom18a4/nsprpub/pr/include/prlog.h

    r11551 r101899  
    205205#if (defined(DEBUG) || defined(FORCE_PR_LOG)) && !defined(WIN16)
    206206#define PR_LOGGING 1
    207 
    208207#define PR_LOG_TEST(_module,_level) \
    209208    ((_module)->level >= (_level))
  • trunk/src/libs/xpcom18a4/nsprpub/pr/src/pthreads/ptthread.c

    r101891 r101899  
    5151#include <signal.h>
    5252
    53 #ifdef VBOX_USE_IPRT_IN_NSPR
    54 # include <iprt/thread.h>
    55 # include <iprt/mem.h>
    56 # include <iprt/asm.h>
    57 # include <iprt/err.h>
    58 #endif /* VBOX_USE_IPRT_IN_NSPR */
     53#include <iprt/thread.h>
     54#include <iprt/mem.h>
     55#include <iprt/asm.h>
     56#include <iprt/err.h>
    5957
    6058/*
     
    7573    pthread_key_t key;          /* private private data key */
    7674    PRThread *first, *last;     /* list of threads we know about */
    77 #if defined(_PR_DCETHREADS) || defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
     75#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
    7876    PRInt32 minPrio, maxPrio;   /* range of scheduling priorities */
    7977#endif
     
    8179
    8280static void _pt_thread_death(void *arg);
    83 static void init_pthread_gc_support(void);
    84 
    85 #if defined(_PR_DCETHREADS) || defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
     81
     82#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
    8683static PRIntn pt_PriorityMap(PRThreadPriority pri)
    8784{
    88 #ifdef NTO
    89     /* This priority algorithm causes lots of problems on Neutrino
    90      * for now I have just hard coded everything to run at priority 10
    91      * until I can come up with a new algorithm.
    92      *     [email protected]
    93      */
    94     return 10;
    95 #else
    9685    return pt_book.minPrio +
    9786            pri * (pt_book.maxPrio - pt_book.minPrio) / PR_PRIORITY_LAST;
    98 #endif
    9987}
    10088#endif
     
    139127    thred->id = pthread_self();
    140128
    141     /*
    142     ** DCE Threads can't detach during creation, so do it late.
    143     ** I would like to do it only here, but that doesn't seem
    144     ** to work.
    145     */
    146 #if defined(_PR_DCETHREADS)
    147     if (detached)
    148     {
    149         /* pthread_detach() modifies its argument, so we must pass a copy */
    150         pthread_t self = thred->id;
    151         rv = pthread_detach(&self);
    152         PR_ASSERT(0 == rv);
    153     }
    154 #endif /* defined(_PR_DCETHREADS) */
    155 
    156129    /* Set up the thread stack information */
    157130    _PR_InitializeStack(thred->stack);
     
    222195}  /* _pt_root */
    223196
    224 #ifdef VBOX_USE_IPRT_IN_NSPR
    225197static DECLCALLBACK(int) _pt_iprt_root(
    226198    RTTHREAD Thread, void *pvUser)
     
    230202    return VINF_SUCCESS;
    231203}
    232 #endif /* VBOX_USE_IPRT_IN_NSPR */
    233204
    234205static PRThread* pt_AttachThread(void)
     
    279250    int rv;
    280251    PRThread *thred;
    281 #ifndef VBOX_USE_IPRT_IN_NSPR
    282     pthread_attr_t tattr;
    283 #else
    284252    static uint32_t volatile s_iThread = 0;
    285253    RTTHREADTYPE enmType;
    286254    RTTHREAD hThread;
    287255    uint32_t fFlags = 0;
    288 #endif
    289256
    290257    if (!_pr_initialized) _PR_ImplicitInitialization();
     
    295262        priority = PR_PRIORITY_LAST;
    296263
    297 #ifndef VBOX_USE_IPRT_IN_NSPR
    298     rv = _PT_PTHREAD_ATTR_INIT(&tattr);
    299     PR_ASSERT(0 == rv);
    300 
    301     if (EPERM != pt_schedpriv)
    302     {
    303 #if !defined(_PR_DCETHREADS) && defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
    304         struct sched_param schedule;
    305 #endif
    306 
    307 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
    308         rv = pthread_attr_setinheritsched(&tattr, PTHREAD_EXPLICIT_SCHED);
    309         PR_ASSERT(0 == rv);
    310 #endif
    311 
    312         /* Use the default scheduling policy */
    313 
    314 #if defined(_PR_DCETHREADS)
    315         rv = pthread_attr_setprio(&tattr, pt_PriorityMap(priority));
    316         PR_ASSERT(0 == rv);
    317 #elif defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
    318         rv = pthread_attr_getschedparam(&tattr, &schedule);
    319         PR_ASSERT(0 == rv);
    320         schedule.sched_priority = pt_PriorityMap(priority);
    321         rv = pthread_attr_setschedparam(&tattr, &schedule);
    322         PR_ASSERT(0 == rv);
    323 #ifdef NTO
    324         rv = pthread_attr_setschedpolicy(&tattr, SCHED_RR); /* Round Robin */
    325         PR_ASSERT(0 == rv);
    326 #endif
    327 #endif /* !defined(_PR_DCETHREADS) */
    328     }
    329 #else  /* VBOX_USE_IPRT_IN_NSPR */
    330264    /* calc priority */
    331265    switch (priority)
     
    337271        case PR_PRIORITY_URGENT:    enmType = RTTHREADTYPE_IO; break;
    338272    }
    339 #endif /* VBOX_USE_IPRT_IN_NSPR */
    340 
    341 #ifndef VBOX_USE_IPRT_IN_NSPR
    342     /*
    343      * DCE threads can't set detach state before creating the thread.
    344      * AIX can't set detach late. Why can't we all just get along?
    345      */
    346 #if !defined(_PR_DCETHREADS)
    347     rv = pthread_attr_setdetachstate(&tattr,
    348         ((PR_JOINABLE_THREAD == state) ?
    349             PTHREAD_CREATE_JOINABLE : PTHREAD_CREATE_DETACHED));
    350     PR_ASSERT(0 == rv);
    351 #endif /* !defined(_PR_DCETHREADS) */
    352 #else
     273
    353274    if (state == PR_JOINABLE_THREAD)
    354275        fFlags |= RTTHREADFLAGS_WAITABLE;
    355 #endif /* !VBOX_USE_IPRT_IN_NSPR */
    356 
    357 #ifndef VBOX_USE_IPRT_IN_NSPR /* We let stackSize stay zero and let IPRT choose a default size. */
    358     if (0 == stackSize) stackSize = (64 * 1024);  /* default == 64K */
    359 #ifdef _MD_MINIMUM_STACK_SIZE
    360     if (stackSize < _MD_MINIMUM_STACK_SIZE) stackSize = _MD_MINIMUM_STACK_SIZE;
    361 #endif
    362     /*
    363      * Linux doesn't have pthread_attr_setstacksize.
    364      */
    365 #ifndef LINUX
    366     rv = pthread_attr_setstacksize(&tattr, stackSize);
    367     PR_ASSERT(0 == rv);
    368 #endif
    369 #endif /* !VBOX_USE_IPRT_IN_NSPR */
    370276
    371277    thred = PR_NEWZAP(PRThread);
     
    387293        if (PR_LOCAL_THREAD == scope)
    388294                scope = PR_GLOBAL_THREAD;
    389                        
    390 #ifndef VBOX_USE_IPRT_IN_NSPR
    391         if (PR_GLOBAL_BOUND_THREAD == scope) {
    392 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
    393                 rv = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM);
    394                         if (rv) {
    395                                 /*
    396                                  * system scope not supported
    397                                  */
    398                         scope = PR_GLOBAL_THREAD;
    399                                 /*
    400                                  * reset scope
    401                                  */
    402                         rv = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_PROCESS);
    403                         PR_ASSERT(0 == rv);
    404                         }
    405 #endif
    406                 }
    407 #endif /* !VBOX_USE_IPRT_IN_NSPR */
    408295        if (PR_GLOBAL_THREAD == scope)
    409296            thred->state |= PT_THREAD_GLOBAL;
     
    445332         * pthread_create() may be doing to its argument.
    446333         */
    447 #ifndef VBOX_USE_IPRT_IN_NSPR
    448         rv = _PT_PTHREAD_CREATE(&id, tattr, _pt_root, thred);
    449 
    450 #if !defined(_PR_DCETHREADS)
    451         if (EPERM == rv)
    452         {
    453 #if defined(IRIX)
    454                 if (PR_GLOBAL_BOUND_THREAD == scope) {
    455                                 /*
    456                                  * SCOPE_SYSTEM requires appropriate privilege
    457                                  * reset to process scope and try again
    458                                  */
    459                         rv = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_PROCESS);
    460                         PR_ASSERT(0 == rv);
    461                 thred->state &= ~PT_THREAD_BOUND;
    462                         }
    463 #else
    464             /* Remember that we don't have thread scheduling privilege. */
    465             pt_schedpriv = EPERM;
    466             PR_LOG(_pr_thread_lm, PR_LOG_MIN,
    467                 ("_PR_CreateThread: no thread scheduling privilege"));
    468             /* Try creating the thread again without setting priority. */
    469 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
    470             rv = pthread_attr_setinheritsched(&tattr, PTHREAD_INHERIT_SCHED);
    471             PR_ASSERT(0 == rv);
    472 #endif
    473 #endif  /* IRIX */
    474             rv = _PT_PTHREAD_CREATE(&id, tattr, _pt_root, thred);
    475         }
    476 #endif
    477 #else  /* VBOX_USE_IPRT_IN_NSPR */
    478334                rv = RTThreadCreateF(&hThread, _pt_iprt_root, thred, stackSize, enmType, fFlags, "nspr-%u", ASMAtomicIncU32(&s_iThread));
    479335                if (RT_SUCCESS(rv)) {
    480 #ifdef VBOX_USE_IPRT_IN_NSPR
    481336                        RTMEM_WILL_LEAK(hThread);
    482 #endif
    483337                        id = (pthread_t)RTThreadGetNative(hThread);
    484338            rv = 0;
    485339        }
    486 #endif /* VBOX_USE_IPRT_IN_NSPR */
    487340
    488341        if (0 != rv)
    489342        {
    490 #if defined(_PR_DCETHREADS)
    491             PRIntn oserr = errno;
    492 #else
    493343            PRIntn oserr = rv;
    494 #endif
    495344            PR_Lock(pt_book.ml);
    496345            if (thred->state & PT_THREAD_SYSTEM)
     
    528377
    529378done:
    530 #ifndef VBOX_USE_IPRT_IN_NSPR
    531     rv = _PT_PTHREAD_ATTR_DESTROY(&tattr);
    532     PR_ASSERT(0 == rv);
    533 #endif
    534 
    535379    return thred;
    536380}  /* _PR_CreateThread */
     
    544388        type, start, arg, priority, scope, state, stackSize, PR_FALSE);
    545389} /* PR_CreateThread */
    546 
    547 PR_IMPLEMENT(PRThread*) PR_CreateThreadGCAble(
    548     PRThreadType type, void (*start)(void *arg), void *arg,
    549     PRThreadPriority priority, PRThreadScope scope,
    550     PRThreadState state, PRUint32 stackSize)
    551 {
    552     return _PR_CreateThread(
    553         type, start, arg, priority, scope, state, stackSize, PR_TRUE);
    554 }  /* PR_CreateThreadGCAble */
    555 
    556 PR_IMPLEMENT(void*) GetExecutionEnvironment(PRThread *thred)
    557 {
    558     return thred->environment;
    559 }  /* GetExecutionEnvironment */
    560  
    561 PR_IMPLEMENT(void) SetExecutionEnvironment(PRThread *thred, void *env)
    562 {
    563     thred->environment = env;
    564 }  /* SetExecutionEnvironment */
    565 
    566 PR_IMPLEMENT(PRThread*) PR_AttachThread(
    567     PRThreadType type, PRThreadPriority priority, PRThreadStack *stack)
    568 {
    569     return PR_GetCurrentThread();
    570 }  /* PR_AttachThread */
    571 
    572390
    573391PR_IMPLEMENT(PRStatus) PR_JoinThread(PRThread *thred)
     
    593411    else
    594412    {
    595 #ifndef VBOX_USE_IPRT_IN_NSPR
    596         pthread_t id = thred->id;
    597         rv = pthread_join(id, &result);
    598         PR_ASSERT(rv == 0 && result == NULL);
    599         if (0 == rv)
    600         {
    601 #ifdef _PR_DCETHREADS
    602             rv = pthread_detach(&id);
    603             PR_ASSERT(0 == rv);
    604 #endif
    605             _pt_thread_death(thred);
    606         }
    607         else
    608         {
    609             PRErrorCode prerror;
    610             switch (rv)
    611             {
    612                 case EINVAL:  /* not a joinable thread */
    613                 case ESRCH:   /* no thread with given ID */
    614                     prerror = PR_INVALID_ARGUMENT_ERROR;
    615                     break;
    616                 case EDEADLK: /* a thread joining with itself */
    617                     prerror = PR_DEADLOCK_ERROR;
    618                     break;
    619                 default:
    620                     prerror = PR_UNKNOWN_ERROR;
    621                     break;
    622             }
    623             PR_SetError(prerror, rv);
    624         }
    625 #else  /* VBOX_USE_IPRT_IN_NSPR */
    626413        rv = VERR_INVALID_HANDLE;
    627414        RTTHREAD hThread = RTThreadFromNative((RTNATIVETHREAD)thred->id);
     
    642429                            rv);
    643430        }
    644 #endif /* VBOX_USE_IPRT_IN_NSPR */
    645431    }
    646432    return (0 == rv) ? PR_SUCCESS : PR_FAILURE;
    647433}  /* PR_JoinThread */
    648 
    649 PR_IMPLEMENT(void) PR_DetachThread(void) { }  /* PR_DetachThread */
    650434
    651435PR_IMPLEMENT(PRThread*) PR_GetCurrentThread(void)
     
    696480        newPri = PR_PRIORITY_LAST;
    697481
    698 #if defined(_PR_DCETHREADS)
    699     rv = pthread_setprio(thred->id, pt_PriorityMap(newPri));
    700     /* pthread_setprio returns the old priority */
    701 #elif defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
     482#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
    702483    if (EPERM != pt_schedpriv)
    703484    {
     
    855636    PRThread *thred;
    856637
    857 #ifdef _PR_NEED_PTHREAD_INIT
    858     /*
    859      * On BSD/OS (3.1 and 4.0), the pthread subsystem is lazily
    860      * initialized, but pthread_self() fails to initialize
    861      * pthreads and hence returns a null thread ID if invoked
    862      * by the primordial thread before any other pthread call.
    863      * So we explicitly initialize pthreads here.
    864      */
    865     pthread_init();
    866 #endif
    867 
    868 #if defined(_PR_DCETHREADS) || defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
     638#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
    869639#if defined(FREEBSD)
    870640    {
     
    984754}  /* PR_Cleanup */
    985755
    986 PR_IMPLEMENT(void) PR_ProcessExit(PRIntn status)
    987 {
    988     _exit(status);
    989 }
    990 
    991 PR_IMPLEMENT(PRUint32) PR_GetThreadID(PRThread *thred)
    992 {
    993 #if defined(_PR_DCETHREADS)
    994     return (PRUint32)&thred->id;  /* this is really a sham! */
    995 #else
    996     return (PRUint32)thred->id;  /* and I don't know what they will do with it */
    997 #endif
    998 }
    999 
    1000 /*
    1001  * $$$
    1002  * The following two thread-to-processor affinity functions are not
    1003  * yet implemented for pthreads.  By the way, these functions should return
    1004  * PRStatus rather than PRInt32 to indicate the success/failure status.
    1005  * $$$
    1006  */
    1007 
    1008 PR_IMPLEMENT(PRInt32) PR_GetThreadAffinityMask(PRThread *thread, PRUint32 *mask)
    1009 {
    1010     return 0;  /* not implemented */
    1011 }
    1012 
    1013 PR_IMPLEMENT(PRInt32) PR_SetThreadAffinityMask(PRThread *thread, PRUint32 mask )
    1014 {
    1015     return 0;  /* not implemented */
    1016 }
    1017 
    1018 PR_IMPLEMENT(void)
    1019 PR_SetThreadDumpProc(PRThread* thread, PRThreadDumpProc dump, void *arg)
    1020 {
    1021     thread->dump = dump;
    1022     thread->dumpArg = arg;
    1023 }
    1024 
    1025 /*
    1026  * Garbage collection support follows.
    1027  */
    1028 
    1029 #if defined(_PR_DCETHREADS)
    1030 
    1031 /*
    1032  * statics for Garbage Collection support.  We don't need to protect these
    1033  * signal masks since the garbage collector itself is protected by a lock
    1034  * and multiple threads will not be garbage collecting at the same time.
    1035  */
    1036 static sigset_t javagc_vtalarm_sigmask;
    1037 static sigset_t javagc_intsoff_sigmask;
    1038 
    1039 #else /* defined(_PR_DCETHREADS) */
    1040 
    1041 /* a bogus signal mask for forcing a timed wait */
    1042 /* Not so bogus in AIX as we really do a sigwait */
    1043 static sigset_t sigwait_set;
    1044 
    1045 static struct timespec onemillisec = {0, 1000000L};
    1046 #ifndef PT_NO_SIGTIMEDWAIT
    1047 static struct timespec hundredmillisec = {0, 100000000L};
    1048 #endif
    1049 
    1050 static void suspend_signal_handler(PRIntn sig);
    1051 
    1052 #ifdef PT_NO_SIGTIMEDWAIT
    1053 static void null_signal_handler(PRIntn sig);
    1054 #endif
    1055 
    1056 #endif /* defined(_PR_DCETHREADS) */
    1057 
    1058 /*
    1059  * Linux pthreads use SIGUSR1 and SIGUSR2 internally, which
    1060  * conflict with the use of these two signals in our GC support.
    1061  * So we don't know how to support GC on Linux pthreads.
    1062  */
    1063 static void init_pthread_gc_support(void)
    1064 {
    1065     PRIntn rv;
    1066 
    1067 #if defined(_PR_DCETHREADS)
    1068         rv = sigemptyset(&javagc_vtalarm_sigmask);
    1069     PR_ASSERT(0 == rv);
    1070         rv = sigaddset(&javagc_vtalarm_sigmask, SIGVTALRM);
    1071     PR_ASSERT(0 == rv);
    1072 #else  /* defined(_PR_DCETHREADS) */
    1073         {
    1074             struct sigaction sigact_usr2;
    1075 
    1076             sigact_usr2.sa_handler = suspend_signal_handler;
    1077             sigact_usr2.sa_flags = SA_RESTART;
    1078             sigemptyset (&sigact_usr2.sa_mask);
    1079 
    1080         rv = sigaction (SIGUSR2, &sigact_usr2, NULL);
    1081         PR_ASSERT(0 == rv);
    1082 
    1083         sigemptyset (&sigwait_set);
    1084 #if defined(PT_NO_SIGTIMEDWAIT)
    1085         sigaddset (&sigwait_set, SIGUSR1);
    1086 #else
    1087         sigaddset (&sigwait_set, SIGUSR2);
    1088 #endif  /* defined(PT_NO_SIGTIMEDWAIT) */
    1089         }
    1090 #if defined(PT_NO_SIGTIMEDWAIT)
    1091         {
    1092             struct sigaction sigact_null;
    1093             sigact_null.sa_handler = null_signal_handler;
    1094             sigact_null.sa_flags = SA_RESTART;
    1095             sigemptyset (&sigact_null.sa_mask);
    1096         rv = sigaction (SIGUSR1, &sigact_null, NULL);
    1097             PR_ASSERT(0 ==rv);
    1098     }
    1099 #endif  /* defined(PT_NO_SIGTIMEDWAIT) */
    1100 #endif /* defined(_PR_DCETHREADS) */
    1101 }
    1102 
    1103 PR_IMPLEMENT(void) PR_SetThreadGCAble(void)
    1104 {
    1105     PR_Lock(pt_book.ml);
    1106         PR_CurrentThread()->state |= PT_THREAD_GCABLE;
    1107     PR_Unlock(pt_book.ml);
    1108 }
    1109 
    1110 PR_IMPLEMENT(void) PR_ClearThreadGCAble(void)
    1111 {
    1112     PR_Lock(pt_book.ml);
    1113         PR_CurrentThread()->state &= (~PT_THREAD_GCABLE);
    1114     PR_Unlock(pt_book.ml);
    1115 }
    1116 
    1117 #if defined(DEBUG)
    1118 static PRBool suspendAllOn = PR_FALSE;
    1119 #endif
    1120 
    1121 static PRBool suspendAllSuspended = PR_FALSE;
    1122 
    1123 PR_IMPLEMENT(PRStatus) PR_EnumerateThreads(PREnumerator func, void *arg)
    1124 {
    1125     PRIntn count = 0;
    1126     PRStatus rv = PR_SUCCESS;
    1127     PRThread* thred = pt_book.first;
    1128     PRThread *me = PR_CurrentThread();
    1129 
    1130     PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_EnumerateThreads\n"));
    1131     /*
    1132      * $$$
    1133      * Need to suspend all threads other than me before doing this.
    1134      * This is really a gross and disgusting thing to do. The only
    1135      * good thing is that since all other threads are suspended, holding
    1136      * the lock during a callback seems like child's play.
    1137      * $$$
    1138      */
    1139     PR_ASSERT(suspendAllOn);
    1140 
    1141     while (thred != NULL)
    1142     {
    1143         /* Steve Morse, 4-23-97: Note that we can't walk a queue by taking
    1144          * qp->next after applying the function "func".  In particular, "func"
    1145          * might remove the thread from the queue and put it into another one in
    1146          * which case qp->next no longer points to the next entry in the original
    1147          * queue.
    1148          *
    1149          * To get around this problem, we save qp->next in qp_next before applying
    1150          * "func" and use that saved value as the next value after applying "func".
    1151          */
    1152         PRThread* next = thred->next;
    1153 
    1154         if (_PT_IS_GCABLE_THREAD(thred))
    1155         {
    1156 #if !defined(_PR_DCETHREADS)
    1157             PR_ASSERT((thred == me) || (thred->suspend & PT_THREAD_SUSPENDED));
    1158 #endif
    1159             PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,
    1160                    ("In PR_EnumerateThreads callback thread %X thid = %X\n",
    1161                     thred, thred->id));
    1162 
    1163             rv = func(thred, count++, arg);
    1164             if (rv != PR_SUCCESS)
    1165                 return rv;
    1166         }
    1167         thred = next;
    1168     }
    1169     PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,
    1170            ("End PR_EnumerateThreads count = %d \n", count));
    1171     return rv;
    1172 }  /* PR_EnumerateThreads */
    1173 
    1174 /*
    1175  * PR_SuspendAll and PR_ResumeAll are called during garbage collection.  The strategy
    1176  * we use is to send a SIGUSR2 signal to every gc able thread that we intend to suspend.
    1177  * The signal handler will record the stack pointer and will block until resumed by
    1178  * the resume call.  Since the signal handler is the last routine called for the
    1179  * suspended thread, the stack pointer will also serve as a place where all the
    1180  * registers have been saved on the stack for the previously executing routines.
    1181  *
    1182  * Through global variables, we also make sure that PR_Suspend and PR_Resume does not
    1183  * proceed until the thread is suspended or resumed.
    1184  */
    1185 
    1186 #if !defined(_PR_DCETHREADS)
    1187 
    1188 /*
    1189  * In the signal handler, we can not use condition variable notify or wait.
    1190  * This does not work consistently across all pthread platforms.  We also can not
    1191  * use locking since that does not seem to work reliably across platforms.
    1192  * Only thing we can do is yielding while testing for a global condition
    1193  * to change.  This does work on pthread supported platforms.  We may have
    1194  * to play with priortities if there are any problems detected.
    1195  */
    1196 
    1197  /*
    1198   * In AIX, you cannot use ANY pthread calls in the signal handler except perhaps
    1199   * pthread_yield. But that is horribly inefficient. Hence we use only sigwait, no
    1200   * sigtimedwait is available. We need to use another user signal, SIGUSR1. Actually
    1201   * SIGUSR1 is also used by exec in Java. So our usage here breaks the exec in Java,
    1202   * for AIX. You cannot use pthread_cond_wait or pthread_delay_np in the signal
    1203   * handler as all synchronization mechanisms just break down.
    1204   */
    1205 
    1206 #if defined(PT_NO_SIGTIMEDWAIT)
    1207 static void null_signal_handler(PRIntn sig)
    1208 {
    1209         return;
    1210 }
    1211 #endif
    1212 
    1213 static void suspend_signal_handler(PRIntn sig)
    1214 {
    1215         PRThread *me = PR_CurrentThread();
    1216 
    1217         PR_ASSERT(me != NULL);
    1218         PR_ASSERT(_PT_IS_GCABLE_THREAD(me));
    1219         PR_ASSERT((me->suspend & PT_THREAD_SUSPENDED) == 0);
    1220 
    1221         PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,
    1222         ("Begin suspend_signal_handler thred %X thread id = %X\n",
    1223                 me, me->id));
    1224 
    1225         /*
    1226          * save stack pointer
    1227          */
    1228         me->sp = &me;
    1229 
    1230         /*
    1231            At this point, the thread's stack pointer has been saved,
    1232            And it is going to enter a wait loop until it is resumed.
    1233            So it is _really_ suspended
    1234         */
    1235 
    1236         me->suspend |= PT_THREAD_SUSPENDED;
    1237 
    1238         /*
    1239          * now, block current thread
    1240          */
    1241 #if defined(PT_NO_SIGTIMEDWAIT)
    1242         pthread_cond_signal(&me->suspendResumeCV);
    1243         while (me->suspend & PT_THREAD_SUSPENDED)
    1244         {
    1245 #if !defined(FREEBSD) && !defined(NETBSD) && !defined(OPENBSD) \
    1246     && !defined(BSDI) && !defined(VMS) && !defined(UNIXWARE) && !defined(DARWIN)  /*XXX*/
    1247         PRIntn rv;
    1248             sigwait(&sigwait_set, &rv);
    1249 #endif
    1250         }
    1251         me->suspend |= PT_THREAD_RESUMED;
    1252         pthread_cond_signal(&me->suspendResumeCV);
    1253 #else /* defined(PT_NO_SIGTIMEDWAIT) */
    1254         while (me->suspend & PT_THREAD_SUSPENDED)
    1255         {
    1256                 PRIntn rv = sigtimedwait(&sigwait_set, NULL, &hundredmillisec);
    1257         PR_ASSERT(-1 == rv);
    1258         }
    1259         me->suspend |= PT_THREAD_RESUMED;
    1260 #endif
    1261 
    1262     /*
    1263      * At this point, thread has been resumed, so set a global condition.
    1264      * The ResumeAll needs to know that this has really been resumed.
    1265      * So the signal handler sets a flag which PR_ResumeAll will reset.
    1266      * The PR_ResumeAll must reset this flag ...
    1267      */
    1268 
    1269     PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,
    1270         ("End suspend_signal_handler thred = %X tid = %X\n", me, me->id));
    1271 }  /* suspend_signal_handler */
    1272 
    1273 static void pt_SuspendSet(PRThread *thred)
    1274 {
    1275     PRIntn rv;
    1276 
    1277     PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,
    1278            ("pt_SuspendSet thred %X thread id = %X\n", thred, thred->id));
    1279 
    1280 
    1281     /*
    1282      * Check the thread state and signal the thread to suspend
    1283      */
    1284 
    1285     PR_ASSERT((thred->suspend & PT_THREAD_SUSPENDED) == 0);
    1286 
    1287     PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,
    1288            ("doing pthread_kill in pt_SuspendSet thred %X tid = %X\n",
    1289            thred, thred->id));
    1290 #if defined(VMS)
    1291     rv = thread_suspend(thred);
    1292 #else
    1293     rv = pthread_kill (thred->id, SIGUSR2);
    1294 #endif
    1295     PR_ASSERT(0 == rv);
    1296 }
    1297 
    1298 static void pt_SuspendTest(PRThread *thred)
    1299 {
    1300     PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,
    1301            ("Begin pt_SuspendTest thred %X thread id = %X\n", thred, thred->id));
    1302 
    1303 
    1304     /*
    1305      * Wait for the thread to be really suspended. This happens when the
    1306      * suspend signal handler stores the stack pointer and sets the state
    1307      * to suspended.
    1308      */
    1309 
    1310 #if defined(PT_NO_SIGTIMEDWAIT)
    1311     pthread_mutex_lock(&thred->suspendResumeMutex);
    1312     while ((thred->suspend & PT_THREAD_SUSPENDED) == 0)
    1313     {
    1314             pthread_cond_timedwait(
    1315                 &thred->suspendResumeCV, &thred->suspendResumeMutex, &onemillisec);
    1316         }
    1317         pthread_mutex_unlock(&thred->suspendResumeMutex);
    1318 #else
    1319     while ((thred->suspend & PT_THREAD_SUSPENDED) == 0)
    1320     {
    1321                 PRIntn rv = sigtimedwait(&sigwait_set, NULL, &onemillisec);
    1322         PR_ASSERT(-1 == rv);
    1323         }
    1324 #endif
    1325 
    1326     PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,
    1327         ("End pt_SuspendTest thred %X tid %X\n", thred, thred->id));
    1328 }  /* pt_SuspendTest */
    1329 
    1330 static void pt_ResumeSet(PRThread *thred)
    1331 {
    1332     PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,
    1333            ("pt_ResumeSet thred %X thread id = %X\n", thred, thred->id));
    1334 
    1335     /*
    1336      * Clear the global state and set the thread state so that it will
    1337      * continue past yield loop in the suspend signal handler
    1338      */
    1339 
    1340     PR_ASSERT(thred->suspend & PT_THREAD_SUSPENDED);
    1341 
    1342 
    1343     thred->suspend &= ~PT_THREAD_SUSPENDED;
    1344 
    1345 #if defined(PT_NO_SIGTIMEDWAIT)
    1346 #if defined(VMS)
    1347         thread_resume(thred);
    1348 #else
    1349         pthread_kill(thred->id, SIGUSR1);
    1350 #endif
    1351 #endif
    1352 
    1353 }  /* pt_ResumeSet */
    1354 
    1355 static void pt_ResumeTest(PRThread *thred)
    1356 {
    1357     PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,
    1358            ("Begin pt_ResumeTest thred %X thread id = %X\n", thred, thred->id));
    1359 
    1360     /*
    1361      * Wait for the threads resume state to change
    1362      * to indicate it is really resumed
    1363      */
    1364 #if defined(PT_NO_SIGTIMEDWAIT)
    1365     pthread_mutex_lock(&thred->suspendResumeMutex);
    1366     while ((thred->suspend & PT_THREAD_RESUMED) == 0)
    1367     {
    1368             pthread_cond_timedwait(
    1369                 &thred->suspendResumeCV, &thred->suspendResumeMutex, &onemillisec);
    1370     }
    1371     pthread_mutex_unlock(&thred->suspendResumeMutex);
    1372 #else
    1373     while ((thred->suspend & PT_THREAD_RESUMED) == 0) {
    1374                 PRIntn rv = sigtimedwait(&sigwait_set, NULL, &onemillisec);
    1375         PR_ASSERT(-1 == rv);
    1376         }
    1377 #endif
    1378 
    1379     thred->suspend &= ~PT_THREAD_RESUMED;
    1380 
    1381     PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, (
    1382         "End pt_ResumeTest thred %X tid %X\n", thred, thred->id));
    1383 }  /* pt_ResumeTest */
    1384 
    1385 static pthread_once_t pt_gc_support_control = PTHREAD_ONCE_INIT;
    1386 
    1387 PR_IMPLEMENT(void) PR_SuspendAll(void)
    1388 {
    1389 #ifdef DEBUG
    1390     PRIntervalTime stime, etime;
    1391 #endif
    1392     PRThread* thred = pt_book.first;
    1393     PRThread *me = PR_CurrentThread();
    1394     int rv;
    1395 
    1396     rv = pthread_once(&pt_gc_support_control, init_pthread_gc_support);
    1397     PR_ASSERT(0 == rv);
    1398     PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_SuspendAll\n"));
    1399     /*
    1400      * Stop all threads which are marked GC able.
    1401      */
    1402     PR_Lock(pt_book.ml);
    1403 #ifdef DEBUG
    1404     suspendAllOn = PR_TRUE;
    1405     stime = PR_IntervalNow();
    1406 #endif
    1407     while (thred != NULL)
    1408     {
    1409             if ((thred != me) && _PT_IS_GCABLE_THREAD(thred))
    1410                 pt_SuspendSet(thred);
    1411         thred = thred->next;
    1412     }
    1413 
    1414     /* Wait till they are really suspended */
    1415     thred = pt_book.first;
    1416     while (thred != NULL)
    1417     {
    1418             if ((thred != me) && _PT_IS_GCABLE_THREAD(thred))
    1419             pt_SuspendTest(thred);
    1420         thred = thred->next;
    1421     }
    1422 
    1423     suspendAllSuspended = PR_TRUE;
    1424 
    1425 #ifdef DEBUG
    1426     etime = PR_IntervalNow();
    1427     PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,\
    1428         ("End PR_SuspendAll (time %dms)\n",
    1429         PR_IntervalToMilliseconds(etime - stime)));
    1430 #endif
    1431 }  /* PR_SuspendAll */
    1432 
    1433 PR_IMPLEMENT(void) PR_ResumeAll(void)
    1434 {
    1435 #ifdef DEBUG
    1436     PRIntervalTime stime, etime;
    1437 #endif
    1438     PRThread* thred = pt_book.first;
    1439     PRThread *me = PR_CurrentThread();
    1440     PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_ResumeAll\n"));
    1441     /*
    1442      * Resume all previously suspended GC able threads.
    1443      */
    1444     suspendAllSuspended = PR_FALSE;
    1445 #ifdef DEBUG
    1446     stime = PR_IntervalNow();
    1447 #endif
    1448 
    1449     while (thred != NULL)
    1450     {
    1451             if ((thred != me) && _PT_IS_GCABLE_THREAD(thred))
    1452             pt_ResumeSet(thred);
    1453         thred = thred->next;
    1454     }
    1455 
    1456     thred = pt_book.first;
    1457     while (thred != NULL)
    1458     {
    1459             if ((thred != me) && _PT_IS_GCABLE_THREAD(thred))
    1460             pt_ResumeTest(thred);
    1461         thred = thred->next;
    1462     }
    1463 
    1464     PR_Unlock(pt_book.ml);
    1465 #ifdef DEBUG
    1466     suspendAllOn = PR_FALSE;
    1467     etime = PR_IntervalNow();
    1468     PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,
    1469         ("End PR_ResumeAll (time %dms)\n",
    1470         PR_IntervalToMilliseconds(etime - stime)));
    1471 #endif
    1472 }  /* PR_ResumeAll */
    1473 
    1474 /* Return the stack pointer for the given thread- used by the GC */
    1475 PR_IMPLEMENT(void *)PR_GetSP(PRThread *thred)
    1476 {
    1477     PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,
    1478             ("in PR_GetSP thred %X thid = %X, sp = %X \n",
    1479             thred, thred->id, thred->sp));
    1480     return thred->sp;
    1481 }  /* PR_GetSP */
    1482 
    1483 #else /* !defined(_PR_DCETHREADS) */
    1484 
    1485 static pthread_once_t pt_gc_support_control = pthread_once_init;
    1486 
    1487 /*
    1488  * For DCE threads, there is no pthread_kill or a way of suspending or resuming a
    1489  * particular thread.  We will just disable the preemption (virtual timer alarm) and
    1490  * let the executing thread finish the garbage collection.  This stops all other threads
    1491  * (GC able or not) and is very inefficient but there is no other choice.
    1492  */
    1493 PR_IMPLEMENT(void) PR_SuspendAll()
    1494 {
    1495     PRIntn rv;
    1496 
    1497     rv = pthread_once(&pt_gc_support_control, init_pthread_gc_support);
    1498     PR_ASSERT(0 == rv);  /* returns -1 on failure */
    1499 #ifdef DEBUG
    1500     suspendAllOn = PR_TRUE;
    1501 #endif
    1502     PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_SuspendAll\n"));
    1503     /*
    1504      * turn off preemption - i.e add virtual alarm signal to the set of
    1505      * blocking signals
    1506      */
    1507     rv = sigprocmask(
    1508         SIG_BLOCK, &javagc_vtalarm_sigmask, &javagc_intsoff_sigmask);
    1509     PR_ASSERT(0 == rv);
    1510     suspendAllSuspended = PR_TRUE;
    1511     PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End PR_SuspendAll\n"));
    1512 }  /* PR_SuspendAll */
    1513 
    1514 PR_IMPLEMENT(void) PR_ResumeAll()
    1515 {
    1516     PRIntn rv;
    1517    
    1518     suspendAllSuspended = PR_FALSE;
    1519     PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_ResumeAll\n"));
    1520     /* turn on preemption - i.e re-enable virtual alarm signal */
    1521 
    1522     rv = sigprocmask(SIG_SETMASK, &javagc_intsoff_sigmask, (sigset_t *)NULL);
    1523     PR_ASSERT(0 == rv);
    1524 #ifdef DEBUG
    1525     suspendAllOn = PR_FALSE;
    1526 #endif
    1527 
    1528     PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End PR_ResumeAll\n"));
    1529 }  /* PR_ResumeAll */
    1530 
    1531 /* Return the stack pointer for the given thread- used by the GC */
    1532 PR_IMPLEMENT(void*)PR_GetSP(PRThread *thred)
    1533 {
    1534         pthread_t tid = thred->id;
    1535         char *thread_tcb, *top_sp;
    1536 
    1537         /*
    1538          * For HPUX DCE threads, pthread_t is a struct with the
    1539          * following three fields (see pthread.h, dce/cma.h):
    1540          *     cma_t_address       field1;
    1541          *     short int           field2;
    1542          *     short int           field3;
    1543          * where cma_t_address is typedef'd to be either void*
    1544          * or char*.
    1545          */
    1546         PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_GetSP\n"));
    1547         thread_tcb = (char*)tid.field1;
    1548         top_sp = *(char**)(thread_tcb + 128);
    1549         PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End PR_GetSP %X \n", top_sp));
    1550         return top_sp;
    1551 }  /* PR_GetSP */
    1552 
    1553 #endif /* !defined(_PR_DCETHREADS) */
    1554 
    1555756/* ptthread.c */
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette