summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog128
-rw-r--r--Makefile.direct5
-rw-r--r--dbg_mlc.c22
-rw-r--r--dyn_load.c8
-rw-r--r--include/gc.h38
-rw-r--r--include/gc_config_macros.h6
-rw-r--r--include/private/gc_locks.h9
-rw-r--r--include/private/gc_priv.h12
-rw-r--r--include/private/gcconfig.h9
-rw-r--r--include/private/thread_local_alloc.h9
-rw-r--r--malloc.c24
-rw-r--r--mark.c8
-rw-r--r--misc.c100
-rw-r--r--os_dep.c11
-rw-r--r--tests/test.c88
-rw-r--r--thread_local_alloc.c6
-rw-r--r--win32_threads.c168
17 files changed, 464 insertions, 187 deletions
diff --git a/ChangeLog b/ChangeLog
index 06eed467..82e80aac 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,133 @@
2009-09-10 Ivan Maidanski <ivmai@mail.ru>
+ (diff114a, diff114b, diff114c)
+
+ * dbg_mlc.c: Guard include <errno.h> with ifndef MSWINCE; include
+ "private/dbg_mlc.h" before it.
+ * malloc.c: Ditto.
+ * dbg_mlc.c (GC_debug_strdup): Use memcpy() instead of strcpy()
+ for WinCE (since deprecated); evaluate strlen() only once; don't
+ set errno for WinCE.
+ * malloc.c (GC_strdup): Ditto.
+ * dyn_load.c (GC_wnt): Define as macro (FALSE) for WinCE.
+ * include/gc.h (GC_unregister_my_thread): Refine the comment.
+ * include/gc.h (GC_uintptr_t, GC_beginthreadex, GC_endthreadex):
+ Don't declare for WinCE.
+ * include/gc.h (GC_WINMAIN_WINCE_LPTSTR): New macro (WinCE only).
+ * include/gc.h (GC_WinMain): Remove GC_API.
+ * include/gc.h (GC_WinMain): Use GC_WINMAIN_WINCE_LPTSTR for
+ lpCmdLine.
+ * tests/test.c (GC_WinMain): Ditto.
+ * win32_threads.c (main_thread_args, GC_WinMain): Ditto.
+ * include/gc_config_macros.h (ptrdiff_t): Guard with
+ ifndef _PTRDIFF_T_DEFINED; define _PTRDIFF_T_DEFINED macro.
+ * include/private/gc_locks.h: Guard include "atomic_ops.h" with
+ ifdef GC_PTHREADS (and not GC_WIN32_THREADS).
+ * mark.c: Include "atomic_ops.h" if PARALLEL_MARK.
+ * thread_local_alloc.c: Include "atomic_ops.h" if GC_GCJ_SUPPORT.
+ * win32_threads.c: Include "atomic_ops.h" if MPROTECT_VDB.
+ * include/private/gc_locks.h: Use include "atomic_ops.h" instead
+ of include <atomic_ops.h>.
+ * include/private/gc_priv.h: Ditto.
+ * include/private/gc_locks.h (GC_allocate_ml, GC_need_to_lock):
+ Don't export (replace GC_API to "extern").
+ * win32_threads.c (GC_allocate_ml): Don't export.
+ * include/private/gc_priv.h (DebugBreak): Define as macro for
+ WinCE (if not UNDER_CE and DebugBreak is not defined yet).
+ * include/private/gc_priv.h (UNALIGNED): Rename to UNALIGNED_PTRS
+ (since "UNALIGNED" is defined in winnt.h of WinCE).
+ * mark.c (UNALIGNED): Ditto.
+ * include/private/gcconfig.h (ARM32): Recognize _M_ARM and _ARM_.
+ * include/private/gcconfig.h (ALIGNMENT): Check always defined.
+ * include/private/gcconfig.h: Allow GC_WIN32_THREADS for WinCE.
+ * include/private/thread_local_alloc.h: Define USE_WIN32_SPECIFIC
+ for WinCE (since __declspec(thread) is unsupported).
+ * include/private/thread_local_alloc.h (TLS_OUT_OF_INDEXES):
+ Define for WinCE (if undefined).
+ * malloc.c (GC_malloc): Remove outdated comment about disabling
+ signals.
+ * misc.c: Don't include <tchar.h> (since not used anymore and may
+ break TEXT() macro defined in winnt.h).
+ * misc.c (GC_init_inner): Don't use GetModuleHandle() and
+ InitializeCriticalSectionAndSpinCount() for WinCE.
+ * misc.c (GC_init_inner): Replace GetModuleHandleA() with
+ GetModuleHandle() (and use TEXT() macro controlled by UNICODE).
+ * misc.c (LOG_FILE): Remove unused macro; don't use _T() macro.
+ * misc.c (GC_CreateLogFile): New static function (Win32/WinCE
+ only); move the code from GC_write(); replace GETENV() with
+ GetEnvironmentVariable(); replace CreateFileA() with
+ CreateFile(); use TEXT() macro (for Unicode support); replace
+ strcat() with memcpy() (since deprecated in WinCE).
+ * misc.c (GC_write): Define as STATIC.
+ * win32_threads.c (GC_attached_thread): Ditto.
+ * misc.c (GC_write): Use GC_CreateLogFile().
+ * misc.c: Define vsnprintf macro as StringCchVPrintfA for WinCE.
+ * misc.c (GC_abort): Try to invoke MessageBoxA() dynamically
+ (Win32 only) if DONT_USE_USER32_DLL is defined.
+ * misc.c (GC_abort): Duplicate msg to GC log file (for Win32 and
+ WinCE).
+ * misc.c (GC_abort): Use a more user-friendly abort if
+ NO_DEBUGGING (Win32 only).
+ * os_dep.c: Include "atomic_ops.h" only if MPROTECT_VDB (and
+ THREADS).
+ * os_dep.c (detect_GetWriteWatch): Use TEXT() for GetModuleHandle
+ (for Unicode support); check GetModuleHandle() result.
+ * tests/test.c: Don't define assert for WinCE (since may be
+ redefined by "assert.h" included from libatomic_ops).
+ * tests/test.c (FAIL): Define as ABORT for all targets (except
+ for PCR).
+ * tests/test.c (n_tests): Don't use AO_t.
+ * tests/test.c (check_heap_stats): Don't cast n_tests.
+ * tests/test.c (inc_int_counter): New function (for n_tests atomic
+ incrementation).
+ * tests/test.c (run_one_test): Test GC_memalign() for all targets.
+ * tests/test.c (run_one_test): Avoid unbalanced brackets in
+ #if-#else-#endif blocks.
+ * tests/test.c (run_one_test): Replace AO_fetch_and_add1() and
+ private LOCK/UNLOCK with GC_call_with_alloc_lock(inc_int_counter).
+ * tests/test.c (check_heap_stats): Replace
+ "if (sizeof(char *) > 4)" with "#if CPP_WORDSZ == 64" to suppress
+ "unreachable code" compiler warning.
+ * tests/test.c (WinMain): Set cmd type to LPWSTR (for WinCE
+ "UNDER_CE" mode); else use LPSTR type (for Win32 and WinCE).
+ * tests/test.c (thr_window): Replace "L" string prefix with
+ TEXT().
+ * thread_local_alloc.c: Check THREADS is defined (to prevent other
+ compiler errors and warnings otherwise).
+ * tests/test.c (WinMain): Recognize GC_NO_DLLMAIN macro (for
+ GC_use_DllMain()).
+ * Makefile.direct (GC_NO_DLLMAIN, DONT_IMPORT_GETCURTHREAD): Add
+ the comments for.
+ * win32_threads.c (GC_register_my_thread_inner): Recognize
+ DONT_IMPORT_GETCURTHREAD macro.
+ * win32_threads.c: Recognize GC_NO_DLLMAIN macro (to exclude
+ DllMain support if needed).
+ * win32_threads.c (GC_NO_DLLMAIN): Define implicitly if DllMain
+ thread registration is unsupported for a given configuration.
+ * win32_threads.c (GC_use_DllMain): Update the comment; refine
+ ABORT message.
+ * win32_threads.c (GC_use_DllMain,
+ GC_started_thread_while_stopped, GC_register_my_thread_inner,
+ GC_lookup_thread_inner, GC_delete_gc_thread,
+ GC_allow_register_threads, GC_lookup_pthread,
+ GC_push_thread_structures, GC_stop_world, GC_push_all_stacks):
+ Check for GC_NO_DLLMAIN.
+ * win32_threads.c (GC_Thread_Rep.tm_in_use, GC_attached_thread,
+ DllMain): Don't define if GC_NO_DLLMAIN.
+ * win32_threads.c (GC_stop_world): Declare "i" and "max" local
+ vars only if not GC_NO_DLLMAIN (to suppress compiler warning).
+ * win32_threads.c (GC_mark_thread, start_mark_threads): Use
+ CreateThread() instead of _beginthreadex() for WinCE.
+ * win32_threads.c (MARK_THREAD_STACK_SIZE, WINCE_MAIN_STACK_SIZE):
+ New macros defined (used by start_mark_threads(), WinMain()).
+ * win32_threads.c (GC_thr_init): Exclude parallel-specific code on
+ WinCE for now (since getenv(), GetProcessAffinityMask() and
+ SignalObjectAndWait() are missing on WinCE).
+ * win32_threads.c (GC_thr_init): replace GetModuleHandleA() with
+ GetModuleHandle(); replace CreateEventA() with CreateEvent(); use
+ TEXT() macro (for Unicode support).
+
+2009-09-10 Ivan Maidanski <ivmai@mail.ru>
(diff113)
* include/gc.h (GC_has_static_roots_func): New typedef (user filter
diff --git a/Makefile.direct b/Makefile.direct
index 81003447..b1c4cc12 100644
--- a/Makefile.direct
+++ b/Makefile.direct
@@ -330,6 +330,11 @@ HOSTCFLAGS=$(CFLAGS)
# -DGC_PREFER_MPROTECT_VDB Choose MPROTECT_VDB manually in case of multiple
# virtual dirty bit strategies are implemented (at present useful on Win32
# to force MPROTECT_VDB strategy instead of the default GWW_VDB one).
+# -DGC_NO_DLLMAIN (Win32+DLL only) Exclude DllMain-based thread registration
+# support.
+# -DDONT_IMPORT_GETCURTHREAD (Win32 only) Use MS hard-coded thread-self
+# pseudohandle value (-2) instead of linking (or binding) to a real
+# GetCurrentThread() func; mostly useful on WinCE unless "UNDER_CE" mode.
#
CXXFLAGS= $(CFLAGS)
diff --git a/dbg_mlc.c b/dbg_mlc.c
index 85d82b89..d3884184 100644
--- a/dbg_mlc.c
+++ b/dbg_mlc.c
@@ -15,10 +15,13 @@
* modified is included with the above copyright notice.
*/
-#include <errno.h>
-#include <string.h>
#include "private/dbg_mlc.h"
+#ifndef MSWINCE
+# include <errno.h>
+#endif
+#include <string.h>
+
void GC_default_print_heap_obj_proc(ptr_t p);
GC_API void GC_CALL GC_register_finalizer_no_order
(void * obj, GC_finalization_proc fn, void * cd,
@@ -641,13 +644,22 @@ GC_API void * GC_CALL GC_debug_malloc_atomic(size_t lb, GC_EXTRA_PARAMS)
GC_API char * GC_CALL GC_debug_strdup(const char *str, GC_EXTRA_PARAMS)
{
char *copy;
+ size_t lb;
if (str == NULL) return NULL;
- copy = GC_debug_malloc_atomic(strlen(str) + 1, OPT_RA s, i);
+ lb = strlen(str) + 1;
+ copy = GC_debug_malloc_atomic(lb, OPT_RA s, i);
if (copy == NULL) {
- errno = ENOMEM;
+# ifndef MSWINCE
+ errno = ENOMEM;
+# endif
return NULL;
}
- strcpy(copy, str);
+# ifndef MSWINCE
+ strcpy(copy, str);
+# else
+ /* strcpy() is deprecated in WinCE */
+ memcpy(copy, str, lb);
+# endif
return copy;
}
diff --git a/dyn_load.c b/dyn_load.c
index 7960a53f..920d17de 100644
--- a/dyn_load.c
+++ b/dyn_load.c
@@ -859,8 +859,12 @@ void GC_register_dynamic_libraries(void)
}
# endif /* DEBUG_VIRTUALQUERY */
- extern GC_bool GC_wnt; /* Is Windows NT derivative. */
- /* Defined and set in os_dep.c. */
+# ifdef MSWINCE
+# define GC_wnt FALSE
+# else
+ extern GC_bool GC_wnt; /* Is Windows NT derivative. */
+ /* Defined and set in os_dep.c. */
+# endif
void GC_register_dynamic_libraries(void)
{
diff --git a/include/gc.h b/include/gc.h
index 3a0f95e2..9110bf0b 100644
--- a/include/gc.h
+++ b/include/gc.h
@@ -962,7 +962,8 @@ GC_API int GC_CALL GC_register_my_thread(struct GC_stack_base *);
/* Specifically, if it wants to return or otherwise communicate a */
/* pointer to the garbage-collected heap to another thread, it must */
/* do this before calling GC_unregister_my_thread, most probably */
-/* by saving it in a global data structure. */
+/* by saving it in a global data structure. Must not be called inside */
+/* a GC callback function (except for GC_call_with_stack_base() one). */
GC_API int GC_CALL GC_unregister_my_thread(void);
/* Attempt to fill in the GC_stack_base structure with the stack base */
@@ -1142,6 +1143,10 @@ GC_API void GC_CALL GC_register_has_static_roots_callback(
DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId );
+ GC_API void WINAPI GC_ExitThread(DWORD /* dwExitCode */);
+
+# if !defined(_WIN32_WCE)
+
# if !defined(_UINTPTR_T) && !defined(_UINTPTR_T_DEFINED) \
&& !defined(UINTPTR_MAX)
typedef GC_word GC_uintptr_t;
@@ -1156,21 +1161,22 @@ GC_API void GC_CALL GC_register_has_static_roots_callback(
GC_API void GC_CALL GC_endthreadex(unsigned retval);
- GC_API void WINAPI GC_ExitThread(DWORD dwExitCode);
-
-# if defined(_WIN32_WCE)
- /*
- * win32_threads.c implements the real WinMain, which will start a new thread
- * to call GC_WinMain after initializing the garbage collector.
- */
- GC_API int WINAPI GC_WinMain(
- HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- LPWSTR lpCmdLine,
- int nCmdShow );
-# ifndef GC_BUILD
-# define WinMain GC_WinMain
-# endif
+# else
+ /* win32_threads.c implements the real WinMain, which will start */
+ /* a new thread to call GC_WinMain after initializing the garbage */
+ /* collector. */
+# ifdef UNDER_CE
+# define GC_WINMAIN_WINCE_LPTSTR LPWSTR
+# else
+# define GC_WINMAIN_WINCE_LPTSTR LPSTR
+# endif
+ /* not exported (since defined outside GC by an application) */
+ int WINAPI GC_WinMain(
+ HINSTANCE /* hInstance */, HINSTANCE /* hPrevInstance */,
+ GC_WINMAIN_WINCE_LPTSTR /* lpCmdLine */, int /* nCmdShow */);
+# ifndef GC_BUILD
+# define WinMain GC_WinMain
+# endif
# endif /* defined(_WIN32_WCE) */
#endif /* !GC_NO_THREAD_DECLS */
diff --git a/include/gc_config_macros.h b/include/gc_config_macros.h
index ac56b719..7295ad41 100644
--- a/include/gc_config_macros.h
+++ b/include/gc_config_macros.h
@@ -143,7 +143,11 @@
# else /* ! _WIN32_WCE */
/* Yet more kludges for WinCE */
# include <stdlib.h> /* size_t is defined here */
- typedef long ptrdiff_t; /* ptrdiff_t is not defined */
+# ifndef _PTRDIFF_T_DEFINED
+ /* ptrdiff_t is not defined */
+# define _PTRDIFF_T_DEFINED
+ typedef long ptrdiff_t;
+# endif
# endif
#if defined(_DLL) && !defined(GC_NOT_DLL) && !defined(GC_DLL)
diff --git a/include/private/gc_locks.h b/include/private/gc_locks.h
index 467c1a53..7a9a6689 100644
--- a/include/private/gc_locks.h
+++ b/include/private/gc_locks.h
@@ -27,7 +27,10 @@
* in assertions, and may return TRUE in the "dont know" case.
*/
# ifdef THREADS
-# include <atomic_ops.h>
+
+# if defined(GC_PTHREADS) && !defined(GC_WIN32_THREADS)
+# include "atomic_ops.h"
+# endif
GC_API void GC_CALL GC_noop1(word);
# ifdef PCR
@@ -52,7 +55,7 @@
# include <windows.h>
# define NO_THREAD (DWORD)(-1)
extern DWORD GC_lock_holder;
- GC_API CRITICAL_SECTION GC_allocate_ml;
+ extern CRITICAL_SECTION GC_allocate_ml;
# ifdef GC_ASSERTIONS
# define UNCOND_LOCK() \
{ EnterCriticalSection(&GC_allocate_ml); \
@@ -192,7 +195,7 @@
# endif /* !THREADS */
#if defined(UNCOND_LOCK) && !defined(LOCK)
- GC_API GC_bool GC_need_to_lock;
+ extern GC_bool GC_need_to_lock;
/* At least two thread running; need to lock. */
# define LOCK() if (GC_need_to_lock) { UNCOND_LOCK(); }
# define UNLOCK() if (GC_need_to_lock) { UNCOND_UNLOCK(); }
diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h
index 3976ddd8..d9f5dd22 100644
--- a/include/private/gc_priv.h
+++ b/include/private/gc_priv.h
@@ -334,6 +334,12 @@ void GC_print_callers(struct callinfo info[NFRAMES]);
# ifdef PCR
# define ABORT(s) PCR_Base_Panic(s)
# else
+# if defined(MSWINCE) && !defined(UNDER_CE) && !defined(DebugBreak)
+ /* This simplifies linking for WinCE (and, probably, doesn't */
+ /* hurt debugging much); use -DDebugBreak=DebugBreak to override */
+ /* this behavior if really needed. */
+# define DebugBreak() _exit(-1) /* there is no abort() in WinCE */
+# endif
# ifdef SMALL_CONFIG
# if defined(MSWIN32) || defined(MSWINCE)
# define ABORT(msg) DebugBreak()
@@ -444,7 +450,7 @@ extern GC_warn_proc GC_current_warn_proc;
# define LOGWL ((word)5) /* log[2] of CPP_WORDSZ */
# define modWORDSZ(n) ((n) & 0x1f) /* n mod size of word */
# if ALIGNMENT != 4
-# define UNALIGNED
+# define UNALIGNED_PTRS
# endif
#endif
@@ -454,7 +460,7 @@ extern GC_warn_proc GC_current_warn_proc;
# define LOGWL ((word)6) /* log[2] of CPP_WORDSZ */
# define modWORDSZ(n) ((n) & 0x3f) /* n mod size of word */
# if ALIGNMENT != 8
-# define UNALIGNED
+# define UNALIGNED_PTRS
# endif
#endif
@@ -682,7 +688,7 @@ typedef word page_hash_table[PHT_SIZE];
# endif
#ifdef PARALLEL_MARK
-# include <atomic_ops.h>
+# include "atomic_ops.h"
typedef AO_t counter_t;
#else
typedef size_t counter_t;
diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h
index e8c261d6..6b5cedc7 100644
--- a/include/private/gcconfig.h
+++ b/include/private/gcconfig.h
@@ -374,7 +374,7 @@
# if defined(x86)
# define I386
# endif
-# if defined(ARM)
+# if defined(_M_ARM) || defined(ARM) || defined(_ARM_)
# define ARM32
# endif
# define MSWINCE
@@ -2100,6 +2100,10 @@
-> bad word size
# endif
+# ifndef ALIGNMENT
+ --> undefined ALIGNMENT
+# endif
+
# ifdef PCR
# undef DYNAMIC_LOADING
# undef STACKBOTTOM
@@ -2211,7 +2215,8 @@
# if defined(GC_GNU_THREADS) && !defined(HURD)
--> inconsistent configuration
# endif
-# if defined(GC_WIN32_THREADS) && !defined(MSWIN32) && !defined(CYGWIN32)
+# if defined(GC_WIN32_THREADS) && !defined(MSWIN32) && !defined(CYGWIN32) \
+ && !defined(MSWINCE)
--> inconsistent configuration
# endif
diff --git a/include/private/thread_local_alloc.h b/include/private/thread_local_alloc.h
index 32b6a3e5..9bfbcb52 100644
--- a/include/private/thread_local_alloc.h
+++ b/include/private/thread_local_alloc.h
@@ -26,7 +26,7 @@
#include "gc_inline.h"
-# if defined USE_HPUX_TLS
+# if defined(USE_HPUX_TLS)
# error USE_HPUX_TLS macro was replaced by USE_COMPILER_TLS
# endif
@@ -34,7 +34,8 @@
!defined(USE_WIN32_COMPILER_TLS) && !defined(USE_COMPILER_TLS) && \
!defined(USE_CUSTOM_SPECIFIC)
# if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32)
-# if defined(__GNUC__) /* Fixed for versions past 2.95? */
+# if defined(__GNUC__) /* Fixed for versions past 2.95? */ \
+ || defined(MSWINCE)
# define USE_WIN32_SPECIFIC
# else
# define USE_WIN32_COMPILER_TLS
@@ -107,6 +108,10 @@ typedef struct thread_local_freelists {
# define GC_getspecific TlsGetValue
# define GC_setspecific(key, v) !TlsSetValue(key, v)
/* We assume 0 == success, msft does the opposite. */
+# ifndef TLS_OUT_OF_INDEXES
+ /* this is currently missing in WinCE */
+# define TLS_OUT_OF_INDEXES (DWORD)0xFFFFFFFF
+# endif
# define GC_key_create(key, d) \
((d) != 0? (ABORT("Destructor unsupported by TlsAlloc"),0) \
: ((*(key) = TlsAlloc()) == TLS_OUT_OF_INDEXES? \
diff --git a/malloc.c b/malloc.c
index 62fc64cf..3c3cca76 100644
--- a/malloc.c
+++ b/malloc.c
@@ -13,10 +13,13 @@
* modified is included with the above copyright notice.
*/
+#include "private/gc_priv.h"
+
#include <stdio.h>
#include <string.h>
-#include <errno.h>
-#include "private/gc_priv.h"
+#ifndef MSWINCE
+# include <errno.h>
+#endif
extern void * GC_clear_stack(void *); /* in misc.c, behaves like identity */
void GC_extend_size_map(size_t); /* in misc.c. */
@@ -236,13 +239,21 @@ void * GC_generic_malloc(size_t lb, int k)
GC_API char * GC_CALL GC_strdup(const char *s)
{
char *copy;
-
+ size_t lb;
if (s == NULL) return NULL;
- if ((copy = GC_malloc_atomic(strlen(s) + 1)) == NULL) {
- errno = ENOMEM;
+ lb = strlen(s) + 1;
+ if ((copy = GC_malloc_atomic(lb)) == NULL) {
+# ifndef MSWINCE
+ errno = ENOMEM;
+# endif
return NULL;
}
- strcpy(copy, s);
+# ifndef MSWINCE
+ strcpy(copy, s);
+# else
+ /* strcpy() is deprecated in WinCE */
+ memcpy(copy, s, lb);
+# endif
return copy;
}
@@ -266,7 +277,6 @@ GC_API char * GC_CALL GC_strdup(const char *s)
UNLOCK();
return(GENERAL_MALLOC((word)lb, NORMAL));
}
- /* See above comment on signals. */
GC_ASSERT(0 == obj_link(op)
|| ((word)obj_link(op)
<= (word)GC_greatest_plausible_heap_addr
diff --git a/mark.c b/mark.c
index da9dc1c2..56eb539a 100644
--- a/mark.c
+++ b/mark.c
@@ -113,8 +113,6 @@ mse * GC_mark_stack_limit;
size_t GC_mark_stack_size = 0;
#ifdef PARALLEL_MARK
-# include "atomic_ops.h"
-
mse * volatile GC_mark_stack_top;
/* Updated only with mark lock held, but read asynchronously. */
volatile AO_t GC_first_nonempty;
@@ -1640,7 +1638,7 @@ void GC_push_marked1(struct hblk *h, hdr *hhdr)
}
-#ifndef UNALIGNED
+#ifndef UNALIGNED_PTRS
/* Push all objects reachable from marked objects in the given block */
/* of size 2 (granules) objects. */
@@ -1738,7 +1736,7 @@ void GC_push_marked4(struct hblk *h, hdr *hhdr)
#endif /* GC_GRANULE_WORDS < 4 */
-#endif /* UNALIGNED */
+#endif /* UNALIGNED_PTRS */
#endif /* USE_PUSH_MARKED_ACCELERATORS */
@@ -1769,7 +1767,7 @@ void GC_push_marked(struct hblk *h, hdr *hhdr)
case 1:
GC_push_marked1(h, hhdr);
break;
-# if !defined(UNALIGNED)
+# if !defined(UNALIGNED_PTRS)
case 2:
GC_push_marked2(h, hhdr);
break;
diff --git a/misc.c b/misc.c
index 142b2766..25ee10c3 100644
--- a/misc.c
+++ b/misc.c
@@ -32,7 +32,6 @@
# define WIN32_LEAN_AND_MEAN
# define NOSERVICE
# include <windows.h>
-# include <tchar.h>
#endif
#if defined(UNIX_LIKE) || defined(CYGWIN32)
@@ -523,8 +522,9 @@ void GC_init_inner(void)
# endif
# if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS)
if (!GC_is_initialized) {
+# ifndef MSWINCE
BOOL (WINAPI *pfn) (LPCRITICAL_SECTION, DWORD) = NULL;
- HMODULE hK32 = GetModuleHandleA("kernel32.dll");
+ HMODULE hK32 = GetModuleHandle(TEXT("kernel32.dll"));
if (hK32)
pfn = (BOOL (WINAPI *) (LPCRITICAL_SECTION, DWORD))
GetProcAddress (hK32,
@@ -532,7 +532,8 @@ void GC_init_inner(void)
if (pfn)
pfn(&GC_allocate_ml, 4000);
else
- InitializeCriticalSection (&GC_allocate_ml);
+# endif /* !MSWINCE */
+ /* else */ InitializeCriticalSection (&GC_allocate_ml);
}
#endif /* MSWIN32 */
# if (defined(MSWIN32) || defined(MSWINCE)) && defined(THREADS)
@@ -869,9 +870,6 @@ out:
# if defined(_MSC_VER) && defined(_DEBUG)
# include <crtdbg.h>
# endif
-# ifdef OLD_WIN32_LOG_FILE
-# define LOG_FILE _T("gc.log")
-# endif
STATIC HANDLE GC_stdout = 0;
@@ -894,7 +892,37 @@ out:
# define IF_NEED_TO_LOCK(x)
#endif
- int GC_write(const char *buf, size_t len)
+ STATIC HANDLE GC_CreateLogFile(void)
+ {
+# if !defined(NO_GETENV) || !defined(OLD_WIN32_LOG_FILE)
+ TCHAR logPath[_MAX_PATH + sizeof(".log")];
+# endif
+ /* Use GetEnvironmentVariable instead of GETENV() for unicode support. */
+# ifndef NO_GETENV
+ if (GetEnvironmentVariable(TEXT("GC_LOG_FILE"), logPath,
+ _MAX_PATH + 1) - 1U >= (DWORD)_MAX_PATH)
+# endif
+ {
+ /* Env var not found or its value too long. */
+# ifdef OLD_WIN32_LOG_FILE
+ return CreateFile(TEXT("gc.log"), GENERIC_WRITE, FILE_SHARE_READ,
+ NULL /* lpSecurityAttributes */, CREATE_ALWAYS,
+ FILE_FLAG_WRITE_THROUGH, NULL /* hTemplateFile */);
+# else
+ /* strcat/wcscat() are deprecated on WinCE, so use memcpy() */
+ memcpy(&logPath[GetModuleFileName(NULL /* hModule */, logPath,
+ _MAX_PATH + 1)],
+ TEXT(".log"), sizeof(TEXT(".log")));
+# endif
+ }
+# if !defined(NO_GETENV) || !defined(OLD_WIN32_LOG_FILE)
+ return CreateFile(logPath, GENERIC_WRITE, FILE_SHARE_READ,
+ NULL /* lpSecurityAttributes */, CREATE_ALWAYS,
+ FILE_FLAG_WRITE_THROUGH, NULL /* hTemplateFile */);
+# endif
+ }
+
+ STATIC int GC_write(const char *buf, size_t len)
{
BOOL tmp;
DWORD written;
@@ -905,22 +933,7 @@ out:
IF_NEED_TO_LOCK(LeaveCriticalSection(&GC_write_cs));
return -1;
} else if (GC_stdout == 0) {
- char * file_name = GETENV("GC_LOG_FILE");
- char logPath[_MAX_PATH + 5];
-
- if (0 == file_name) {
-# ifdef OLD_WIN32_LOG_FILE
- strcpy(logPath, LOG_FILE);
-# else
- GetModuleFileNameA(NULL, logPath, _MAX_PATH);
- strcat(logPath, ".log");
-# endif
- file_name = logPath;
- }
- GC_stdout = CreateFileA(file_name, GENERIC_WRITE,
- FILE_SHARE_READ,
- NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH,
- NULL);
+ GC_stdout = GC_CreateLogFile();
if (GC_stdout == INVALID_HANDLE_VALUE)
ABORT("Open of log file failed");
}
@@ -967,7 +980,7 @@ STATIC int GC_tmp; /* Should really be local ... */
#if !defined(MSWIN32) && !defined(MSWINCE) && !defined(OS2) \
&& !defined(MACOS) && !defined(ECOS) && !defined(NOSYS)
-int GC_write(int fd, const char *buf, size_t len)
+STATIC int GC_write(int fd, const char *buf, size_t len)
{
register int bytes_written = 0;
register int result;
@@ -987,7 +1000,7 @@ int GC_write(int fd, const char *buf, size_t len)
#endif /* UN*X */
#ifdef ECOS
-int GC_write(int fd, const char *buf, size_t len)
+STATIC int GC_write(int fd, const char *buf, size_t len)
{
_Jv_diag_write (buf, len);
return len;
@@ -995,7 +1008,7 @@ int GC_write(int fd, const char *buf, size_t len)
#endif
#ifdef NOSYS
-int GC_write(int fd, const char *buf, size_t len)
+STATIC int GC_write(int fd, const char *buf, size_t len)
{
/* No writing. */
return len;
@@ -1018,7 +1031,12 @@ int GC_write(int fd, const char *buf, size_t len)
#define BUFSZ 1024
#ifdef _MSC_VER
-# define vsnprintf _vsnprintf
+# ifdef MSWINCE
+ /* _vsnprintf is deprecated in WinCE */
+# define vsnprintf StringCchVPrintfA
+# else
+# define vsnprintf _vsnprintf
+# endif
#endif
/* A version of printf that is unlikely to call malloc, and is thus safer */
/* to call from the collector in case malloc has been bound to GC_malloc. */
@@ -1121,15 +1139,30 @@ GC_API GC_warn_proc GC_CALL GC_get_warn_proc(void)
#if !defined(PCR) && !defined(SMALL_CONFIG)
void GC_abort(const char *msg)
{
-# if defined(MSWIN32) && !defined(DONT_USE_USER32_DLL)
- (void) MessageBoxA(NULL, msg, "Fatal error in gc", MB_ICONERROR|MB_OK);
-# else
+# if defined(MSWIN32)
+# ifndef DONT_USE_USER32_DLL
+ /* Use static binding to "user32.dll". */
+ (void)MessageBoxA(NULL, msg, "Fatal error in GC", MB_ICONERROR|MB_OK);
+# else
+ /* This simplifies linking - resolve "MessageBoxA" at run-time. */
+ HINSTANCE hU32 = LoadLibrary(TEXT("user32.dll"));
+ if (hU32) {
+ FARPROC pfn = GetProcAddress(hU32, "MessageBoxA");
+ if (pfn)
+ (void)(*(int (WINAPI *)(HWND, LPCSTR, LPCSTR, UINT))pfn)(
+ NULL /* hWnd */, msg, "Fatal error in GC",
+ MB_ICONERROR | MB_OK);
+ (void)FreeLibrary(hU32);
+ }
+# endif
+ /* Also duplicate msg to GC log file. */
+# endif
/* Avoid calling GC_err_printf() here, as GC_abort() could be */
/* called from it. Note 1: this is not an atomic output. */
/* Note 2: possible write errors are ignored. */
if (WRITE(GC_stderr, (void *)msg, strlen(msg)) >= 0)
(void)WRITE(GC_stderr, (void *)("\n"), 1);
-# endif
+
if (GETENV("GC_LOOP_ON_ABORT") != NULL) {
/* In many cases it's easier to debug a running process. */
/* It's arguably nicer to sleep, but that makes it harder */
@@ -1137,7 +1170,10 @@ void GC_abort(const char *msg)
/* about threads. */
for(;;) {}
}
-# if defined(MSWIN32) || defined(MSWINCE)
+# if defined(MSWIN32) && defined(NO_DEBUGGING)
+ /* A more user-friendly abort after showing fatal message. */
+ _exit(-1); /* exit on error without running "at-exit" callbacks */
+# elif defined(MSWIN32) || defined(MSWINCE)
DebugBreak();
# else
(void) abort();
diff --git a/os_dep.c b/os_dep.c
index 9b80603a..26135e9d 100644
--- a/os_dep.c
+++ b/os_dep.c
@@ -15,7 +15,8 @@
*/
# include "private/gc_priv.h"
-# ifdef THREADS
+
+# if defined(THREADS) && defined(MPROTECT_VDB)
# include "atomic_ops.h"
# endif
@@ -1283,6 +1284,7 @@ void GC_register_data_segments(void)
static void detect_GetWriteWatch(void)
{
static GC_bool done;
+ HMODULE hK32;
if (done)
return;
@@ -1306,9 +1308,10 @@ void GC_register_data_segments(void)
}
# endif
- GetWriteWatch_func = (GetWriteWatch_type)
- GetProcAddress(GetModuleHandle("kernel32.dll"), "GetWriteWatch");
- if (GetWriteWatch_func != NULL) {
+ hK32 = GetModuleHandle(TEXT("kernel32.dll"));
+ if (hK32 != (HMODULE)0 &&
+ (GetWriteWatch_func = (GetWriteWatch_type)GetProcAddress(hK32,
+ "GetWriteWatch")) != NULL) {
/* Also check whether VirtualAlloc accepts MEM_WRITE_WATCH, */
/* as some versions of kernel32.dll have one but not the */
/* other, making the feature completely broken. */
diff --git a/tests/test.c b/tests/test.c
index 79ea8a04..bfe9c49f 100644
--- a/tests/test.c
+++ b/tests/test.c
@@ -37,7 +37,7 @@
# include <stdio.h>
# ifdef _WIN32_WCE
# include <winbase.h>
-# define assert ASSERT
+/* # define assert ASSERT */
# else
# include <assert.h> /* Not normally used, but handy for debugging. */
# endif
@@ -130,14 +130,7 @@ int realloc_count = 0;
# ifdef PCR
# define FAIL (void)abort()
# else
-# ifdef MSWINCE
-# define FAIL DebugBreak()
-# else
-# ifdef SMALL_CONFIG
- void GC_abort(const char * msg);
-# endif
-# define FAIL GC_abort("Test failed");
-# endif
+# define FAIL ABORT("Test failed")
# endif
#endif /* !AMIGA_FASTALLOC */
@@ -519,11 +512,11 @@ void reverse_test(void)
/* Win32S only allows 128K stacks */
# define BIG 1000
# else
-# if defined PCR
+# if defined(PCR)
/* PCR default stack is 100K. Stack frames are up to 120 bytes. */
# define BIG 700
# else
-# if defined MSWINCE
+# if defined(MSWINCE)
/* WinCE only allows 64K stacks */
# define BIG 500
# else
@@ -881,11 +874,7 @@ void tree_test(void)
# endif
}
-#if defined(THREADS) && defined(AO_HAVE_fetch_and_add1_full)
- AO_t n_tests = 0; /* Updated by AO_fetch_and_add1_full(). */
-#else
- unsigned n_tests = 0;
-#endif
+unsigned n_tests = 0;
GC_word bm_huge[10] = {
0xffffffff,
@@ -1009,6 +998,12 @@ static void uniq(void *p, ...) {
# define TEST_FAIL_COUNT(n) (fail_count >= (n))
#endif
+void * GC_CALLBACK inc_int_counter(void *pcounter)
+{
+ ++(*(int *)pcounter);
+ return NULL;
+}
+
void run_one_test(void)
{
# ifndef DBG_HDRS_ALL
@@ -1103,7 +1098,6 @@ void run_one_test(void)
"GC_is_valid_displacement produced incorrect result\n");
FAIL;
}
-# if !defined(MSWINCE)
{
size_t i;
@@ -1113,14 +1107,14 @@ void run_one_test(void)
if (result % i != 0 || result == 0 || *(int *)result != 0) FAIL;
}
}
-# endif
# ifndef ALL_INTERIOR_POINTERS
# if defined(RS6000) || defined(POWERPC)
- if (!TEST_FAIL_COUNT(1)) {
+ if (!TEST_FAIL_COUNT(1))
# else
if ((GC_all_interior_pointers && !TEST_FAIL_COUNT(1))
- || (!GC_all_interior_pointers && !TEST_FAIL_COUNT(2))) {
+ || (!GC_all_interior_pointers && !TEST_FAIL_COUNT(2)))
# endif
+ {
GC_printf("GC_is_valid_displacement produced wrong failure indication\n");
FAIL;
}
@@ -1195,16 +1189,9 @@ void run_one_test(void)
GC_log_printf("-------------Finished second reverse_test at time %u (%p)\n",
(unsigned) time_diff, &start_time);
}
-# if defined(THREADS) && defined(AO_HAVE_fetch_and_add1_full)
- /* Use AO_fetch_and_add1_full() if available. */
- /* GC_allocate_ml may not always be visible outside GC. */
- (void)AO_fetch_and_add1_full(&n_tests);
-# else
- LOCK();
- /* AO_fetch_and_add1 is not always available. */
- n_tests++;
- UNLOCK();
-# endif
+ /* GC_allocate_ml and GC_need_to_lock are no longer exported, and */
+ /* AO_fetch_and_add1() may be unavailable to update a counter. */
+ (void)GC_call_with_alloc_lock(inc_int_counter, &n_tests);
# if defined(THREADS) && defined(HANDLE_FORK)
if (fork() == 0) {
GC_gcollect();
@@ -1234,17 +1221,17 @@ void check_heap_stats(void)
/* these may be particularly dubious, since empirically the */
/* heap tends to grow largely as a result of the GC not */
/* getting enough cycles. */
- if (sizeof(char *) > 4) {
+# if CPP_WORDSZ == 64
max_heap_sz = 4500000;
- } else {
+# else
max_heap_sz = 2800000;
- }
+# endif
# else
- if (sizeof(char *) > 4) {
+# if CPP_WORDSZ == 64
max_heap_sz = 19000000;
- } else {
+# else
max_heap_sz = 12000000;
- }
+# endif
# endif
# ifdef GC_DEBUG
max_heap_sz *= 2;
@@ -1265,7 +1252,7 @@ void check_heap_stats(void)
# endif
GC_invoke_finalizers();
}
- (void)GC_printf("Completed %u tests\n", (unsigned) n_tests);
+ (void)GC_printf("Completed %u tests\n", n_tests);
(void)GC_printf("Allocated %d collectable objects\n", collectable_count);
(void)GC_printf("Allocated %d uncollectable objects\n",
uncollectable_count);
@@ -1353,8 +1340,10 @@ void GC_CALLBACK warn_proc(char *msg, GC_word p)
#if !defined(PCR) \
&& !defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS) \
|| defined(LINT)
-#if defined(MSWIN32) && !defined(__MINGW32__)
- int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prev, LPTSTR cmd, int n)
+#if defined(MSWINCE) && defined(UNDER_CE)
+ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prev, LPWSTR cmd, int n)
+#elif defined(MSWIN32) && !defined(__MINGW32__) || defined(MSWINCE)
+ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prev, LPSTR cmd, int n)
#else
int main(void)
#endif
@@ -1457,7 +1446,7 @@ DWORD __stdcall thr_window(void *arg)
NULL,
(HBRUSH)(COLOR_APPWORKSPACE+1),
NULL,
- L"GCtestWindow"
+ TEXT("GCtestWindow")
};
MSG msg;
@@ -1466,8 +1455,8 @@ DWORD __stdcall thr_window(void *arg)
win_handle = CreateWindowEx(
0,
- L"GCtestWindow",
- L"GCtest",
+ TEXT("GCtestWindow"),
+ TEXT("GCtest"),
0,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL,
@@ -1492,11 +1481,12 @@ DWORD __stdcall thr_window(void *arg)
}
#endif
-# ifdef MSWINCE
-int APIENTRY GC_WinMain(HINSTANCE instance, HINSTANCE prev, LPWSTR cmd, int n)
-# else
-int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prev, LPSTR cmd, int n)
-# endif
+#ifdef MSWINCE
+ int APIENTRY GC_WinMain(HINSTANCE instance, HINSTANCE prev,
+ GC_WINMAIN_WINCE_LPTSTR cmd, int n)
+#else
+ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prev, LPSTR cmd, int n)
+#endif
{
# if NTHREADS > 0
HANDLE h[NTHREADS];
@@ -1506,8 +1496,8 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prev, LPSTR cmd, int n)
HANDLE win_thr_h;
# endif
DWORD thread_id;
-
-# if defined(GC_DLL) && !defined(THREAD_LOCAL_ALLOC) && !defined(PARALLEL_MARK)
+# if defined(GC_DLL) && !defined(GC_NO_DLLMAIN) && !defined(MSWINCE) \
+ && !defined(THREAD_LOCAL_ALLOC) && !defined(PARALLEL_MARK)
GC_use_DllMain(); /* Test with implicit thread registration if possible. */
GC_printf("Using DllMain to track threads\n");
# endif
diff --git a/thread_local_alloc.c b/thread_local_alloc.c
index 0e78f2f6..db217c26 100644
--- a/thread_local_alloc.c
+++ b/thread_local_alloc.c
@@ -14,6 +14,10 @@
# if defined(THREAD_LOCAL_ALLOC)
+#ifndef THREADS
+# error "invalid config - THREAD_LOCAL_ALLOC requires GC_THREADS"
+#endif
+
#include "private/thread_local_alloc.h"
#include "gc_inline.h"
@@ -215,6 +219,8 @@ GC_API void * GC_CALL GC_malloc_atomic(size_t bytes)
#ifdef GC_GCJ_SUPPORT
+#include "atomic_ops.h" /* for AO_compiler_barrier() */
+
#include "include/gc_gcj.h"
#ifdef GC_ASSERTIONS
diff --git a/win32_threads.c b/win32_threads.c
index 75865da2..a7744a35 100644
--- a/win32_threads.c
+++ b/win32_threads.c
@@ -27,11 +27,7 @@
/* Allocation lock declarations. */
#if !defined(USE_PTHREAD_LOCKS)
-# if defined(GC_DLL)
- __declspec(dllexport) CRITICAL_SECTION GC_allocate_ml;
-# else
- CRITICAL_SECTION GC_allocate_ml;
-# endif
+ CRITICAL_SECTION GC_allocate_ml;
DWORD GC_lock_holder = NO_THREAD;
/* Thread id for current holder of allocation lock */
#else
@@ -94,8 +90,10 @@
/* DllMain-based thread registration is currently incompatible */
/* with thread-local allocation, pthreads and WinCE. */
-#if defined(GC_DLL) && !defined(MSWINCE) \
+#if defined(GC_DLL) && !defined(GC_NO_DLLMAIN) && !defined(MSWINCE) \
&& !defined(THREAD_LOCAL_ALLOC) && !defined(GC_PTHREADS)
+# include "atomic_ops.h"
+
static GC_bool GC_win32_dll_threads = FALSE;
/* This code operates in two distinct modes, depending on */
/* the setting of GC_win32_dll_threads. If */
@@ -126,6 +124,9 @@
/* i.e. before any collector or thread calls. We make it a */
/* "dynamic" option only to avoid multiple library versions. */
#else
+# ifndef GC_NO_DLLMAIN
+# define GC_NO_DLLMAIN
+# endif
# define GC_win32_dll_threads FALSE
# undef MAX_THREADS
# define MAX_THREADS 1 /* dll_thread_table[] is always empty. */
@@ -151,28 +152,21 @@ static GC_bool parallel_initialized = FALSE;
void GC_init_parallel(void);
-/* GC_use_DllMain() is currently incompatible with pthreads. */
-/* It might be possible to get GC_DLL and DllMain-based thread registration */
-/* to work with Cygwin, but if you try, you are on your own. */
-#if defined(GC_DLL) && !defined(GC_PTHREADS)
+/* GC_use_DllMain() is currently incompatible with pthreads and WinCE. */
+/* It might be possible to get DllMain-based thread registration to */
+/* work with Cygwin, but if you try, you are on your own. */
+#ifndef GC_NO_DLLMAIN
/* Turn on GC_win32_dll_threads */
GC_API void GC_CALL GC_use_DllMain(void)
{
-# ifdef THREAD_LOCAL_ALLOC
- ABORT("Cannot use thread local allocation with DllMain-based "
- "thread registration.");
- /* Thread-local allocation really wants to lock at thread */
- /* entry and exit. */
-# else
GC_ASSERT(!parallel_initialized);
GC_win32_dll_threads = TRUE;
GC_init_parallel();
-# endif
}
#else
GC_API void GC_CALL GC_use_DllMain(void)
{
- ABORT("GC not configured as DLL");
+ ABORT("GC DllMain-based thread registration unsupported");
}
#endif
@@ -182,11 +176,13 @@ STATIC DWORD GC_main_thread = 0;
struct GC_Thread_Rep {
union {
- AO_t tm_in_use; /* Updated without lock. */
+# ifndef GC_NO_DLLMAIN
+ AO_t tm_in_use; /* Updated without lock. */
/* We assert that unused */
/* entries have invalid ids of */
/* zero and zero stack fields. */
/* Used only with GC_win32_dll_threads. */
+# endif
struct GC_Thread_Rep * tm_next;
/* Hash table link without */
/* GC_win32_dll_threads. */
@@ -250,11 +246,15 @@ volatile GC_bool GC_please_stop = FALSE;
* If we notice this in the middle of marking.
*/
-AO_t GC_attached_thread = FALSE;
+#ifndef GC_NO_DLLMAIN
+ STATIC AO_t GC_attached_thread = FALSE;
+#endif
+
/* Return TRUE if an thread was attached since we last asked or */
/* since GC_attached_thread was explicitly reset. */
GC_bool GC_started_thread_while_stopped(void)
{
+#ifndef GC_NO_DLLMAIN
AO_t result;
if (GC_win32_dll_threads) {
@@ -264,9 +264,9 @@ GC_bool GC_started_thread_while_stopped(void)
AO_store(&GC_attached_thread, FALSE);
}
return ((GC_bool)result);
- } else {
- return FALSE;
}
+#endif
+ return FALSE;
}
/* Thread table used if GC_win32_dll_threads is set. */
@@ -360,6 +360,7 @@ static GC_thread GC_register_my_thread_inner(struct GC_stack_base *sb,
# endif
# endif
+#ifndef GC_NO_DLLMAIN
if (GC_win32_dll_threads) {
int i;
/* It appears to be unsafe to acquire a lock here, since this */
@@ -400,7 +401,9 @@ static GC_thread GC_register_my_thread_inner(struct GC_stack_base *sb,
GC_max_thread_index = MAX_THREADS - 1;
}
me = dll_thread_table + i;
- } else /* Not using DllMain */ {
+ } else
+#endif
+ /* else */ /* Not using DllMain */ {
GC_ASSERT(I_HOLD_LOCK());
GC_in_thread_creation = TRUE; /* OK to collect from unknown thread. */
me = GC_new_thread(thread_id);
@@ -413,6 +416,12 @@ static GC_thread GC_register_my_thread_inner(struct GC_stack_base *sb,
me -> pthread_id = pthread_self();
# endif
+# if defined(DONT_IMPORT_GETCURTHREAD) && !defined(UNDER_CE)
+ /* This simplifies linking for some WinAPI systems (like WinCE). */
+# undef GetCurrentThread
+# define GetCurrentThread() (HANDLE)-2L /* "thread_self" pseudohandle */
+# endif
+
if (!DuplicateHandle(GetCurrentProcess(),
GetCurrentThread(),
GetCurrentProcess(),
@@ -438,6 +447,7 @@ static GC_thread GC_register_my_thread_inner(struct GC_stack_base *sb,
# endif
if (me -> stack_base == NULL)
ABORT("Bad stack base in GC_register_my_thread_inner");
+#ifndef GC_NO_DLLMAIN
if (GC_win32_dll_threads) {
if (GC_please_stop) {
AO_store(&GC_attached_thread, TRUE);
@@ -446,7 +456,9 @@ static GC_thread GC_register_my_thread_inner(struct GC_stack_base *sb,
/* We'd like to wait here, but can't, since waiting in DllMain */
/* provokes deadlocks. */
/* Thus we force marking to be restarted instead. */
- } else {
+ } else
+#endif
+ /* else */ {
GC_ASSERT(!GC_please_stop);
/* Otherwise both we and the thread stopping code would be */
/* holding the allocation lock. */
@@ -477,6 +489,7 @@ STATIC LONG GC_get_max_thread_index(void)
/* we hold the allocator lock. */
/* Also used (for assertion checking only) from thread_local_alloc.c. */
GC_thread GC_lookup_thread_inner(DWORD thread_id) {
+#ifndef GC_NO_DLLMAIN
if (GC_win32_dll_threads) {
int i;
LONG my_max = GC_get_max_thread_index();
@@ -491,7 +504,9 @@ GC_thread GC_lookup_thread_inner(DWORD thread_id) {
} else {
return (GC_thread)(dll_thread_table + i);
}
- } else {
+ }
+#endif
+ {
word hv = ((word)thread_id) % THREAD_TABLE_SZ;
register GC_thread p = GC_threads[hv];
@@ -557,6 +572,7 @@ unsigned *GC_check_finalizer_nested(void)
STATIC void GC_delete_gc_thread(GC_vthread gc_id)
{
CloseHandle(gc_id->handle);
+#ifndef GC_NO_DLLMAIN
if (GC_win32_dll_threads) {
/* This is intended to be lock-free. */
/* It is either called synchronously from the thread being deleted, */
@@ -571,7 +587,9 @@ STATIC void GC_delete_gc_thread(GC_vthread gc_id)
gc_id -> pthread_id.p = NULL;
# endif /* GC_WIN32_PTHREADS */
AO_store_release(&(gc_id->in_use), FALSE);
- } else {
+ } else
+#endif
+ /* else */ {
/* Cast away volatile qualifier, since we have lock. */
GC_thread gc_nvid = (GC_thread)gc_id;
DWORD id = gc_nvid -> id;
@@ -634,7 +652,7 @@ GC_API void GC_CALL GC_allow_register_threads(void)
/* Check GC is initialized and the current thread is registered. */
GC_ASSERT(GC_lookup_thread_inner(GetCurrentThreadId()) != 0);
-# if defined(GC_DLL) && !defined(PARALLEL_MARK) && !defined(THREAD_LOCAL_ALLOC)
+# if !defined(GC_NO_DLLMAIN) && !defined(PARALLEL_MARK)
/* GC_init_parallel() is not called from GC_init_inner(). */
parallel_initialized = TRUE;
# endif
@@ -706,6 +724,7 @@ DWORD GC_pthread_map_cache[PTHREAD_MAP_SIZE];
/* Assumes we do NOT hold the allocation lock. */
static GC_thread GC_lookup_pthread(pthread_t id)
{
+#ifndef GC_NO_DLLMAIN
if (GC_win32_dll_threads) {
int i;
LONG my_max = GC_get_max_thread_index();
@@ -718,7 +737,9 @@ static GC_thread GC_lookup_pthread(pthread_t id)
i++);
if (i > my_max) return 0;
return (GC_thread)(dll_thread_table + i);
- } else {
+ }
+#endif
+ {
/* We first try the cache. If that fails, we use a very slow */
/* approach. */
int hv_guess = GET_PTHREAD_MAP_CACHE(id) % THREAD_TABLE_SZ;
@@ -748,6 +769,7 @@ static GC_thread GC_lookup_pthread(pthread_t id)
void GC_push_thread_structures(void)
{
GC_ASSERT(I_HOLD_LOCK());
+#ifndef GC_NO_DLLMAIN
if (GC_win32_dll_threads) {
/* Unlike the other threads implementations, the thread table here */
/* contains no pointers to the collectable heap. Thus we have */
@@ -762,7 +784,9 @@ void GC_push_thread_structures(void)
(ptr_t)(&(dll_thread_table[i].status)+1));
}
# endif
- } else {
+ } else
+#endif
+ /* else */ {
GC_push_all((ptr_t)(GC_threads), (ptr_t)(GC_threads)+sizeof(GC_threads));
}
# if defined(THREAD_LOCAL_ALLOC)
@@ -773,6 +797,7 @@ void GC_push_thread_structures(void)
}
#if defined(MPROTECT_VDB) && !defined(MSWINCE)
+# include "atomic_ops.h"
extern volatile AO_TS_t GC_fault_handler_lock; /* from os_dep.c */
#endif
@@ -828,8 +853,6 @@ STATIC void GC_suspend(GC_thread t)
void GC_stop_world(void)
{
DWORD thread_id = GetCurrentThreadId();
- int i;
- int my_max;
if (!GC_thr_initialized) ABORT("GC_stop_world() called before GC_thr_init()");
GC_ASSERT(I_HOLD_LOCK());
@@ -847,7 +870,10 @@ void GC_stop_world(void)
# ifndef CYGWIN32
EnterCriticalSection(&GC_write_cs);
# endif
+#ifndef GC_NO_DLLMAIN
if (GC_win32_dll_threads) {
+ int i;
+ int my_max;
/* Any threads being created during this loop will end up setting */
/* GC_attached_thread when they start. This will force marking to */
/* restart. */
@@ -861,7 +887,9 @@ void GC_stop_world(void)
GC_suspend((GC_thread)t);
}
}
- } else {
+ } else
+#endif
+ /* else */ {
GC_thread t;
int i;
@@ -1088,7 +1116,7 @@ void GC_push_all_stacks(void)
# ifndef SMALL_CONFIG
unsigned nthreads = 0;
# endif
-
+#ifndef GC_NO_DLLMAIN
if (GC_win32_dll_threads) {
int i;
LONG my_max = GC_get_max_thread_index();
@@ -1103,7 +1131,9 @@ void GC_push_all_stacks(void)
if (t -> id == me) found_me = TRUE;
}
}
- } else {
+ } else
+#endif
+ /* else */ {
GC_thread t;
int i;
@@ -1257,7 +1287,11 @@ void GC_get_next_stack(char *start, char *limit,
#ifdef GC_PTHREADS
STATIC void * GC_mark_thread(void * id)
#else
- STATIC unsigned __stdcall GC_mark_thread(void * id)
+# ifdef MSWINCE
+ STATIC DWORD WINAPI GC_mark_thread(LPVOID id)
+# else
+ STATIC unsigned __stdcall GC_mark_thread(void * id)
+# endif
#endif
{
word my_mark_no = 0;
@@ -1418,19 +1452,37 @@ void GC_notify_all_marker(void)
#else /* ! GC_PTHREADS */
+# ifndef MARK_THREAD_STACK_SIZE
+# define MARK_THREAD_STACK_SIZE 0 /* default value */
+# endif
+
STATIC void start_mark_threads(void)
{
int i;
- GC_uintptr_t handle;
- unsigned thread_id;
+# ifdef MSWINCE
+ HANDLE handle;
+ DWORD thread_id;
+# else
+ GC_uintptr_t handle;
+ unsigned thread_id;
+# endif
for (i = 0; i < GC_markers - 1; ++i) {
marker_last_stack_min[i] = ADDR_LIMIT;
- handle = _beginthreadex(NULL /* security_attr */, 0 /* stack_size */,
- GC_mark_thread, (void *)(word)i, 0 /* flags */,
- &thread_id);
- if (!handle || handle == (GC_uintptr_t)-1L)
- WARN("Marker thread creation failed\n", 0);
+# ifdef MSWINCE
+ /* There is no _beginthreadex() in WinCE. */
+ handle = CreateThread(NULL /* lpsa */, MARK_THREAD_STACK_SIZE,
+ GC_mark_thread, (LPVOID)(word)i,
+ 0 /* fdwCreate */, &thread_id);
+ if (!handle || handle == (HANDLE)-1L)
+ WARN("Marker thread creation failed\n", 0);
+# else
+ handle = _beginthreadex(NULL /* security_attr */,
+ MARK_THREAD_STACK_SIZE, GC_mark_thread,
+ (void *)(word)i, 0 /* flags */, &thread_id);
+ if (!handle || handle == (GC_uintptr_t)-1L)
+ WARN("Marker thread creation failed\n", 0);
+# endif
else { /* We may detach the thread (if handle is of HANDLE type) */
/* CloseHandle((HANDLE)handle); */
}
@@ -1747,14 +1799,18 @@ GC_API void GC_CALL GC_endthreadex(unsigned retval)
typedef struct {
HINSTANCE hInstance;
HINSTANCE hPrevInstance;
- LPWSTR lpCmdLine;
+ GC_WINMAIN_WINCE_LPTSTR lpCmdLine;
int nShowCmd;
} main_thread_args;
DWORD WINAPI main_thread_start(LPVOID arg);
+# ifndef WINCE_MAIN_STACK_SIZE
+# define WINCE_MAIN_STACK_SIZE 0 /* default value */
+# endif
+
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
- LPWSTR lpCmdLine, int nShowCmd)
+ GC_WINMAIN_WINCE_LPTSTR lpCmdLine, int nShowCmd)
{
DWORD exit_code = 1;
@@ -1768,8 +1824,9 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
GC_init();
/* start the main thread */
- thread_h = GC_CreateThread(
- NULL, 0, main_thread_start, &args, 0, &thread_id);
+ thread_h = GC_CreateThread(NULL /* lpsa */, WINCE_MAIN_STACK_SIZE,
+ main_thread_start, &args, 0 /* fdwCreate */,
+ &thread_id);
if (thread_h != NULL)
{
@@ -1792,7 +1849,7 @@ DWORD WINAPI main_thread_start(LPVOID arg)
args->lpCmdLine, args->nShowCmd);
}
-# else /* !MSWINCE */
+#endif /* MSWINCE */
/* Called by GC_init() - we hold the allocation lock. */
void GC_thr_init(void) {
@@ -1813,7 +1870,7 @@ void GC_thr_init(void) {
GC_get_stack_base(&sb);
GC_ASSERT(sb_result == GC_SUCCESS);
-# ifdef PARALLEL_MARK
+# if defined(PARALLEL_MARK) && !defined(MSWINCE)
/* Set GC_markers. */
{
char * markers_string = GETENV("GC_MARKERS");
@@ -1854,7 +1911,7 @@ void GC_thr_init(void) {
if (GC_markers <= 1 || GC_win32_dll_threads
# ifndef GC_PTHREADS
|| GC_wnt == FALSE
- || (hK32 = GetModuleHandleA("kernel32.dll")) == (HMODULE)0
+ || (hK32 = GetModuleHandle(TEXT("kernel32.dll"))) == (HMODULE)0
|| (signalObjectAndWait_func = (SignalObjectAndWait_type)
GetProcAddress(hK32, "SignalObjectAndWait")) == 0
# endif
@@ -1865,13 +1922,13 @@ void GC_thr_init(void) {
} else {
# ifndef GC_PTHREADS
/* Initialize Win32 event objects for parallel marking. */
- mark_mutex_event = CreateEventA(NULL /* attrs */,
+ mark_mutex_event = CreateEvent(NULL /* attrs */,
FALSE /* isManualReset */,
FALSE /* initialState */, NULL /* name */);
- builder_cv = CreateEventA(NULL /* attrs */,
+ builder_cv = CreateEvent(NULL /* attrs */,
TRUE /* isManualReset */,
FALSE /* initialState */, NULL /* name */);
- mark_cv = CreateEventA(NULL /* attrs */, TRUE /* isManualReset */,
+ mark_cv = CreateEvent(NULL /* attrs */, TRUE /* isManualReset */,
FALSE /* initialState */, NULL /* name */);
if (mark_mutex_event == (HANDLE)0 || builder_cv == (HANDLE)0
|| mark_cv == (HANDLE)0)
@@ -2134,7 +2191,7 @@ int GC_pthread_detach(pthread_t thread)
* the collector here seems dangerous, since DllMain is limited in what it
* can do.)
*/
-#ifdef GC_DLL
+#ifndef GC_NO_DLLMAIN
/*ARGSUSED*/
BOOL WINAPI DllMain(HINSTANCE inst, ULONG reason, LPVOID reserved)
{
@@ -2203,10 +2260,9 @@ BOOL WINAPI DllMain(HINSTANCE inst, ULONG reason, LPVOID reserved)
}
return TRUE;
}
-#endif /* GC_DLL */
-#endif /* !GC_PTHREADS */
+#endif /* !GC_NO_DLLMAIN */
-# endif /* !MSWINCE */
+#endif /* !GC_PTHREADS */
/* Perform all initializations, including those that */
/* may require allocation. */