+
+ return me;
+}
+
+int GC_thread_register_foreign (void *base_addr)
+{
+ struct start_info si = { 0, }; /* stacked for legibility & locking */
+ GC_thread me;
+
+# ifdef DEBUG_THREADS
+ GC_printf1( "GC_thread_register_foreign %p\n", &si );
+# endif
+
+ si.flags = FOREIGN_THREAD;
+
+ if (!parallel_initialized) GC_init_parallel();
+ LOCK();
+ if (!GC_thr_initialized) GC_thr_init();
+
+ UNLOCK();
+
+ me = GC_start_routine_head(&si, base_addr, NULL, NULL);
+
+ return me != NULL;
+}
+
+void * GC_start_routine(void * arg)
+{
+ int dummy;
+ struct start_info * si = arg;
+ void * result;
+ GC_thread me;
+ ThreadStartFn start;
+ void *start_arg;
+
+ me = GC_start_routine_head (arg, &dummy, &start, &start_arg);
+
+ pthread_cleanup_push(GC_thread_exit_proc, 0);
+# ifdef DEBUG_THREADS
+ GC_printf1("start_routine = 0x%lx\n", start);
+# endif