+typedef void * (GC_CALLBACK * GC_fn_type) (void * client_data);
+GC_API void * GC_CALL GC_call_with_alloc_lock (GC_fn_type fn,
+ void * client_data);
+
+/* These routines are intended to explicitly notify the collector */
+/* of new threads. Often this is unnecessary because thread creation */
+/* is implicitly intercepted by the collector, using header-file */
+/* defines, or linker-based interception. In the long run the intent */
+/* is to always make redundant registration safe. In the short run, */
+/* this is being implemented a platform at a time. */
+/* The interface is complicated by the fact that we probably will not */
+/* ever be able to automatically determine the stack base for thread */
+/* stacks on all platforms. */
+
+/* Structure representing the base of a thread stack. On most */
+/* platforms this contains just a single address. */
+struct GC_stack_base {
+ void * mem_base; /* Base of memory stack. */
+# if defined(__ia64) || defined(__ia64__) || defined(_M_IA64)
+ void * reg_base; /* Base of separate register stack. */
+# endif
+};
+
+typedef void * (GC_CALLBACK * GC_stack_base_func)(struct GC_stack_base *sb,
+ void *arg);
+
+/* Call a function with a stack base structure corresponding to */
+/* somewhere in the GC_call_with_stack_base frame. This often can */
+/* be used to provide a sufficiently accurate stack base. And we */
+/* implement it everywhere. */
+GC_API void * GC_CALL GC_call_with_stack_base(GC_stack_base_func fn,
+ void *arg);
+
+/* Explicitly enable GC_register_my_thread() invocation. */
+/* Done implicitly if a GC thread-creation function is called (or */
+/* DllMain-based thread registration is enabled). Otherwise, it must */
+/* be called from the main (or any previously registered) thread */
+/* between the collector initialization and the first explicit */
+/* registering of a thread (it should be called as late as possible). */
+GC_API void GC_CALL GC_allow_register_threads(void);
+
+/* Register the current thread, with the indicated stack base, as */
+/* a new thread whose stack(s) should be traced by the GC. If it */
+/* is not implicitly called by the GC, this must be called before a */
+/* thread can allocate garbage collected memory, or assign pointers */
+/* to the garbage collected heap. Once registered, a thread will be */
+/* stopped during garbage collections. */
+/* This call must be previously enabled (see above). */
+/* This should never be called from the main thread, where it is */
+/* always done implicitly. This is normally done implicitly if GC_ */
+/* functions are called to create the thread, e.g. by defining */
+/* GC_THREADS and including gc.h (which redefines some system */
+/* functions) before calling the system thread creation function. */
+/* It is also always done implicitly under win32 with DllMain-based */
+/* thread registration enabled. Except in this latter case, explicit */
+/* calls are normally required for threads created by third-party */
+/* libraries. */
+#define GC_SUCCESS 0
+#define GC_DUPLICATE 1 /* Was already registered. */
+#define GC_NO_THREADS 2 /* No thread support in GC. */
+#define GC_UNIMPLEMENTED 3 /* Not yet implemented on this platform. */
+GC_API int GC_CALL GC_register_my_thread(struct GC_stack_base *);
+
+/* Unregister the current thread. Only an explicity registered thread */
+/* (i.e. for which GC_register_my_thread() returns GC_SUCCESS) is */
+/* allowed (and required) to call this function. The thread may no */
+/* longer allocate garbage collected memory or manipulate pointers to */
+/* the garbage collected heap after making this call. */
+/* Specifically, if it wants to return or otherwise communicate a */
+/* pointer to the garbage-collected heap to another thread, it must */
+/* do this before calling GC_unregister_my_thread, most probably */
+/* by saving it in a global data structure. */
+GC_API int GC_CALL GC_unregister_my_thread(void);
+
+/* Attempt to fill in the GC_stack_base structure with the stack base */
+/* for this thread. This appears to be required to implement anything */
+/* like the JNI AttachCurrentThread in an environment in which new */
+/* threads are not automatically registered with the collector. */
+/* It is also unfortunately hard to implement well on many platforms. */
+/* Returns GC_SUCCESS or GC_UNIMPLEMENTED. */
+GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *);