home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / nsprpub / pr / src / misc / prinit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  13.2 KB  |  520 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /*
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  * 
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  * 
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. #include "primpl.h"
  20. #include <string.h>
  21.  
  22. PRLogModuleInfo *_pr_clock_lm;
  23. PRLogModuleInfo *_pr_cmon_lm;
  24. PRLogModuleInfo *_pr_io_lm;
  25. PRLogModuleInfo *_pr_cvar_lm;
  26. PRLogModuleInfo *_pr_mon_lm;
  27. PRLogModuleInfo *_pr_linker_lm;
  28. PRLogModuleInfo *_pr_sched_lm;
  29. PRLogModuleInfo *_pr_thread_lm;
  30. PRLogModuleInfo *_pr_gc_lm;
  31.  
  32. PRFileDesc *_pr_stdin;
  33. PRFileDesc *_pr_stdout;
  34. PRFileDesc *_pr_stderr;
  35.  
  36. #if !defined(_PR_PTHREADS)
  37.  
  38. PRCList _pr_active_local_threadQ =
  39.             PR_INIT_STATIC_CLIST(&_pr_active_local_threadQ);
  40. PRCList _pr_active_global_threadQ =
  41.             PR_INIT_STATIC_CLIST(&_pr_active_global_threadQ);
  42.  
  43. _MDLock  _pr_cpuLock;           /* lock for the CPU Q */
  44. PRCList _pr_cpuQ = PR_INIT_STATIC_CLIST(&_pr_cpuQ);
  45.  
  46. PRUint32 _pr_utid;
  47.  
  48. PRUintn _pr_userActive;
  49. PRUintn _pr_systemActive;
  50. PRUintn _pr_maxPTDs;
  51.  
  52. #ifdef _PR_LOCAL_THREADS_ONLY
  53.  
  54. struct _PRCPU     *_pr_currentCPU;
  55. PRThread     *_pr_currentThread;
  56. PRThread     *_pr_lastThread;
  57. PRInt32     _pr_intsOff;
  58.  
  59. #endif /* _PR_LOCAL_THREADS_ONLY */
  60.  
  61. /* Lock protecting all "termination" condition variables of all threads */
  62. PRLock *_pr_terminationCVLock;
  63.  
  64. #endif /* !defined(_PR_PTHREADS) */
  65.  
  66. static void _PR_InitCallOnce(void);
  67. static void _PR_InitStuff(void);
  68.  
  69. /************************************************************************/
  70. /**************************IDENTITY AND VERSIONING***********************/
  71. /************************************************************************/
  72. PR_IMPLEMENT(PRBool) PR_VersionCheck(const char *importedVersion)
  73. {
  74.     /*
  75.     ** This is the secret handshake algorithm. Right now it requires
  76.     ** an exact match. Later it should get more tricky.
  77.     */
  78.     return ((0 == strcmp(importedVersion, PR_VERSION)) ? PR_TRUE : PR_FALSE);
  79. }  /* PR_VersionCheck */
  80.  
  81.  
  82. PRBool _pr_initialized = PR_FALSE;
  83.  
  84. PR_IMPLEMENT(PRBool) PR_Initialized(void)
  85. {
  86.     return _pr_initialized;
  87. }
  88.  
  89. static void _PR_InitStuff()
  90. {
  91.     if (_pr_initialized) return;
  92.     _pr_initialized = PR_TRUE;
  93.  
  94.     (void) PR_GetPageSize();
  95.  
  96.     _pr_clock_lm = PR_NewLogModule("clock");
  97.     _pr_cmon_lm = PR_NewLogModule("cmon");
  98.     _pr_io_lm = PR_NewLogModule("io");
  99.     _pr_mon_lm = PR_NewLogModule("mon");
  100.     _pr_linker_lm = PR_NewLogModule("linker");
  101.     _pr_cvar_lm = PR_NewLogModule("cvar");
  102.     _pr_sched_lm = PR_NewLogModule("sched");
  103.     _pr_thread_lm = PR_NewLogModule("thread");
  104.     _pr_gc_lm = PR_NewLogModule("gc");
  105.       
  106.     /* NOTE: These init's cannot depend on _PR_MD_CURRENT_THREAD() */ 
  107.     _PR_MD_EARLY_INIT();
  108.  
  109.     _PR_InitAtomic();
  110.     _PR_InitLocks();
  111.     _PR_InitSegs();
  112.     _PR_InitStacks();
  113.     _PR_InitTPD();
  114.     _PR_InitEnv();
  115.     _PR_InitLayerCache();
  116.  
  117.     _PR_InitThreads(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
  118.     
  119. #ifdef WIN16
  120.     {
  121.     PRInt32 top;   /* artificial top of stack, win16 */
  122.     _pr_top_of_task_stack = (char *) ⊤
  123.     }
  124. #endif    
  125.  
  126. #ifndef _PR_GLOBAL_THREADS_ONLY
  127.     _PR_InitCPUs();
  128. #endif
  129.  
  130. /*
  131.  * XXX: call _PR_InitMem only on those platforms for which nspr implements
  132.  *    malloc, for now.
  133.  */
  134. #ifdef _PR_OVERRIDE_MALLOC
  135.     _PR_InitMem();
  136. #endif
  137.  
  138.     _PR_InitCMon();
  139.     _PR_InitIO();
  140.     _PR_InitNet();
  141.     _PR_InitClock();
  142. #ifdef PR_LOGGING
  143.     _PR_InitLog();
  144. #endif
  145.     _PR_InitLinker();
  146.     _PR_InitCallOnce();
  147.     _PR_InitDtoa();
  148.  
  149.     _PR_MD_FINAL_INIT();
  150. }
  151.  
  152. void _PR_ImplicitInitialization()
  153. {
  154.     _PR_InitStuff();
  155.  
  156.     /* Enable interrupts */
  157. #ifndef _PR_GLOBAL_THREADS_ONLY
  158.     _PR_MD_START_INTERRUPTS();
  159. #endif
  160.  
  161. }
  162.  
  163. PR_IMPLEMENT(void) PR_DisableClockInterrupts(void)
  164. {
  165. #if !defined(_PR_PTHREADS)
  166.     if (!_pr_initialized) {
  167.         _PR_InitStuff();
  168.     } else {
  169.         _PR_MD_DISABLE_CLOCK_INTERRUPTS();
  170.     }
  171. #endif
  172. }
  173.  
  174. PR_IMPLEMENT(void) PR_BlockClockInterrupts(void)
  175. {
  176. #if !defined(_PR_PTHREADS)
  177.         _PR_MD_BLOCK_CLOCK_INTERRUPTS();
  178. #endif
  179. }
  180.  
  181. PR_IMPLEMENT(void) PR_UnblockClockInterrupts(void)
  182. {
  183. #if !defined(_PR_PTHREADS)
  184.         _PR_MD_UNBLOCK_CLOCK_INTERRUPTS();
  185. #endif
  186. }
  187.  
  188. PR_IMPLEMENT(void) PR_Init(
  189.     PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs)
  190. {
  191. #if defined(XP_MAC)
  192. #pragma unused (type, priority, maxPTDs)
  193. #endif
  194.  
  195.     _PR_ImplicitInitialization();
  196. }
  197.  
  198. PR_IMPLEMENT(PRIntn) PR_Initialize(
  199.     PRPrimordialFn prmain, PRIntn argc, char **argv, PRUintn maxPTDs)
  200. {
  201. #if defined(XP_MAC)
  202. #pragma unused (maxPTDs)
  203. #endif
  204.  
  205.     PRIntn rv;
  206.     _PR_ImplicitInitialization();
  207.     rv = prmain(argc, argv);
  208.     PR_Cleanup();
  209.     return rv;
  210. }  /* PR_Initialize */
  211.  
  212. /*
  213.  *-----------------------------------------------------------------------
  214.  *
  215.  * _PR_CleanupBeforeExit --
  216.  *
  217.  *   Perform the cleanup work before exiting the process. 
  218.  *   We first do the cleanup generic to all platforms.  Then
  219.  *   we call _PR_MD_CLEANUP_BEFORE_EXIT(), where platform-dependent
  220.  *   cleanup is done.  This function is used by PR_Cleanup().
  221.  *
  222.  * See also: PR_Cleanup().
  223.  *
  224.  *-----------------------------------------------------------------------
  225.  */
  226. #if defined(_PR_PTHREADS)
  227.     /* see ptthread.c */
  228. #else
  229. static void
  230. _PR_CleanupBeforeExit(void)
  231. {
  232. /* 
  233. Do not make any calls here other than to destroy resources.  For example,
  234. do not make any calls that eventually may end up in PR_Lock.  Because the
  235. thread is destroyed, can not access current thread any more.
  236. */
  237.     _PR_CleanupTPD();
  238.     if (_pr_terminationCVLock)
  239.     /*
  240.      * In light of the comment above, this looks real suspicious.
  241.      * I'd go so far as to say it's just a problem waiting to happen.
  242.      */
  243.         PR_DestroyLock(_pr_terminationCVLock);
  244.  
  245.     _PR_MD_CLEANUP_BEFORE_EXIT();
  246. }
  247. #endif /* defined(_PR_PTHREADS) */
  248.  
  249. /*
  250.  *----------------------------------------------------------------------
  251.  *
  252.  * PR_Cleanup --
  253.  *
  254.  *   Perform a graceful shutdown of the NSPR runtime.  PR_Cleanup() may
  255.  *   only be called from the primordial thread, typically at the
  256.  *   end of the main() function.  It returns when it has completed
  257.  *   its platform-dependent duty and the process must not make any other
  258.  *   NSPR library calls prior to exiting from main().
  259.  *
  260.  *   PR_Cleanup() first blocks the primordial thread until all the
  261.  *   other user (non-system) threads, if any, have terminated.
  262.  *   Then it performs cleanup in preparation for exiting the process.
  263.  *   PR_Cleanup() does not exit the primordial thread (which would
  264.  *   in turn exit the process).
  265.  *   
  266.  *   PR_Cleanup() only responds when it is called by the primordial
  267.  *   thread. Calls by any other thread are silently ignored.
  268.  *
  269.  * See also: PR_ExitProcess()
  270.  *
  271.  *----------------------------------------------------------------------
  272.  */
  273. #if defined(_PR_PTHREADS)
  274.     /* see ptthread.c */
  275. #else
  276.  
  277. PR_IMPLEMENT(PRStatus) PR_Cleanup()
  278. {
  279.     PRThread *me = PR_GetCurrentThread();
  280.     PR_ASSERT((NULL != me) && (me->flags & _PR_PRIMORDIAL));
  281.     if ((NULL != me) && (me->flags & _PR_PRIMORDIAL))
  282.     {
  283.  
  284.         PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_Cleanup: shutting down NSPR"));
  285.  
  286.         /*
  287.          * No more recycling of threads
  288.          */
  289.         _pr_recycleThreads = 0;
  290.  
  291.         /*
  292.          * Wait for all other user (non-system/daemon) threads
  293.          * to terminate.
  294.          */
  295.         PR_Lock(_pr_activeLock);
  296.         while (_pr_userActive > _pr_primordialExitCount) {
  297.             PR_WaitCondVar(_pr_primordialExitCVar, PR_INTERVAL_NO_TIMEOUT);
  298.         }
  299.         PR_Unlock(_pr_activeLock);
  300.  
  301. #if defined(WIN16)
  302.         _PR_ShutdownLinker();
  303. #endif
  304.         /* Release the primordial thread's private data, etc. */
  305.         _PR_CleanupThread(me);
  306.  
  307.         _PR_MD_STOP_INTERRUPTS();
  308.  
  309.         PR_LOG(_pr_thread_lm, PR_LOG_MIN,
  310.                 ("PR_Cleanup: clean up before destroying thread"));
  311.     #ifdef PR_LOGGING
  312.         _PR_LogCleanup();
  313.     #endif
  314.  
  315.         /*
  316.          * This part should look like the end of _PR_NativeRunThread
  317.          * and _PR_UserRunThread.
  318.          */
  319.         if (_PR_IS_NATIVE_THREAD(me)) {
  320.             _PR_MD_EXIT_THREAD(me);
  321.             _PR_NativeDestroyThread(me);
  322.         } else {
  323.             _PR_UserDestroyThread(me);
  324.             PR_DELETE(me->stack);
  325.             PR_DELETE(me);
  326.         }
  327.  
  328.         /*
  329.          * XXX: We are freeing the heap memory here so that Purify won't
  330.          * complain, but we should also free other kinds of resources
  331.          * that are allocated by the _PR_InitXXX() functions.
  332.          * Ideally, for each _PR_InitXXX(), there should be a corresponding
  333.          * _PR_XXXCleanup() that we can call here.
  334.          */
  335.         _PR_CleanupBeforeExit();
  336.         return PR_SUCCESS;
  337.     }
  338.     return PR_FAILURE;
  339. }
  340. #endif /* defined(_PR_PTHREADS) */
  341.  
  342. /*
  343.  *------------------------------------------------------------------------
  344.  * PR_ProcessExit --
  345.  * 
  346.  *   Cause an immediate, nongraceful, forced termination of the process.
  347.  *   It takes a PRIntn argument, which is the exit status code of the
  348.  *   process.
  349.  *   
  350.  * See also: PR_Cleanup()
  351.  *
  352.  *------------------------------------------------------------------------
  353.  */
  354.  
  355. #if defined(_PR_PTHREADS)
  356.     /* see ptthread.c */
  357. #else
  358. PR_IMPLEMENT(void) PR_ProcessExit(PRIntn status)
  359. {
  360.     _PR_MD_EXIT(status);
  361. }
  362.  
  363. #endif /* defined(_PR_PTHREADS) */
  364.  
  365. PR_IMPLEMENT(PRProcessAttr *)
  366. PR_NewProcessAttr(void)
  367. {
  368.     PRProcessAttr *attr;
  369.  
  370.     attr = PR_NEWZAP(PRProcessAttr);
  371.     if (!attr) {
  372.         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
  373.     }
  374.     return attr;
  375. }
  376.  
  377. PR_IMPLEMENT(void)
  378. PR_ResetProcessAttr(PRProcessAttr *attr)
  379. {
  380.     memset(attr, 0, sizeof(*attr));
  381. }
  382.  
  383. PR_IMPLEMENT(void)
  384. PR_DestroyProcessAttr(PRProcessAttr *attr)
  385. {
  386.     PR_DELETE(attr);
  387. }
  388.  
  389. PR_IMPLEMENT(void)
  390. PR_SetStdioRedirect(
  391.     PRProcessAttr *attr,
  392.     PRSpecialFD stdioFd,
  393.     PRFileDesc *redirectFd
  394. )
  395. {
  396.     switch (stdioFd) {
  397.         case PR_StandardInput:
  398.             attr->stdinFd = redirectFd;
  399.             break;
  400.         case PR_StandardOutput:
  401.             attr->stdoutFd = redirectFd;
  402.             break;
  403.         case PR_StandardError:
  404.             attr->stderrFd = redirectFd;
  405.             break;
  406.         default:
  407.             PR_ASSERT(0);
  408.     }
  409. }
  410.  
  411. PR_IMPLEMENT(PRProcess*) PR_CreateProcess(
  412.     const char *path,
  413.     char *const *argv,
  414.     char *const *envp,
  415.     const PRProcessAttr *attr)
  416. {
  417.     return _PR_MD_CREATE_PROCESS(path, argv, envp, attr);
  418. }  /* PR_CreateProcess */
  419.  
  420. PR_IMPLEMENT(PRStatus) PR_CreateProcessDetached(
  421.     const char *path,
  422.     char *const *argv,
  423.     char *const *envp,
  424.     const PRProcessAttr *attr)
  425. {
  426.     PRProcess *process;
  427.     PRStatus rv;
  428.  
  429.     process = PR_CreateProcess(path, argv, envp, attr);
  430.     if (NULL == process) {
  431.     return PR_FAILURE;
  432.     }
  433.     rv = PR_DetachProcess(process);
  434.     PR_ASSERT(PR_SUCCESS == rv);
  435.     if (rv == PR_FAILURE) {
  436.     PR_DELETE(process);
  437.     return PR_FAILURE;
  438.     }
  439.     return PR_SUCCESS;
  440. }
  441.  
  442. PR_IMPLEMENT(PRStatus) PR_DetachProcess(PRProcess *process)
  443. {
  444.     return _PR_MD_DETACH_PROCESS(process);
  445. }
  446.  
  447. PR_IMPLEMENT(PRStatus) PR_WaitProcess(PRProcess *process, PRInt32 *exitCode)
  448. {
  449.     return _PR_MD_WAIT_PROCESS(process, exitCode);
  450. }  /* PR_WaitProcess */
  451.  
  452. PR_IMPLEMENT(PRStatus) PR_KillProcess(PRProcess *process)
  453. {
  454.     return _PR_MD_KILL_PROCESS(process);
  455. }
  456.  
  457. /*
  458.  ********************************************************************
  459.  *
  460.  * Module initialization
  461.  *
  462.  ********************************************************************
  463.  */
  464.  
  465. static struct {
  466.     PRLock *ml;
  467.     PRCondVar *cv;
  468. } mod_init;
  469.  
  470. static void _PR_InitCallOnce() {
  471.     mod_init.ml = PR_NewLock();
  472.     PR_ASSERT(NULL != mod_init.ml);
  473.     mod_init.cv = PR_NewCondVar(mod_init.ml);
  474.     PR_ASSERT(NULL != mod_init.cv);
  475. }
  476.  
  477.  
  478. PR_IMPLEMENT(PRStatus) PR_CallOnce(
  479.     PRCallOnceType *once,
  480.     PRCallOnceFN    func)
  481. {
  482.     if (!_pr_initialized) _PR_ImplicitInitialization();
  483.  
  484.     if (!once->initialized) {
  485.     if (PR_AtomicSet(&once->inProgress, 1) == 0) {
  486.         once->status = (*func)();
  487.         PR_Lock(mod_init.ml);
  488.         once->initialized = 1;
  489.         PR_NotifyAllCondVar(mod_init.cv);
  490.         PR_Unlock(mod_init.ml);
  491.     } else {
  492.         PR_Lock(mod_init.ml);
  493.         while (!once->initialized) {
  494.         PR_WaitCondVar(mod_init.cv, PR_INTERVAL_NO_TIMEOUT);
  495.             }
  496.         PR_Unlock(mod_init.ml);
  497.     }
  498.     }
  499.     return once->status;
  500. }
  501.  
  502. PRBool _PR_Obsolete(const char *obsolete, const char *preferred)
  503. {
  504. #if defined(DEBUG)
  505. #ifndef XP_MAC
  506.     PR_fprintf(
  507.         PR_STDERR, "'%s' is obsolete. Use '%s' instead.\n",
  508.         obsolete, (NULL == preferred) ? "something else" : preferred);
  509.     return PR_FALSE;
  510. #else
  511. #pragma unused (obsolete, preferred)
  512.     return PR_FALSE;
  513. #endif
  514. #endif
  515. }  /* _PR_Obsolete */
  516.  
  517. /* prinit.c */
  518.  
  519.  
  520.