2009-09-10 Ivan Maidanski <ivmai@mail.ru>
authorivmai <ivmai>
Thu, 10 Sep 2009 18:15:46 +0000 (18:15 +0000)
committerIvan Maidanski <ivmai@mail.ru>
Tue, 26 Jul 2011 17:06:46 +0000 (21:06 +0400)
(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).

17 files changed:
ChangeLog
Makefile.direct
dbg_mlc.c
dyn_load.c
include/gc.h
include/gc_config_macros.h
include/private/gc_locks.h
include/private/gc_priv.h
include/private/gcconfig.h
include/private/thread_local_alloc.h
malloc.c
mark.c
misc.c
os_dep.c
tests/test.c
thread_local_alloc.c
win32_threads.c

index 06eed46..82e80aa 100644 (file)
--- 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
index 8100344..b1c4cc1 100644 (file)
@@ -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) 
index 85d82b8..d388418 100644 (file)
--- a/dbg_mlc.c
+++ b/dbg_mlc.c
  * 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;
 }
 
index 7960a53..920d17d 100644 (file)
@@ -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)
   {
index 3a0f95e..9110bf0 100644 (file)
@@ -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 */
 
index ac56b71..7295ad4 100644 (file)
 # 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)
index 467c1a5..7a9a668 100644 (file)
  * 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); \
 # 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(); }
index 3976ddd..d9f5dd2 100644 (file)
@@ -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;
index e8c261d..6b5cedc 100644 (file)
 #   if defined(x86)
 #     define I386
 #   endif
-#   if defined(ARM)
+#   if defined(_M_ARM) || defined(ARM) || defined(_ARM_)
 #     define ARM32
 #   endif
 #   define MSWINCE
           -> bad word size
 # endif
 
+# ifndef ALIGNMENT
+    --> undefined ALIGNMENT
+# endif
+
 # ifdef PCR
 #   undef DYNAMIC_LOADING
 #   undef STACKBOTTOM
 # 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
 
index 32b6a3e..9bfbcb5 100644 (file)
@@ -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? \
index 62fc64c..3c3cca7 100644 (file)
--- a/malloc.c
+++ b/malloc.c
  * 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 da9dc1c..56eb539 100644 (file)
--- 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 142b276..25ee10c 100644 (file)
--- 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();
index 9b80603..26135e9 100644 (file)
--- 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.               */
index 79ea8a0..bfe9c49 100644 (file)
@@ -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
index 0e78f2f..db217c2 100644 (file)
 
 # 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
index 75865da..a7744a3 100644 (file)
 
 /* 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
 
 /* 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                  */
   /* 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.                             */