summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwtc%netscape.com <devnull@localhost>1999-12-07 22:23:48 +0000
committerwtc%netscape.com <devnull@localhost>1999-12-07 22:23:48 +0000
commit350689b221fe4c2c78c068da002c36784327917c (patch)
tree083337834658bc671bc4b4204c3b2fb6df5def07
parent57d033ba36eb40ba3c1290055c9d70cd1a1d5a35 (diff)
downloadnspr-hg-350689b221fe4c2c78c068da002c36784327917c.tar.gz
Reworked how thread scanning is done, so thread objects can now be
safely allocated on the thread stack. Moved the GC scanning code into NSPR in a new file called prgcleak.c. (Checkin for Patrick Beard.) Modified files: primpl.h, prinit.c, prthinfo.c, pruthr.c. Added file: prgcleak.c.
-rw-r--r--pr/include/private/primpl.h3
-rw-r--r--pr/src/md/mac/prgcleak.c99
-rw-r--r--pr/src/misc/prinit.c4
-rw-r--r--pr/src/misc/prthinfo.c13
-rw-r--r--pr/src/threads/combined/pruthr.c13
5 files changed, 119 insertions, 13 deletions
diff --git a/pr/include/private/primpl.h b/pr/include/private/primpl.h
index 8e461ddf..9cc3da5f 100644
--- a/pr/include/private/primpl.h
+++ b/pr/include/private/primpl.h
@@ -1606,6 +1606,9 @@ extern void _PR_CleanupTPD(void);
extern void _PR_Cleanup(void);
extern void _PR_LogCleanup(void);
extern void _PR_InitLayerCache(void);
+#ifdef GC_LEAK_DETECTOR
+extern void _PR_InitGarbageCollector(void);
+#endif
extern PRBool _pr_initialized;
extern void _PR_ImplicitInitialization(void);
diff --git a/pr/src/md/mac/prgcleak.c b/pr/src/md/mac/prgcleak.c
new file mode 100644
index 00000000..49b38b60
--- /dev/null
+++ b/pr/src/md/mac/prgcleak.c
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public License
+ * Version 1.1 (the "NPL"); you may not use this file except in
+ * compliance with the NPL. You may obtain a copy of the NPL at
+ * http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the NPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
+ * for the specific language governing rights and limitations under the
+ * NPL.
+ *
+ * The Initial Developer of this code under the NPL is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1999 Netscape Communications Corporation. All Rights
+ * Reserved.
+ *
+ * Contributor(s):
+ * Patrick Beard <beard@netscape.com>
+ */
+
+/*
+ * prgcleak.c
+ */
+
+#ifdef GC_LEAK_DETECTOR
+
+/* for FILE */
+#include <stdio.h>
+
+/* NSPR stuff */
+#include "generic_threads.h"
+#include "primpl.h"
+
+extern FILE *GC_stdout, *GC_stderr;
+
+extern void GC_gcollect(void);
+extern void GC_clear_roots(void);
+
+static PRStatus PR_CALLBACK scanner(PRThread* t, void** baseAddr, PRUword
+count, void* closure)
+{
+ char* begin = (char*)baseAddr;
+ char* end = (char*)(baseAddr + count);
+ GC_mark_range_proc marker = (GC_mark_range_proc) closure;
+ marker(begin, end);
+ return PR_SUCCESS;
+}
+
+static void mark_all_stacks(GC_mark_range_proc marker)
+{
+ PR_ScanStackPointers(&scanner, (void *)marker);
+}
+
+static void locker(void* mutex)
+{
+ if (_PR_MD_CURRENT_CPU())
+ PR_Lock(mutex);
+}
+
+static void unlocker(void* mutex)
+{
+ if (_PR_MD_CURRENT_CPU())
+ PR_Unlock(mutex);
+}
+
+static void stopper(void* unused)
+{
+ if (_PR_MD_CURRENT_CPU())
+ PR_SuspendAll();
+}
+
+static void starter(void* unused)
+{
+ if (_PR_MD_CURRENT_CPU())
+ PR_ResumeAll();
+}
+
+void _PR_InitGarbageCollector()
+{
+ void* mutex;
+
+ /* redirect GC's stderr to catch startup leaks. */
+ GC_stderr = fopen("StartupLeaks", "w");
+
+ mutex = PR_NewLock();
+ PR_ASSERT(mutex != NULL);
+
+ GC_generic_init_threads(&mark_all_stacks, mutex,
+ &locker, &unlocker,
+ &stopper, &starter);
+}
+
+void _PR_ShutdownGarbageCollector()
+{
+ /* do anything you need to shut down the collector. */
+}
+
+#endif /* GC_LEAK_DETECTOR */
diff --git a/pr/src/misc/prinit.c b/pr/src/misc/prinit.c
index 6c580443..8054228c 100644
--- a/pr/src/misc/prinit.c
+++ b/pr/src/misc/prinit.c
@@ -171,6 +171,10 @@ static void _PR_InitStuff(void)
_pr_sleeplock = PR_NewLock();
PR_ASSERT(NULL != _pr_sleeplock);
+#ifdef GC_LEAK_DETECTOR
+ _PR_InitGarbageCollector();
+#endif
+
_PR_InitThreads(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
#ifdef WIN16
diff --git a/pr/src/misc/prthinfo.c b/pr/src/misc/prthinfo.c
index 67415420..2cfac1b2 100644
--- a/pr/src/misc/prthinfo.c
+++ b/pr/src/misc/prthinfo.c
@@ -140,6 +140,19 @@ PR_ThreadScanStackPointers(PRThread* t,
if (status != PR_SUCCESS)
return status;
}
+
+#ifdef GC_LEAK_DETECTOR
+ /*
+ ** if the thread was allocated on its own stack, conservatively
+ ** scan the thread object itself to keep all data structures
+ ** referenced by the thread visible to the garbage collector.
+ */
+ if (t->threadAllocatedOnStack) {
+ status = scanFun(t, (void**)t, (sizeof(PRThread) + 3) / sizeof(void*), scanClosure);
+ if (status != PR_SUCCESS)
+ return status;
+ }
+#endif
return PR_SUCCESS;
}
diff --git a/pr/src/threads/combined/pruthr.c b/pr/src/threads/combined/pruthr.c
index 492ced6c..77d5a87b 100644
--- a/pr/src/threads/combined/pruthr.c
+++ b/pr/src/threads/combined/pruthr.c
@@ -1227,17 +1227,6 @@ PR_IMPLEMENT(PRThread*) _PR_CreateThread(PRThreadType type,
return NULL;
}
-#if defined(GC_LEAK_DETECTOR)
- top = stack->stackTop;
- /* Allocate thread in heap, so GC will scan it. */
- thread = (PRThread*) PR_CALLOC(sizeof(PRThread));
- if (!thread) {
- PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
- return NULL;
- }
- stack->thr = thread;
- thread->threadAllocatedOnStack = 0;
-#else
/* Allocate thread object and per-thread data off the top of the stack*/
top = stack->stackTop;
#ifdef HAVE_STACK_GROWING_UP
@@ -1262,8 +1251,6 @@ PR_IMPLEMENT(PRThread*) _PR_CreateThread(PRThreadType type,
stack->thr = thread;
memset(thread, 0, sizeof(PRThread));
thread->threadAllocatedOnStack = 1;
-#endif
-
#else
thread = _PR_MD_CREATE_USER_THREAD(stackSize, start, arg);
if (!thread) {