| version 1.5, 2002/07/24 08:00:12 |
version 1.6, 2003/06/24 05:11:34 |
|
|
| #if defined(GC_WIN32_THREADS) |
#if defined(GC_WIN32_THREADS) |
| |
|
| #include "private/gc_priv.h" |
#include "private/gc_priv.h" |
| |
#include <windows.h> |
| |
|
| #ifdef CYGWIN32 |
#ifdef CYGWIN32 |
| # include <errno.h> |
# include <errno.h> |
|
|
| |
|
| #endif |
#endif |
| |
|
| |
#ifndef MAX_THREADS |
| #if 0 |
# define MAX_THREADS 64 |
| #define STRICT |
|
| #include <windows.h> |
|
| #endif |
#endif |
| |
|
| #define MAX_THREADS 64 |
|
| |
|
| struct thread_entry { |
struct thread_entry { |
| LONG in_use; |
LONG in_use; |
| DWORD id; |
DWORD id; |
| Line 58 void GC_push_thread_structures GC_PROTO((void)) |
|
| Line 55 void GC_push_thread_structures GC_PROTO((void)) |
|
| for (i = 0; i < MAX_THREADS; i++) |
for (i = 0; i < MAX_THREADS; i++) |
| if (thread_table[i].in_use) GC_push_all((ptr_t)&(thread_table[i].status),(ptr_t)(&(thread_table[i].status)+1)); |
if (thread_table[i].in_use) GC_push_all((ptr_t)&(thread_table[i].status),(ptr_t)(&(thread_table[i].status)+1)); |
| } |
} |
| #endif |
# endif |
| } |
} |
| |
|
| void GC_stop_world() |
void GC_stop_world() |
| Line 87 void GC_stop_world() |
|
| Line 84 void GC_stop_world() |
|
| DWORD exitCode; |
DWORD exitCode; |
| if (GetExitCodeThread(thread_table[i].handle,&exitCode) && |
if (GetExitCodeThread(thread_table[i].handle,&exitCode) && |
| exitCode != STILL_ACTIVE) { |
exitCode != STILL_ACTIVE) { |
| thread_table[i].stack = 0; /* prevent stack from being pushed */ |
thread_table[i].stack = 0; /* prevent stack from being pushed */ |
| # ifndef CYGWIN32 |
# ifndef CYGWIN32 |
| /* this breaks pthread_join on Cygwin, which is guaranteed to only see user pthreads */ |
/* this breaks pthread_join on Cygwin, which is guaranteed to */ |
| |
/* only see user pthreads */ |
| thread_table[i].in_use = FALSE; |
thread_table[i].in_use = FALSE; |
| CloseHandle(thread_table[i].handle); |
CloseHandle(thread_table[i].handle); |
| BZERO((void *)(&thread_table[i].context), sizeof(CONTEXT)); |
BZERO((void *)(&thread_table[i].context), sizeof(CONTEXT)); |
| #endif |
# endif |
| continue; |
continue; |
| } |
} |
| if (SuspendThread(thread_table[i].handle) == (DWORD)-1) |
if (SuspendThread(thread_table[i].handle) == (DWORD)-1) |
| ABORT("SuspendThread failed"); |
ABORT("SuspendThread failed"); |
| Line 372 void GC_get_next_stack(char *start, char **lo, char ** |
|
| Line 370 void GC_get_next_stack(char *start, char **lo, char ** |
|
| if (*lo < start) *lo = start; |
if (*lo < start) *lo = start; |
| } |
} |
| |
|
| #if !defined(MSWINCE) && !(defined(__MINGW32__) && !defined(_DLL)) |
#if !defined(CYGWIN32) |
| |
|
| HANDLE WINAPI GC_CreateThread( |
#if !defined(MSWINCE) && defined(GC_DLL) |
| |
|
| |
/* We register threads from DllMain */ |
| |
|
| |
GC_API HANDLE GC_CreateThread( |
| LPSECURITY_ATTRIBUTES lpThreadAttributes, |
LPSECURITY_ATTRIBUTES lpThreadAttributes, |
| DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, |
DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, |
| LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId ) |
LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId ) |
| Line 383 HANDLE WINAPI GC_CreateThread( |
|
| Line 385 HANDLE WINAPI GC_CreateThread( |
|
| lpParameter, dwCreationFlags, lpThreadId); |
lpParameter, dwCreationFlags, lpThreadId); |
| } |
} |
| |
|
| #else /* !defined(MSWINCE) && !(defined(__MINGW32__) && !defined(_DLL)) */ |
#else /* defined(MSWINCE) || !defined(GC_DLL)) */ |
| |
|
| |
/* We have no DllMain to take care of new threads. Thus we */ |
| |
/* must properly intercept thread creation. */ |
| |
|
| typedef struct { |
typedef struct { |
| HANDLE child_ready_h, parent_ready_h; |
HANDLE child_ready_h, parent_ready_h; |
| volatile struct thread_entry * entry; |
volatile struct thread_entry * entry; |
| Line 509 static DWORD WINAPI thread_start(LPVOID arg) |
|
| Line 514 static DWORD WINAPI thread_start(LPVOID arg) |
|
| } |
} |
| #endif /* !defined(MSWINCE) && !(defined(__MINGW32__) && !defined(_DLL)) */ |
#endif /* !defined(MSWINCE) && !(defined(__MINGW32__) && !defined(_DLL)) */ |
| |
|
| |
#endif /* !CYGWIN32 */ |
| |
|
| #ifdef MSWINCE |
#ifdef MSWINCE |
| |
|
| typedef struct { |
typedef struct { |
| Line 564 DWORD WINAPI main_thread_start(LPVOID arg) |
|
| Line 571 DWORD WINAPI main_thread_start(LPVOID arg) |
|
| |
|
| LONG WINAPI GC_write_fault_handler(struct _EXCEPTION_POINTERS *exc_info); |
LONG WINAPI GC_write_fault_handler(struct _EXCEPTION_POINTERS *exc_info); |
| |
|
| /* threadAttach/threadDetach routines used by both CYGWIN and DLL implementation, |
/* threadAttach/threadDetach routines used by both CYGWIN and DLL |
| since both recieve explicit notification on thread creation/destruction |
* implementation, since both recieve explicit notification on thread |
| |
* creation/destruction. |
| */ |
*/ |
| void threadAttach() { |
static void threadAttach() { |
| int i; |
int i; |
| /* It appears to be unsafe to acquire a lock here, since this */ |
/* It appears to be unsafe to acquire a lock here, since this */ |
| /* code is apparently not preeemptible on some systems. */ |
/* code is apparently not preeemptible on some systems. */ |
| Line 616 void threadAttach() { |
|
| Line 624 void threadAttach() { |
|
| while (GC_please_stop) Sleep(20); |
while (GC_please_stop) Sleep(20); |
| } |
} |
| |
|
| void threadDetach(DWORD thread_id) { |
static void threadDetach(DWORD thread_id) { |
| int i; |
int i; |
| |
|
| LOCK(); |
LOCK(); |
| Line 782 void GC_thread_exit_proc(void *arg) |
|
| Line 790 void GC_thread_exit_proc(void *arg) |
|
| int i; |
int i; |
| |
|
| # if DEBUG_CYGWIN_THREADS |
# if DEBUG_CYGWIN_THREADS |
| GC_printf2("thread 0x%x(0x%x) called pthread_exit().\n",(int)pthread_self(),GetCurrentThreadId()); |
GC_printf2("thread 0x%x(0x%x) called pthread_exit().\n", |
| |
(int)pthread_self(),GetCurrentThreadId()); |
| # endif |
# endif |
| |
|
| LOCK(); |
LOCK(); |
| Line 805 int GC_pthread_sigmask(int how, const sigset_t *set, s |
|
| Line 814 int GC_pthread_sigmask(int how, const sigset_t *set, s |
|
| int GC_pthread_detach(pthread_t thread) { |
int GC_pthread_detach(pthread_t thread) { |
| return pthread_detach(thread); |
return pthread_detach(thread); |
| } |
} |
| #else |
#else /* !CYGWIN32 */ |
| |
|
| /* |
/* |
| * This isn't generally safe, since DllMain is not premptible. |
* We avoid acquiring locks here, since this doesn't seem to be preemptable. |
| * If another thread holds the lock while this runs we're in trouble. |
|
| * Pontus Rydin suggests wrapping the thread start routine instead. |
* Pontus Rydin suggests wrapping the thread start routine instead. |
| */ |
*/ |
| |
#ifdef GC_DLL |
| BOOL WINAPI DllMain(HINSTANCE inst, ULONG reason, LPVOID reserved) |
BOOL WINAPI DllMain(HINSTANCE inst, ULONG reason, LPVOID reserved) |
| { |
{ |
| switch (reason) { |
switch (reason) { |
| Line 852 BOOL WINAPI DllMain(HINSTANCE inst, ULONG reason, LPVO |
|
| Line 861 BOOL WINAPI DllMain(HINSTANCE inst, ULONG reason, LPVO |
|
| } |
} |
| return TRUE; |
return TRUE; |
| } |
} |
| #endif /* CYGWIN32 */ |
#endif /* GC_DLL */ |
| |
#endif /* !CYGWIN32 */ |
| |
|
| # endif /* !MSWINCE */ |
# endif /* !MSWINCE */ |
| |
|