void * GC_win32_start_inner(struct GC_stack_base *sb, LPVOID arg) { void * ret; thread_args *args = (thread_args *)arg; # if DEBUG_WIN32_THREADS GC_printf("thread 0x%x starting...\n", GetCurrentThreadId()); # endif GC_register_my_thread(sb); /* This waits for an in-progress GC. */ /* Clear the thread entry even if we exit with an exception. */ /* This is probably pointless, since an uncaught exception is */ /* supposed to result in the process being killed. */ #ifndef __GNUC__ __try { #endif /* __GNUC__ */ ret = (void *)(size_t)args->start (args->param); #ifndef __GNUC__ } __finally { #endif /* __GNUC__ */ GC_unregister_my_thread(); GC_free(args); #ifndef __GNUC__ } #endif /* __GNUC__ */ # if DEBUG_WIN32_THREADS GC_printf("thread 0x%x returned from start routine.\n", GetCurrentThreadId()); # endif return ret; }
void * GC_CALLBACK on_thread_exit_inner (struct GC_stack_base * sb, void * arg) { int res = GC_register_my_thread (sb); pthread_t t; GC_pthread_create (&t, NULL, entry, NULL); if (res == GC_SUCCESS) GC_unregister_my_thread (); return NULL; }
void * GC_CALLBACK on_thread_exit_inner (struct GC_stack_base * sb, void * arg) { int res = GC_register_my_thread (sb); pthread_t t; int creation_res; /* Used to suppress a warning about */ /* unchecked pthread_create() result. */ pthread_attr_t attr; if (pthread_attr_init(&attr) != 0 || pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0) { fprintf(stderr, "Thread attribute init or setdetachstate failed\n"); exit(2); } creation_res = GC_pthread_create(&t, &attr, entry, NULL); (void)pthread_attr_destroy(&attr); if (res == GC_SUCCESS) GC_unregister_my_thread (); return arg ? (void*)(GC_word)creation_res : 0; }
void xmlvm_destroy(java_lang_Thread* mainThread) { java_lang_Thread_threadTerminating__(mainThread); #ifdef XMLVM_ENABLE_STACK_TRACES JAVA_LONG nativeThreadId = (JAVA_LONG) pthread_self(); destroyStackForExitingThread(nativeThreadId); #endif // Unregister the current thread. Only an explicitly registered // thread (i.e. for which GC_register_my_thread() returns GC_SUCCESS) // is allowed (and required) to call this function. (As a special // exception, it is also allowed to once unregister the main thread.) #ifndef XMLVM_NO_GC GC_unregister_my_thread(); #endif // Call pthread_exit(0) so that the main thread does not terminate until // the other threads have finished pthread_exit(0); }
EXTERN bool neko_thread_register( bool t ) { # if !defined(NEKO_THREADS) return 0; # elif defined(NEKO_WINDOWS) struct GC_stack_base sb; int r; if( !t ) return GC_unregister_my_thread() == GC_SUCCESS; if( GC_get_stack_base(&sb) != GC_SUCCESS ) return 0; r = GC_register_my_thread(&sb); return( r == GC_SUCCESS || r == GC_DUPLICATE ); # else // since the API is only available on GC 7.0, // we will do our best to locate it dynamically static gc_stack_ptr get_sb = NULL, my_thread = NULL; static std_func unreg_my_thread = NULL; if( !t && unreg_my_thread != NULL ) { return unreg_my_thread() == GC_SUCCESS; } else if( my_thread != NULL ) { __stack_base sb; int r; if( get_sb(&sb) != GC_SUCCESS ) return 0; r = my_thread(&sb); return( r == GC_SUCCESS || r == GC_DUPLICATE ); } else { void *self = dlopen(NULL,0); my_thread = (gc_stack_ptr)dlsym(self,"GC_register_my_thread"); get_sb = (gc_stack_ptr)dlsym(self,"GC_get_stack_base"); unreg_my_thread = (std_func)dlsym(self,"GC_unregister_my_thread"); if( my_thread == NULL ) my_thread = do_nothing; if( get_sb == NULL ) get_sb = do_nothing; if( unreg_my_thread == NULL ) unreg_my_thread = (std_func)do_nothing; return neko_thread_register(t); } # endif }
/* At the end of a thread other than the main thread, we need to unregister the thread with the garbage collector. */ static void conservative_thread_end() { GC_unregister_my_thread(); }
void GC_endthreadex(unsigned retval) { GC_unregister_my_thread(); _endthreadex(retval); }
void WINAPI GC_ExitThread(DWORD dwExitCode) { GC_unregister_my_thread(); ExitThread(dwExitCode); }