(*GC_amiga_allocwrapper_do)(a,GC_malloc_atomic_ignore_off_page)
#endif /* _AMIGA && !GC_AMIGA_MAKINGLIB */
+
+typedef void (*GC_exit_func)(const int status);
+
+GC_API void GC_CALL GC_set_exit_func(GC_exit_func fn);
+
+typedef void (*GC_abort_func)(const char * const msg);
+
+GC_API void GC_CALL GC_set_abort_func(GC_abort_func fn);
+
+#if defined(GC_LINUX_THREADS)
+GC_API void GC_CALL GC_set_suspend_signal(const int sig);
+GC_API void GC_CALL GC_set_thr_restart_signal(const int sig);
+#endif
+
+
#ifdef __cplusplus
} /* end of extern "C" */
#endif
# ifdef PCR
# define EXIT() PCR_Base_Exit(1,PCR_waitForever)
# else
-# define EXIT() (void)exit(1)
+ GC_API_PRIV void GC_exit(int status);
+# define EXIT() GC_exit(1)
# endif
/* Print warning message, e.g. almost out of memory. */
# define SIG_SUSPEND SIGLOST
# else
/* Linuxthreads itself uses SIGUSR1 and SIGUSR2. */
-# define SIG_SUSPEND SIGPWR
+# define SIG_SUSPEND GC_get_suspend_signal()
+# define SIG_THR_RESTART GC_get_thr_restart_signal()
+# define SIG_SUSPEND_DEFAULT SIGPWR
+# define SIG_THR_RESTART_DEFAULT SIGXCPU
# endif
# elif !defined(GC_OPENBSD_THREADS) && !defined(GC_DARWIN_THREADS)
# if defined(_SIGRTMIN)
#ifdef THREADS
- GC_API int GC_CALL GC_get_suspend_signal(void)
- {
+static int suspend_signal = SIG_SUSPEND_DEFAULT;
+static int thread_restart_signal = SIG_THR_RESTART_DEFAULT;
+
+void GC_set_suspend_signal(const int sig)
+{
+ if (GC_is_initialized) return;
+ suspend_signal = sig;
+}
+
+void GC_set_thread_restart_signal(const int sig)
+{
+ if (GC_is_initialized) return;
+ thread_restart_signal = sig;
+}
+
+
+ GC_API int GC_CALL GC_get_suspend_signal(void)
+ {
# ifdef SIG_SUSPEND
- return SIG_SUSPEND;
+ return suspend_signal;
# else
return -1;
# endif
- }
+ }
-# if defined(GC_DARWIN_THREADS) || defined(GC_WIN32_THREADS)
GC_API int GC_CALL GC_get_thr_restart_signal(void)
{
+# ifdef SIG_THR_RESTART
+ return thread_restart_signal;
+# else
return -1; /* GC does not use signals to restart threads. */
+# endif
}
-# endif
+
#endif /* THREADS */
#if !defined(_MAX_PATH) && (defined(MSWIN32) || defined(MSWINCE) \
return(result);
}
+static GC_abort_func abort_fn = NULL; /* JCB */
+
+GC_API void GC_CALL GC_set_abort_func(GC_abort_func fn)
+{
+ abort_fn = fn;
+}
+
+
#if !defined(PCR) && !defined(SMALL_CONFIG)
/* Print (or display) a message before abort. msg must not be NULL. */
void GC_on_abort(const char *msg)
{
+ if (abort_fn) abort_fn(msg);
# if defined(MSWIN32)
# ifndef DONT_USE_USER32_DLL
/* Use static binding to "user32.dll". */
}
#endif /* !SMALL_CONFIG */
+static GC_exit_func exit_fn = NULL;
+
+void GC_exit(int status)
+{
+ if (exit_fn) exit_fn(status);
+ (void) exit(status);
+}
+
+GC_API void GC_CALL GC_set_exit_func(GC_exit_func fn)
+{
+ exit_fn = fn;
+}
+
+
GC_API void GC_CALL GC_enable(void)
{
DCL_LOCK_STATE;