PR_IMPLEMENT(PRStatus) PR_Cleanup() { PRThread *me = PR_GetCurrentThread(); PR_ASSERT((NULL != me) && (me->flags & _PR_PRIMORDIAL)); if ((NULL != me) && (me->flags & _PR_PRIMORDIAL)) { PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_Cleanup: shutting down NSPR")); /* * No more recycling of threads */ _pr_recycleThreads = 0; /* * Wait for all other user (non-system/daemon) threads * to terminate. */ PR_Lock(_pr_activeLock); while (_pr_userActive > _pr_primordialExitCount) { PR_WaitCondVar(_pr_primordialExitCVar, PR_INTERVAL_NO_TIMEOUT); } PR_Unlock(_pr_activeLock); #if defined(WIN16) _PR_ShutdownLinker(); #endif /* Release the primordial thread's private data, etc. */ _PR_CleanupThread(me); _PR_MD_STOP_INTERRUPTS(); PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_Cleanup: clean up before destroying thread")); #ifdef PR_LOGGING _PR_LogCleanup(); #endif /* * This part should look like the end of _PR_NativeRunThread * and _PR_UserRunThread. */ if (_PR_IS_NATIVE_THREAD(me)) { _PR_MD_EXIT_THREAD(me); _PR_NativeDestroyThread(me); } else { _PR_UserDestroyThread(me); PR_DELETE(me->stack); PR_DELETE(me); } /* * XXX: We are freeing the heap memory here so that Purify won't * complain, but we should also free other kinds of resources * that are allocated by the _PR_InitXXX() functions. * Ideally, for each _PR_InitXXX(), there should be a corresponding * _PR_XXXCleanup() that we can call here. */ _PR_CleanupBeforeExit(); return PR_SUCCESS; } return PR_FAILURE; }
PR_IMPLEMENT(PRStatus) PR_Cleanup() { PRThread *me = PR_GetCurrentThread(); PR_ASSERT((NULL != me) && (me->flags & _PR_PRIMORDIAL)); if ((NULL != me) && (me->flags & _PR_PRIMORDIAL)) { PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_Cleanup: shutting down NSPR")); /* * No more recycling of threads */ _pr_recycleThreads = 0; /* * Wait for all other user (non-system/daemon) threads * to terminate. */ PR_Lock(_pr_activeLock); while (_pr_userActive > _pr_primordialExitCount) { PR_WaitCondVar(_pr_primordialExitCVar, PR_INTERVAL_NO_TIMEOUT); } if (me->flags & _PR_SYSTEM) { _pr_systemActive--; } else { _pr_userActive--; } PR_Unlock(_pr_activeLock); #ifdef IRIX _PR_MD_PRE_CLEANUP(me); /* * The primordial thread must now be running on the primordial cpu */ PR_ASSERT((_PR_IS_NATIVE_THREAD(me)) || (me->cpu->id == 0)); #endif _PR_MD_EARLY_CLEANUP(); _PR_CleanupMW(); _PR_CleanupTime(); _PR_CleanupDtoa(); _PR_CleanupCallOnce(); _PR_ShutdownLinker(); _PR_CleanupNet(); _PR_CleanupIO(); /* Release the primordial thread's private data, etc. */ _PR_CleanupThread(me); _PR_MD_STOP_INTERRUPTS(); PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_Cleanup: clean up before destroying thread")); _PR_LogCleanup(); /* * This part should look like the end of _PR_NativeRunThread * and _PR_UserRunThread. */ if (_PR_IS_NATIVE_THREAD(me)) { _PR_MD_EXIT_THREAD(me); _PR_NativeDestroyThread(me); } else { _PR_UserDestroyThread(me); PR_DELETE(me->stack); PR_DELETE(me); } /* * XXX: We are freeing the heap memory here so that Purify won't * complain, but we should also free other kinds of resources * that are allocated by the _PR_InitXXX() functions. * Ideally, for each _PR_InitXXX(), there should be a corresponding * _PR_XXXCleanup() that we can call here. */ #ifdef WINNT _PR_CleanupCPUs(); #endif _PR_CleanupThreads(); _PR_CleanupCMon(); PR_DestroyLock(_pr_sleeplock); _pr_sleeplock = NULL; _PR_CleanupLayerCache(); _PR_CleanupEnv(); _PR_CleanupStacks(); _PR_CleanupBeforeExit(); _pr_initialized = PR_FALSE; return PR_SUCCESS; } return PR_FAILURE; }