/* Explicitly dump the GC state. This is most often called from the */
/* debugger, or by setting the GC_DUMP_REGULARLY environment variable, */
/* but it may be useful to call it from client code during debugging. */
-/* If name is specified (and non-NULL), it is printed to help */
+/* The current collection number is printed in the header of the dump. */
+/* Acquires the GC lock to avoid data races. */
+/* Defined only if the library has been compiled without NO_DEBUGGING. */
+GC_API void GC_CALL GC_dump(void);
+
+/* The same as GC_dump but allows to specify the name of dump and does */
+/* not acquire the lock. If name is non-NULL, it is printed to help */
/* identifying individual dumps. Otherwise the current collection */
/* number is used as the name. */
/* Defined only if the library has been compiled without NO_DEBUGGING. */
GC_API void GC_CALL GC_dump_named(const char * /* name */);
-GC_API void GC_CALL GC_dump(void); /* = GC_dump_named(NULL) */
/* Dump information about each block of every GC memory section. */
/* Defined only if the library has been compiled without NO_DEBUGGING. */
void GC_print_hblkfreelist(void);
void GC_print_heap_sects(void);
void GC_print_static_roots(void);
-/* void GC_dump(void); - declared in gc.h */
extern word GC_fo_entries; /* should be visible in extra/MacOS.c */
#ifndef NO_DEBUGGING
GC_EXTERN GC_bool GC_dump_regularly;
/* Generate regular debugging dumps. */
-# define COND_DUMP if (EXPECT(GC_dump_regularly, FALSE)) GC_dump(); \
- else COND_DUMP_CHECKS
+# define COND_DUMP if (EXPECT(GC_dump_regularly, FALSE)) { \
+ GC_dump_named(NULL); \
+ } else COND_DUMP_CHECKS
#else
# define COND_DUMP COND_DUMP_CHECKS
#endif
/* LOCK(); -- no longer does anything this early. */
word initial_heap_sz;
IF_CANCEL(int cancel_state;)
+# if defined(GC_ASSERTIONS) && defined(GC_ALWAYS_MULTITHREADED)
+ DCL_LOCK_STATE;
+# endif
if (EXPECT(GC_is_initialized, TRUE)) return;
# ifdef REDIRECT_MALLOC
GC_pcr_install();
# endif
GC_is_initialized = TRUE;
+# if defined(GC_ASSERTIONS) && defined(GC_ALWAYS_MULTITHREADED)
+ LOCK(); /* just to set GC_lock_holder */
+# endif
# if defined(GC_PTHREADS) || defined(GC_WIN32_THREADS)
-# if defined(GC_ASSERTIONS) && defined(GC_ALWAYS_MULTITHREADED)
- DCL_LOCK_STATE;
- LOCK(); /* just to set GC_lock_holder */
- GC_thr_init();
- UNLOCK();
-# else
- GC_thr_init();
-# endif
+ GC_thr_init();
# ifdef PARALLEL_MARK
/* Actually start helper threads. */
+# if defined(GC_ASSERTIONS) && defined(GC_ALWAYS_MULTITHREADED)
+ UNLOCK();
+# endif
GC_start_mark_threads_inner();
+# if defined(GC_ASSERTIONS) && defined(GC_ALWAYS_MULTITHREADED)
+ LOCK();
+# endif
# endif
# endif
COND_DUMP;
/* Get black list set up and/or incremental GC started */
- if (!GC_dont_precollect || GC_incremental) {
-# if defined(GC_ASSERTIONS) && defined(GC_ALWAYS_MULTITHREADED)
- LOCK();
- GC_gcollect_inner();
- UNLOCK();
-# else
- GC_gcollect_inner();
-# endif
- }
+ if (!GC_dont_precollect || GC_incremental) {
+ GC_gcollect_inner();
+ }
+# if defined(GC_ASSERTIONS) && defined(GC_ALWAYS_MULTITHREADED)
+ UNLOCK();
+# endif
# ifdef STUBBORN_ALLOC
GC_stubborn_init();
# endif
#if !defined(NO_DEBUGGING)
GC_API void GC_CALL GC_dump(void)
{
+ DCL_LOCK_STATE;
+
+ LOCK();
GC_dump_named(NULL);
+ UNLOCK();
}
GC_API void GC_CALL GC_dump_named(const char *name)