+2007-07-23 Hans Boehm <Hans.Boehm@hp.com>
+
+ * alloc.c (GC_stopped_mark): Call GC_add_current_malloc_heap()
+ while world is still running.
+ * os_dep.c (GC_is_heap_base): Don't call GC_add_current_malloc_heap()
+ with world stopped.
+ * include/gc.h (GC_INIT for cygwin): Always call GC_add_roots.
+ * misc.c (GC_init/GC_init_inner): Perform all work in
+ GC_init_inner.
+ * Makefile.direct: Expand -DUSE_MUNMAP comment.
+
+2007-07-23 Hans Boehm <Hans.Boehm@hp.com> (really Jim Marshall)
+
+ * include/gc.h: Define uintptr_t explicitly for VC++6.
+ * msvc_dbg.c (GetModuleBase): Revert to strcat if strcat_s doesn't
+ exist.
+
2007-07-02 Hans Boehm <Hans.Boehm@hp.com>
* version.h, configure.ac, doc/README: Change to version 7.1alpha1.
# -DUSE_MUNMAP causes memory to be returned to the OS under the right
# circumstances. This currently disables VM-based incremental collection.
# This is currently experimental, and works only under some Unix,
-# Linux and Windows versions.
+# Linux and Windows versions. Requires -DUSE_MMAP, even under Windows,
+# where USE_MMAP doesn't do anything.
# -DMMAP_STACKS (for Solaris threads) Use mmap from /dev/zero rather than
# GC_scratch_alloc() to get stack memory.
# -DPRINT_BLACK_LIST Whenever a black list entry is added, i.e. whenever
if (GC_print_stats)
GET_TIME(start_time);
+# if !defined(REDIRECT_MALLOC) && (defined(MSWIN32) || defined(MSWINCE))
+ GC_add_current_malloc_heap();
+# endif
# if defined(REGISTER_LIBRARIES_EARLY)
GC_cond_register_dynamic_libraries();
# endif
DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId );
+# if defined(_MSC_VER) && _MSC_VER >= 1200 && !defined(_UINTPTR_T_DEFINED)
+ typedef unsigned long uintptr_t;
+# endif
GC_API uintptr_t GC_beginthreadex(
void *security, unsigned stack_size,
# define GC_MIN(x,y) ((x) < (y) ? (x) : (y))
# define GC_DATASTART ((void *) GC_MIN(_data_start__, _bss_start__))
# define GC_DATAEND ((void *) GC_MAX(_data_end__, _bss_end__))
-# if defined(GC_DLL)
-# define GC_INIT() { GC_add_roots(GC_DATASTART, GC_DATAEND); \
+# define GC_INIT() { GC_add_roots(GC_DATASTART, GC_DATAEND); \
GC_gcollect(); /* For blacklisting. */}
-# else
- /* Main program init not required */
-# define GC_INIT() { GC_init(); }
-# endif
+ /* Required at least if GC is in dll. And doesn't hurt. */
# endif
# if defined(_AIX)
extern int _data[], _end[];
extern void GC_init_parallel(void);
# endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */
+/* FIXME: The GC_init/GC_init_inner distinction should go away. */
void GC_init(void)
{
- DCL_LOCK_STATE;
-
-#if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS)
- if (!GC_is_initialized) {
- BOOL (WINAPI *pfn) (LPCRITICAL_SECTION, DWORD) = NULL;
- HMODULE hK32 = GetModuleHandleA("kernel32.dll");
- if (hK32)
- pfn = (BOOL (WINAPI *) (LPCRITICAL_SECTION, DWORD))
- GetProcAddress (hK32,
- "InitializeCriticalSectionAndSpinCount");
- if (pfn)
- pfn(&GC_allocate_ml, 4000);
- else
- InitializeCriticalSection (&GC_allocate_ml);
- }
-#endif /* MSWIN32 */
-
- LOCK();
+ /* LOCK(); -- no longer does anything this early. */
GC_init_inner();
- UNLOCK();
-
-# if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
- /* Make sure marker threads and started and thread local */
- /* allocation is initialized, in case we didn't get */
- /* called from GC_init_parallel(); */
- {
- GC_init_parallel();
- }
-# endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */
-
-# if defined(DYNAMIC_LOADING) && defined(DARWIN)
- {
- /* This must be called WITHOUT the allocation lock held
- and before any threads are created */
- extern void GC_init_dyld();
- GC_init_dyld();
- }
-# endif
+ /* UNLOCK(); */
}
#if defined(MSWIN32) || defined(MSWINCE)
word initial_heap_sz = (word)MINHINCR;
if (GC_is_initialized) return;
+
+ /* Note that although we are nominally called with the */
+ /* allocation lock held, the allocation lock is now */
+ /* only really acquired once a second thread is forked.*/
+ /* And the initialization code needs to run before */
+ /* then. Thus we really don't hold any locks, and can */
+ /* in fact safely initialize them here. */
+ GC_ASSERT(!GC_need_to_lock);
+# if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS)
+ if (!GC_is_initialized) {
+ BOOL (WINAPI *pfn) (LPCRITICAL_SECTION, DWORD) = NULL;
+ HMODULE hK32 = GetModuleHandleA("kernel32.dll");
+ if (hK32)
+ pfn = (BOOL (WINAPI *) (LPCRITICAL_SECTION, DWORD))
+ GetProcAddress (hK32,
+ "InitializeCriticalSectionAndSpinCount");
+ if (pfn)
+ pfn(&GC_allocate_ml, 4000);
+ else
+ InitializeCriticalSection (&GC_allocate_ml);
+ }
+#endif /* MSWIN32 */
# if defined(MSWIN32) || defined(MSWINCE)
InitializeCriticalSection(&GC_write_cs);
# endif
GC_register_finalizer_no_order);
}
# endif
+
+ /* The rest of this again assumes we don't really hold */
+ /* the allocation lock. */
+# if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
+ /* Make sure marker threads and started and thread local */
+ /* allocation is initialized, in case we didn't get */
+ /* called from GC_init_parallel(); */
+ {
+ GC_init_parallel();
+ }
+# endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */
+
+# if defined(DYNAMIC_LOADING) && defined(DARWIN)
+ {
+ /* This must be called WITHOUT the allocation lock held
+ and before any threads are created */
+ extern void GC_init_dyld();
+ GC_init_dyld();
+ }
+# endif
}
void GC_enable_incremental(void)
// Save and restore current directory around SymLoadModule, see KB article Q189780
GetCurrentDirectoryA(sizeof(curDir), curDir);
GetModuleFileNameA(NULL, exePath, sizeof(exePath));
+#if defined(_MSC_VER) && _MSC_VER == 1200
+ /* use strcat for VC6 */
+ strcat(exePath, "\\..");
+#else
strcat_s(exePath, sizeof(exePath), "\\..");
+#endif /* _MSC_VER >= 1200 */
SetCurrentDirectoryA(exePath);
#ifdef _DEBUG
GetCurrentDirectoryA(sizeof(exePath), exePath);
unsigned i;
# ifndef REDIRECT_MALLOC
- static word last_gc_no = (word)(-1);
-
- if (last_gc_no != GC_gc_no) {
- GC_add_current_malloc_heap();
- last_gc_no = GC_gc_no;
- }
if (GC_root_size > GC_max_root_size) GC_max_root_size = GC_root_size;
if (GC_is_malloc_heap_base(p)) return TRUE;
# endif