+#include "private/gc_priv.h"
+
#if defined(GC_WIN32_THREADS)
-#include "private/gc_priv.h"
#include <windows.h>
#ifdef CYGWIN32
# undef pthread_create
# undef pthread_sigmask
# undef pthread_join
+# undef pthread_detach
# undef dlopen
# define DEBUG_CYGWIN_THREADS 0
int GC_thread_is_registered (void)
{
+#if defined(GC_DLL) || defined(GC_INSIDE_DLL)
+ /* Registered by DllMain */
return 1;
+#else
+ /* FIXME: */
+ return 0;
+#endif
+}
+
+void GC_allow_register_threads (void)
+{
+ /* No-op for GC pre-v7. */
+}
+
+int GC_register_my_thread (struct GC_stack_base *sb)
+{
+# if defined(GC_DLL) || defined(GC_INSIDE_DLL)
+ /* Registered by DllMain. */
+ return GC_DUPLICATE;
+# else
+ /* TODO: Implement. */
+ return GC_UNIMPLEMENTED;
+# endif
+}
+
+void GC_register_altstack (void *stack, int stack_size, void *altstack, int altstack_size)
+{
}
/*
#ifdef __GNUC__
__inline__
#endif
-LONG GC_get_max_thread_index()
+static LONG GC_get_max_thread_index()
{
LONG my_max = GC_max_thread_index;
/* Must still be in_use, since nobody else can store our thread_id. */
i++) {}
if (i > my_max) {
- WARN("Removing nonexisiting thread %ld\n", (GC_word)thread_id);
+ WARN("Removing nonexistent thread %ld\n", (GC_word)thread_id);
} else {
GC_delete_gc_thread(thread_table+i);
}
# endif
}
+/* Defined in misc.c */
+extern CRITICAL_SECTION GC_write_cs;
+
void GC_stop_world()
{
DWORD thread_id = GetCurrentThreadId();
if (!GC_thr_initialized) ABORT("GC_stop_world() called before GC_thr_init()");
GC_please_stop = TRUE;
+# ifndef CYGWIN32
+ EnterCriticalSection(&GC_write_cs);
+# endif /* !CYGWIN32 */
for (i = 0; i <= GC_get_max_thread_index(); i++)
if (thread_table[i].stack_base != 0
&& thread_table[i].id != thread_id) {
# endif
continue;
}
- if (SuspendThread(thread_table[i].handle) == (DWORD)-1)
- ABORT("SuspendThread failed");
+ if (SuspendThread(thread_table[i].handle) == (DWORD)-1) {
+ thread_table[i].stack_base = 0; /* prevent stack from being pushed */
+# ifndef CYGWIN32
+ /* this breaks pthread_join on Cygwin, which is guaranteed to */
+ /* only see user pthreads */
+ thread_table[i].in_use = FALSE;
+ CloseHandle(thread_table[i].handle);
+# endif
+ }
# endif
thread_table[i].suspended = TRUE;
}
+# ifndef CYGWIN32
+ LeaveCriticalSection(&GC_write_cs);
+# endif /* !CYGWIN32 */
}
void GC_start_world()
# if defined(I386)
PUSH4(Edi,Esi,Ebx,Edx), PUSH2(Ecx,Eax), PUSH1(Ebp);
sp = (ptr_t)context.Esp;
+# elif defined(X86_64)
+ PUSH4(Rax,Rcx,Rdx,Rbx); PUSH2(Rbp, Rsi); PUSH1(Rdi);
+ PUSH4(R8, R9, R10, R11); PUSH4(R12, R13, R14, R15);
+ sp = (ptr_t)context.Rsp;
# elif defined(ARM32)
PUSH4(R0,R1,R2,R3),PUSH4(R4,R5,R6,R7),PUSH4(R8,R9,R10,R11),PUSH1(R12);
sp = (ptr_t)context.Sp;
* We avoid acquiring locks here, since this doesn't seem to be preemptable.
* Pontus Rydin suggests wrapping the thread start routine instead.
*/
-#ifdef GC_DLL
-BOOL WINAPI DllMain(HINSTANCE inst, ULONG reason, LPVOID reserved)
+#if defined(GC_DLL) || defined(GC_INSIDE_DLL)
+BOOL WINAPI GC_DllMain(HINSTANCE inst, ULONG reason, LPVOID reserved)
{
switch (reason) {
case DLL_PROCESS_ATTACH: