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 */ |
|
|