home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / nsprpub / lib / msgc / src / prgcapi.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  7.5 KB  |  333 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 <stdarg.h>
  20. #include <string.h>
  21. #include <stdio.h>
  22. #include "prenv.h"
  23. #include "prmem.h"
  24. #include "prmon.h"
  25. #include "prlog.h"
  26. #include "prthread.h"
  27. #if defined(XP_MAC)
  28. #include "pprthred.h"
  29. #else
  30. #include "private/pprthred.h"
  31. #endif
  32. #include "gcint.h"
  33.  
  34. /*
  35. ** Generic GC implementation independent code for the NSPR GC
  36. */
  37.  
  38. RootFinder *_pr_rootFinders;
  39.  
  40. CollectorType *_pr_collectorTypes;
  41.  
  42. /* GC State information */
  43. GCInfo _pr_gcData;
  44.  
  45. GCBeginGCHook *_pr_beginGCHook;
  46. void *_pr_beginGCHookArg;
  47. GCBeginGCHook *_pr_endGCHook;
  48. void *_pr_endGCHookArg;
  49.  
  50. GCBeginFinalizeHook *_pr_beginFinalizeHook;
  51. void *_pr_beginFinalizeHookArg;
  52. GCBeginFinalizeHook *_pr_endFinalizeHook;
  53. void *_pr_endFinalizeHookArg;
  54.  
  55. FILE *_pr_dump_file;
  56. int _pr_do_a_dump;
  57. GCLockHook *_pr_GCLockHook;
  58.  
  59. extern PRLogModuleInfo *_pr_msgc_lm;
  60.  
  61. /************************************************************************/
  62.  
  63. static PRStatus PR_CALLBACK
  64. pr_ScanOneThread(PRThread* t, void** addr, PRUword count, void* closure)
  65. {
  66. #if defined(XP_MAC)
  67. #pragma unused (t, closure)
  68. #endif
  69.  
  70.     _pr_gcData.processRootBlock(addr, count);
  71.     return PR_SUCCESS;
  72. }
  73.  
  74. /*
  75. ** Scan all of the threads C stack's and registers, looking for "root"
  76. ** pointers into the GC heap. These are the objects that the GC cannot
  77. ** move and are considered "live" by the GC. Caller has stopped all of
  78. ** the threads from running.
  79. */
  80. static void PR_CALLBACK ScanThreads(void *arg)
  81. {
  82.     PR_ScanStackPointers(pr_ScanOneThread, arg);
  83. }
  84.  
  85. /************************************************************************/
  86.  
  87. PR_IMPLEMENT(GCInfo *) PR_GetGCInfo(void)
  88. {
  89.     return &_pr_gcData;
  90. }
  91.  
  92.  
  93. PR_IMPLEMENT(PRInt32) PR_RegisterType(GCType *t)
  94. {
  95.     CollectorType *ct, *ect;
  96.     int rv = -1;
  97.  
  98.     LOCK_GC();
  99.     ct = &_pr_collectorTypes[0];
  100.     ect = &_pr_collectorTypes[FREE_MEMORY_TYPEIX];
  101.     for (; ct < ect; ct++) {
  102.     if (ct->flags == 0) {
  103.         ct->gctype = *t;
  104.         ct->flags = _GC_TYPE_BUSY;
  105.         if (0 != ct->gctype.finalize) {
  106.         ct->flags |= _GC_TYPE_FINAL;
  107.         }
  108.         if (0 != ct->gctype.getWeakLinkOffset) {
  109.         ct->flags |= _GC_TYPE_WEAK;
  110.         }
  111.         rv = ct - &_pr_collectorTypes[0];
  112.         break;
  113.     }
  114.     }
  115.     UNLOCK_GC();
  116.     return rv;
  117. }
  118.  
  119. PR_IMPLEMENT(PRStatus) PR_RegisterRootFinder(
  120.     GCRootFinder f, char *name, void *arg)
  121. {
  122.     RootFinder *rf = PR_NEWZAP(RootFinder);
  123.     if (rf) {
  124.         rf->func = f;
  125.         rf->name = name;
  126.         rf->arg = arg;
  127.  
  128.         LOCK_GC();
  129.         rf->next = _pr_rootFinders;
  130.         _pr_rootFinders = rf;
  131.         UNLOCK_GC();
  132.         return PR_SUCCESS;
  133.     }
  134.     return PR_FAILURE;
  135. }
  136.  
  137.  
  138. PR_IMPLEMENT(int) PR_RegisterGCLockHook(GCLockHookFunc* f, void *arg)
  139. {
  140.  
  141.     GCLockHook *rf = 0;
  142.  
  143.     rf = (GCLockHook*) calloc(1, sizeof(GCLockHook));
  144.     if (rf) {
  145.     rf->func = f;
  146.     rf->arg = arg;
  147.  
  148.     LOCK_GC();
  149.         /* first dummy node */
  150.         if (! _pr_GCLockHook) {
  151.           _pr_GCLockHook = (GCLockHook*) calloc(1, sizeof(GCLockHook));
  152.           _pr_GCLockHook->next = _pr_GCLockHook;
  153.           _pr_GCLockHook->prev = _pr_GCLockHook;
  154.         }
  155.  
  156.         rf->next = _pr_GCLockHook;
  157.         rf->prev = _pr_GCLockHook->prev;
  158.         _pr_GCLockHook->prev->next = rf;
  159.         _pr_GCLockHook->prev = rf;
  160.     UNLOCK_GC();
  161.     return 0;
  162.     }
  163.     return -1;
  164. }
  165.  
  166. /*
  167. PR_IMPLEMENT(void) PR_SetGCLockHook(GCLockHook *hook, void *arg)
  168. {
  169.     LOCK_GC();
  170.     _pr_GCLockHook = hook;
  171.     _pr_GCLockHookArg2 = arg;
  172.     UNLOCK_GC();
  173. }
  174.  
  175. PR_IMPLEMENT(void) PR_GetGCLockHook(GCLockHook **hook, void **arg)
  176. {
  177.     LOCK_GC();
  178.     *hook = _pr_GCLockHook;
  179.     *arg = _pr_GCLockHookArg2;
  180.     UNLOCK_GC();
  181. }
  182. */
  183.  
  184.   
  185. PR_IMPLEMENT(void) PR_SetBeginGCHook(GCBeginGCHook *hook, void *arg)
  186. {
  187.     LOCK_GC();
  188.     _pr_beginGCHook = hook;
  189.     _pr_beginGCHookArg = arg;
  190.     UNLOCK_GC();
  191. }
  192.  
  193. PR_IMPLEMENT(void) PR_GetBeginGCHook(GCBeginGCHook **hook, void **arg)
  194. {
  195.     LOCK_GC();
  196.     *hook = _pr_beginGCHook;
  197.     *arg = _pr_beginGCHookArg;
  198.     UNLOCK_GC();
  199. }
  200.  
  201. PR_IMPLEMENT(void) PR_SetEndGCHook(GCEndGCHook *hook, void *arg)
  202. {
  203.     LOCK_GC();
  204.     _pr_endGCHook = hook;
  205.     _pr_endGCHookArg = arg;
  206.     UNLOCK_GC();
  207. }
  208.  
  209. PR_IMPLEMENT(void) PR_GetEndGCHook(GCEndGCHook **hook, void **arg)
  210. {
  211.     LOCK_GC();
  212.     *hook = _pr_endGCHook;
  213.     *arg = _pr_endGCHookArg;
  214.     UNLOCK_GC();
  215. }
  216.  
  217. PR_IMPLEMENT(void) PR_SetBeginFinalizeHook(GCBeginFinalizeHook *hook, void *arg)
  218. {
  219.     LOCK_GC();
  220.     _pr_beginFinalizeHook = hook;
  221.     _pr_beginFinalizeHookArg = arg;
  222.     UNLOCK_GC();
  223. }
  224.  
  225. PR_IMPLEMENT(void) PR_GetBeginFinalizeHook(GCBeginFinalizeHook **hook, 
  226.                                            void **arg)
  227. {
  228.     LOCK_GC();
  229.     *hook = _pr_beginFinalizeHook;
  230.     *arg = _pr_beginFinalizeHookArg;
  231.     UNLOCK_GC();
  232. }
  233.  
  234. PR_IMPLEMENT(void) PR_SetEndFinalizeHook(GCEndFinalizeHook *hook, void *arg)
  235. {
  236.     LOCK_GC();
  237.     _pr_endFinalizeHook = hook;
  238.     _pr_endFinalizeHookArg = arg;
  239.     UNLOCK_GC();
  240. }
  241.  
  242. PR_IMPLEMENT(void) PR_GetEndFinalizeHook(GCEndFinalizeHook **hook, void **arg)
  243. {
  244.     LOCK_GC();
  245.     *hook = _pr_endFinalizeHook;
  246.     *arg = _pr_endFinalizeHookArg;
  247.     UNLOCK_GC();
  248. }
  249.  
  250. #ifdef DEBUG
  251. #include "prprf.h"
  252.  
  253. #if defined(WIN16)
  254. static FILE *tracefile = 0;
  255. #endif
  256.  
  257. PR_IMPLEMENT(void) GCTrace(char *fmt, ...)
  258. {    
  259.     va_list ap;
  260.     char buf[400];
  261.  
  262.     va_start(ap, fmt);
  263.     PR_vsnprintf(buf, sizeof(buf), fmt, ap);
  264.     va_end(ap);
  265. #if defined(WIN16)
  266.     if ( tracefile == 0 )
  267.     {
  268.         tracefile = fopen( "xxxGCtr", "w" );
  269.     }
  270.     fprintf(tracefile, "%s\n", buf );
  271.     fflush(tracefile);
  272. #else
  273.     PR_LOG(_pr_msgc_lm, PR_LOG_ALWAYS, ("%s", buf));
  274. #endif
  275. }
  276. #endif
  277.  
  278. void _PR_InitGC(PRWord flags)
  279. {
  280.     static char firstTime = 1;
  281.  
  282.     if (!firstTime) return;
  283.     firstTime = 0;
  284.  
  285.     _MD_InitGC();
  286.  
  287.     if (flags == 0) {
  288.     char *ev = PR_GetEnv("GCLOG");
  289.     if (ev && ev[0]) {
  290.         flags = atoi(ev);
  291.     }
  292.     }
  293.     _pr_gcData.flags = flags;
  294.  
  295.     _pr_gcData.lock = PR_NewMonitor();
  296.  
  297.     _pr_collectorTypes = (CollectorType*) PR_CALLOC(256 * sizeof(CollectorType));
  298.  
  299.     PR_RegisterRootFinder(ScanThreads, "scan threads", 0);
  300.     PR_RegisterRootFinder(_PR_ScanFinalQueue, "scan final queue", 0);
  301. }
  302.  
  303. extern void pr_FinalizeOnExit(void);
  304.  
  305. #ifdef DEBUG
  306. #ifdef GC_STATS
  307. PR_PUBLIC_API(void) PR_PrintGCAllocStats(void);
  308. #endif 
  309. #endif 
  310.   
  311. PR_IMPLEMENT(void) 
  312. PR_ShutdownGC(PRBool finalizeOnExit)
  313. {
  314.     /* first finalize all the objects in the heap */
  315.     if (finalizeOnExit) {
  316.         pr_FinalizeOnExit();
  317.     }
  318.  
  319. #ifdef DEBUG
  320. #ifdef GC_STATS
  321.     PR_PrintGCAllocStats();
  322. #endif /* GC_STATS */
  323. #endif /* DEBUG */
  324.  
  325.     /* then the chance for any future allocations */
  326.  
  327.     /* finally delete the gc heap */
  328.  
  329.     /* write me */
  330. }
  331.  
  332. /******************************************************************************/
  333.