boehm-gc: revert all CACAO-specific modifications; this is now an exact copy of the...
[cacao.git] / src / mm / boehm-gc / include / gc.h
index 19a6571058bb76ca49207b366a4c324b2a3d4b9e..c62b14859e5d05fcaed51a3a5e3e02ba75005330 100644 (file)
 /* size as char * or void *.  There seems to be no way to do this      */
 /* even semi-portably.  The following is probably no better/worse      */
 /* than almost anything else.                                          */
-/* The ANSI standard suggests that size_t and ptr_diff_t might be      */
+/* The ANSI standard suggests that size_t and ptrdiff_t might be       */
 /* better choices.  But those had incorrect definitions on some older  */
 /* systems.  Notably "typedef int size_t" is WRONG.                    */
 #ifndef _WIN64
   typedef unsigned long GC_word;
   typedef long GC_signed_word;
 #else
-  /* Win64 isn't really supported yet, but this is the first step. And */
-  /* it might cause error messages to show up in more plausible places.        */
-  /* This needs basetsd.h, which is included by windows.h.             */
+#ifdef __int64
+  typedef unsigned __int64 GC_word;
+  typedef __int64 GC_signed_word;
+#else
   typedef unsigned long long GC_word;
   typedef long long GC_signed_word;
 #endif
+#endif
 
 /* Public read-only variables */
+/* Getter procedures are supplied in some cases and preferred for new  */
+/* code.                                                               */
 
 GC_API GC_word GC_gc_no;/* Counter incremented per collection.         */
                        /* Includes empty GCs at startup.               */
+GC_API GC_word GC_CALL GC_get_gc_no(void);
 
 GC_API int GC_parallel;        /* GC is parallelized for performance on        */
                        /* multiprocessors.  Currently set only         */
@@ -77,11 +82,13 @@ GC_API int GC_parallel;     /* GC is parallelized for performance on        */
                        /* If GC_parallel is set, incremental           */
                        /* collection is only partially functional,     */
                        /* and may not be desirable.                    */
+GC_API int GC_CALL GC_get_parallel(void);
                        
 
 /* Public R/W variables */
 
-GC_API void * (*GC_oom_fn) (size_t bytes_requested);
+typedef void * (GC_CALLBACK * GC_oom_func)(size_t /* bytes_requested */);
+GC_API GC_oom_func GC_oom_fn;
                        /* When there is insufficient memory to satisfy */
                        /* an allocation request, we return             */
                        /* (*GC_oom_fn)().  By default this just        */
@@ -89,12 +96,16 @@ GC_API void * (*GC_oom_fn) (size_t bytes_requested);
                        /* If it returns, it must return 0 or a valid   */
                        /* pointer to a previously allocated heap       */
                        /* object.                                      */
+GC_API void GC_CALL GC_set_oom_fn(GC_oom_func);
+GC_API GC_oom_func GC_CALL GC_get_oom_fn(void);
 
 GC_API int GC_find_leak;
                        /* Do not actually garbage collect, but simply  */
                        /* report inaccessible memory that was not      */
                        /* deallocated with GC_free.  Initial value     */
                        /* is determined by FIND_LEAK macro.            */
+GC_API void GC_CALL GC_set_find_leak(int);
+GC_API int GC_CALL GC_get_find_leak(void);
 
 GC_API int GC_all_interior_pointers;
                        /* Arrange for pointers to object interiors to  */
@@ -107,6 +118,8 @@ GC_API int GC_all_interior_pointers;
                        /* at least a byte to allow "off the end"       */
                        /* pointer recognition.                         */
                        /* MUST BE 0 or 1.                              */
+GC_API void GC_CALL GC_set_all_interior_pointers(int);
+GC_API int GC_CALL GC_get_all_interior_pointers(void);
 
 GC_API int GC_finalize_on_demand;
                        /* If nonzero, finalizers will only be run in   */
@@ -114,17 +127,22 @@ GC_API int GC_finalize_on_demand;
                        /* call.  The default is determined by whether  */
                        /* the FINALIZE_ON_DEMAND macro is defined      */
                        /* when the collector is built.                 */
+GC_API void GC_CALL GC_set_finalize_on_demand(int);
+GC_API int GC_CALL GC_get_finalize_on_demand(void);
 
 GC_API int GC_java_finalization;
                        /* Mark objects reachable from finalizable      */
-                       /* objects in a separate postpass.  This makes  */
+                       /* objects in a separate post-pass.  This makes */
                        /* it a bit safer to use non-topologically-     */
                        /* ordered finalization.  Default value is      */
                        /* determined by JAVA_FINALIZATION macro.       */
                        /* Enables register_finalizer_unreachable to    */
                        /* work correctly.                              */
+GC_API void GC_CALL GC_set_java_finalization(int);
+GC_API int GC_CALL GC_get_java_finalization(void);
 
-GC_API void (* GC_finalizer_notifier)(void);
+typedef void (GC_CALLBACK * GC_finalizer_notifier_proc)(void);
+GC_API GC_finalizer_notifier_proc GC_finalizer_notifier;
                        /* Invoked by the collector when there are      */
                        /* objects to be finalized.  Invoked at most    */
                        /* once per GC cycle.  Never invoked unless     */
@@ -132,6 +150,8 @@ GC_API void (* GC_finalizer_notifier)(void);
                        /* Typically this will notify a finalization    */
                        /* thread, which will call GC_invoke_finalizers */
                        /* in response.                                 */
+GC_API void GC_CALL GC_set_finalizer_notifier(GC_finalizer_notifier_proc);
+GC_API GC_finalizer_notifier_proc GC_CALL GC_get_finalizer_notifier(void);
 
 GC_API int GC_dont_gc; /* != 0 ==> Dont collect.  In versions 6.2a1+,  */
                        /* this overrides explicit GC_gcollect() calls. */
@@ -145,13 +165,15 @@ GC_API int GC_dont_gc;    /* != 0 ==> Dont collect.  In versions 6.2a1+,  */
 GC_API int GC_dont_expand;
                        /* Dont expand heap unless explicitly requested */
                        /* or forced to.                                */
+GC_API void GC_CALL GC_set_dont_expand(int);
+GC_API int GC_CALL GC_get_dont_expand(void);
 
 GC_API int GC_use_entire_heap;
-               /* Causes the nonincremental collector to use the       */
+               /* Causes the non-incremental collector to use the      */
                /* entire heap before collecting.  This was the only    */
                /* option for GC versions < 5.0.  This sometimes        */
                /* results in more large block fragmentation, since     */
-               /* very larg blocks will tend to get broken up          */
+               /* very large blocks will tend to get broken up         */
                /* during each GC cycle.  It is likely to result in a   */
                /* larger working set, but lower collection             */
                /* frequencies, and hence fewer instructions executed   */
@@ -166,12 +188,16 @@ GC_API int GC_full_freq;    /* Number of partial collections between      */
                            /* blocks.  Values in the tens are now      */
                            /* perfectly reasonable, unlike for         */
                            /* earlier GC versions.                     */
+GC_API void GC_CALL GC_set_full_freq(int);
+GC_API int GC_CALL GC_get_full_freq(void);
                        
 GC_API GC_word GC_non_gc_bytes;
                        /* Bytes not considered candidates for collection. */
                        /* Used only to control scheduling of collections. */
                        /* Updated by GC_malloc_uncollectable and GC_free. */
                        /* Wizards only.                                   */
+GC_API void GC_CALL GC_set_non_gc_bytes(GC_word);
+GC_API GC_word GC_CALL GC_get_non_gc_bytes(void);
 
 GC_API int GC_no_dls;
                        /* Don't register dynamic library data segments. */
@@ -180,6 +206,8 @@ GC_API int GC_no_dls;
                        /* In Microsoft Windows environments, this will  */
                        /* usually also prevent registration of the      */
                        /* main data segment as part of the root set.    */
+GC_API void GC_CALL GC_set_no_dls(int);
+GC_API int GC_CALL GC_get_no_dls(void);
 
 GC_API GC_word GC_free_space_divisor;
                        /* We try to make sure that we allocate at      */
@@ -194,11 +222,15 @@ GC_API GC_word GC_free_space_divisor;
                        /* but more collection time.  Decreasing it     */
                        /* will appreciably decrease collection time    */
                        /* at the expense of space.                     */
+GC_API void GC_CALL GC_set_free_space_divisor(GC_word);
+GC_API GC_word GC_CALL GC_get_free_space_divisor(void);
 
 GC_API GC_word GC_max_retries;
                        /* The maximum number of GCs attempted before   */
                        /* reporting out of memory after heap           */
                        /* expansion fails.  Initially 0.               */
+GC_API void GC_CALL GC_set_max_retries(GC_word);
+GC_API GC_word GC_CALL GC_get_max_retries(void);
                        
 
 GC_API char *GC_stackbottom;    /* Cool end of user stack.             */
@@ -220,6 +252,8 @@ GC_API int GC_dont_precollect;  /* Don't collect as part of                 */
                                /* before the first collection.         */
                                /* Interferes with blacklisting.        */
                                /* Wizards only.                        */
+GC_API void GC_CALL GC_set_dont_precollect(int);
+GC_API int GC_CALL GC_get_dont_precollect(void);
 
 GC_API unsigned long GC_time_limit;
                                /* If incremental collection is enabled, */
@@ -234,18 +268,20 @@ GC_API unsigned long GC_time_limit;
                                /* Setting GC_time_limit to this value   */
                                /* will disable the "pause time exceeded"*/
                                /* tests.                                */
+GC_API void GC_CALL GC_set_time_limit(unsigned long);
+GC_API unsigned long GC_CALL GC_get_time_limit(void);
 
 /* Public procedures */
 
 /* Initialize the collector.  Portable clients should call GC_INIT() from
  * the main program instead.
  */
-GC_API void GC_init(void);
+GC_API void GC_CALL GC_init(void);
 
 /*
  * general purpose allocation routines, with roughly malloc calling conv.
  * The atomic versions promise that no relevant pointers are contained
- * in the object.  The nonatomic versions guarantee that the new object
+ * in the object.  The non-atomic versions guarantee that the new object
  * is cleared.  GC_malloc_stubborn promises that no changes to the object
  * will occur after GC_end_stubborn_change has been called on the
  * result of GC_malloc_stubborn. GC_malloc_uncollectable allocates an object
@@ -254,36 +290,38 @@ GC_API void GC_init(void);
  * be reachable.  GC_malloc_uncollectable and GC_free called on the resulting
  * object implicitly update GC_non_gc_bytes appropriately.
  *
- * Note that the GC_malloc_stubborn support is stubbed out by default
- * starting in 6.0.  GC_malloc_stubborn is an alias for GC_malloc unless
- * the collector is built with STUBBORN_ALLOC defined.
+ * Note that the GC_malloc_stubborn support doesn't really
+ * exist anymore.  MANUAL_VDB provides comparable functionality.
  */
-GC_API void * GC_malloc(size_t size_in_bytes);
-GC_API void * GC_malloc_atomic(size_t size_in_bytes);
-GC_API char * GC_strdup (const char *str);
-GC_API void * GC_malloc_uncollectable(size_t size_in_bytes);
-GC_API void * GC_malloc_stubborn(size_t size_in_bytes);
+GC_API void * GC_CALL GC_malloc(size_t size_in_bytes);
+GC_API void * GC_CALL GC_malloc_atomic(size_t size_in_bytes);
+GC_API char * GC_CALL GC_strdup (const char *str);
+GC_API void * GC_CALL GC_malloc_uncollectable(size_t size_in_bytes);
+GC_API void * GC_CALL GC_malloc_stubborn(size_t size_in_bytes);
+
+/* GC_memalign() is not well tested.   */
+GC_API void * GC_CALL GC_memalign(size_t align, size_t lb);
 
 /* The following is only defined if the library has been suitably      */
 /* compiled:                                                           */
-GC_API void * GC_malloc_atomic_uncollectable(size_t size_in_bytes);
+GC_API void * GC_CALL GC_malloc_atomic_uncollectable(size_t size_in_bytes);
 
 /* Explicitly deallocate an object.  Dangerous if used incorrectly.     */
 /* Requires a pointer to the base of an object.                                */
 /* If the argument is stubborn, it should not be changeable when freed. */
-/* An object should not be enable for finalization when it is          */
+/* An object should not be enabled for finalization when it is         */
 /* explicitly deallocated.                                             */
 /* GC_free(0) is a no-op, as required by ANSI C for free.              */
-GC_API void GC_free(void * object_addr);
+GC_API void GC_CALL GC_free(void * object_addr);
 
 /*
  * Stubborn objects may be changed only if the collector is explicitly informed.
  * The collector is implicitly informed of coming change when such
  * an object is first allocated.  The following routines inform the
  * collector that an object will no longer be changed, or that it will
- * once again be changed.  Only nonNIL pointer stores into the object
+ * once again be changed.  Only non-NULL pointer stores into the object
  * are considered to be changes.  The argument to GC_end_stubborn_change
- * must be exacly the value returned by GC_malloc_stubborn or passed to
+ * must be exactly the value returned by GC_malloc_stubborn or passed to
  * GC_change_stubborn.  (In the second case it may be an interior pointer
  * within 512 bytes of the beginning of the objects.)
  * There is a performance penalty for allowing more than
@@ -291,8 +329,8 @@ GC_API void GC_free(void * object_addr);
  * do so.  The same applies to dropping stubborn objects that are still
  * changeable.
  */
-GC_API void GC_change_stubborn(void *);
-GC_API void GC_end_stubborn_change(void *);
+GC_API void GC_CALL GC_change_stubborn(void *);
+GC_API void GC_CALL GC_end_stubborn_change(void *);
 
 /* Return a pointer to the base (lowest address) of an object given    */
 /* a pointer to a location within the object.                          */
@@ -305,12 +343,12 @@ GC_API void GC_end_stubborn_change(void *);
 /* Note that a deallocated object in the garbage collected heap                */
 /* may be considered valid, even if it has been deallocated with       */
 /* GC_free.                                                            */
-GC_API void * GC_base(void * displaced_pointer);
+GC_API void * GC_CALL GC_base(void * displaced_pointer);
 
 /* Given a pointer to the base of an object, return its size in bytes. */
 /* The returned size may be slightly larger than what was originally   */
 /* requested.                                                          */
-GC_API size_t GC_size(void * object_addr);
+GC_API size_t GC_CALL GC_size(void * object_addr);
 
 /* For compatibility with C library.  This is occasionally faster than */
 /* a malloc followed by a bcopy.  But if you rely on that, either here */
@@ -319,36 +357,36 @@ GC_API size_t GC_size(void * object_addr);
 /* The resulting object has the same kind as the original.             */
 /* If the argument is stubborn, the result will have changes enabled.  */
 /* It is an error to have changes enabled for the original object.     */
-/* Follows ANSI comventions for NULL old_object.                       */
-GC_API void * GC_realloc(void * old_object, size_t new_size_in_bytes);
+/* Follows ANSI conventions for NULL old_object.                       */
+GC_API void * GC_CALL GC_realloc(void * old_object, size_t new_size_in_bytes);
                                   
 /* Explicitly increase the heap size.  */
 /* Returns 0 on failure, 1 on success.  */
-GC_API int GC_expand_hp(size_t number_of_bytes);
+GC_API int GC_CALL GC_expand_hp(size_t number_of_bytes);
 
 /* Limit the heap size to n bytes.  Useful when you're debugging,      */
 /* especially on systems that don't handle running out of memory well. */
 /* n == 0 ==> unbounded.  This is the default.                         */
-GC_API void GC_set_max_heap_size(GC_word n);
-
-GC_API GC_word GC_get_max_heap_size(void);
+GC_API void GC_CALL GC_set_max_heap_size(GC_word n);
 
 /* Inform the collector that a certain section of statically allocated */
 /* memory contains no pointers to garbage collected memory.  Thus it   */
 /* need not be scanned.  This is sometimes important if the application */
 /* maps large read/write files into the address space, which could be  */
 /* mistaken for dynamic library data segments on some systems.         */
-GC_API void GC_exclude_static_roots(void * low_address,
+GC_API void GC_CALL GC_exclude_static_roots(void * low_address,
                                    void * high_address_plus_1);
 
 /* Clear the set of root segments.  Wizards only. */
-GC_API void GC_clear_roots(void);
+GC_API void GC_CALL GC_clear_roots(void);
 
 /* Add a root segment.  Wizards only. */
-GC_API void GC_add_roots(void * low_address, void * high_address_plus_1);
+GC_API void GC_CALL GC_add_roots(void * low_address,
+                               void * high_address_plus_1);
 
 /* Remove a root segment.  Wizards only. */
-GC_API void GC_remove_roots(void * low_address, void * high_address_plus_1);
+GC_API void GC_CALL GC_remove_roots(void * low_address,
+                               void * high_address_plus_1);
 
 /* Add a displacement to the set of those considered valid by the      */
 /* collector.  GC_register_displacement(n) means that if p was returned */
@@ -362,14 +400,14 @@ GC_API void GC_remove_roots(void * low_address, void * high_address_plus_1);
 /* retention.                                                          */
 /* This is a no-op if the collector has recognition of                 */
 /* arbitrary interior pointers enabled, which is now the default.      */
-GC_API void GC_register_displacement(size_t n);
+GC_API void GC_CALL GC_register_displacement(size_t n);
 
 /* The following version should be used if any debugging allocation is */
 /* being done.                                                         */
-GC_API void GC_debug_register_displacement(size_t n);
+GC_API void GC_CALL GC_debug_register_displacement(size_t n);
 
 /* Explicitly trigger a full, world-stop collection.   */
-GC_API void GC_gcollect(void);
+GC_API void GC_CALL GC_gcollect(void);
 
 /* Trigger a full world-stopped collection.  Abort the collection if   */
 /* and when stop_func returns a nonzero value.  Stop_func will be      */
@@ -380,49 +418,56 @@ GC_API void GC_gcollect(void);
 /* aborted collections do no useful work; the next collection needs    */
 /* to start from the beginning.                                                */
 /* Return 0 if the collection was aborted, 1 if it succeeded.          */
-typedef int (* GC_stop_func)(void);
-GC_API int GC_try_to_collect(GC_stop_func stop_func);
+typedef int (GC_CALLBACK * GC_stop_func)(void);
+GC_API int GC_CALL GC_try_to_collect(GC_stop_func stop_func);
 
 /* Return the number of bytes in the heap.  Excludes collector private */
-/* data structures.  Includes empty blocks and fragmentation loss.     */
-/* Includes some pages that were allocated but never written.          */
-GC_API size_t GC_get_heap_size(void);
+/* data structures.  Excludes the unmapped memory (retuned to the OS). */
+/* Includes empty blocks and fragmentation loss.  Includes some pages  */
+/* that were allocated but never written.                              */
+GC_API size_t GC_CALL GC_get_heap_size(void);
+
+/* Return a lower bound on the number of free bytes in the heap                */
+/* (excluding the unmapped memory space).                              */
+GC_API size_t GC_CALL GC_get_free_bytes(void);
 
-/* Return a lower bound on the number of free bytes in the heap.       */
-GC_API size_t GC_get_free_bytes(void);
+/* Return the size (in bytes) of the unmapped memory (which is returned        */
+/* to the OS but could be remapped back by the collector later unless  */
+/* the OS runs out of system/virtual memory).                          */
+GC_API size_t GC_CALL GC_get_unmapped_bytes(void);
 
 /* Return the number of bytes allocated since the last collection.     */
-GC_API size_t GC_get_bytes_since_gc(void);
+GC_API size_t GC_CALL GC_get_bytes_since_gc(void);
 
 /* Return the total number of bytes allocated in this process.         */
 /* Never decreases, except due to wrapping.                            */
-GC_API size_t GC_get_total_bytes(void);
+GC_API size_t GC_CALL GC_get_total_bytes(void);
 
 /* Disable garbage collection.  Even GC_gcollect calls will be                 */
 /* ineffective.                                                                */
-GC_API void GC_disable(void);
+GC_API void GC_CALL GC_disable(void);
 
-/* Reenable garbage collection.  GC_disable() and GC_enable() calls    */
+/* Re-enable garbage collection.  GC_disable() and GC_enable() calls   */
 /* nest.  Garbage collection is enabled if the number of calls to both */
 /* both functions is equal.                                            */
-GC_API void GC_enable(void);
+GC_API void GC_CALL GC_enable(void);
 
 /* Enable incremental/generational collection. */
 /* Not advisable unless dirty bits are                 */
 /* available or most heap objects are          */
-/* pointerfree(atomic) or immutable.           */
+/* pointer-free (atomic) or immutable.         */
 /* Don't use in leak finding mode.             */
 /* Ignored if GC_dont_gc is true.              */
 /* Only the generational piece of this is      */
 /* functional if GC_parallel is TRUE           */
 /* or if GC_time_limit is GC_TIME_UNLIMITED.   */
-/* Causes GC_local_gcj_malloc() to revert to   */
-/* locked allocation.  Must be called          */
-/* before any GC_local_gcj_malloc() calls.     */
+/* Causes thread-local variant of GC_gcj_malloc() to revert to */
+/* locked allocation.  Must be called before any such          */
+/* GC_gcj_malloc() calls.                                      */
 /* For best performance, should be called as early as possible.        */
 /* On some platforms, calling it later may have adverse effects.*/
 /* Safe to call before GC_INIT().  Includes a GC_init() call.  */
-GC_API void GC_enable_incremental(void);
+GC_API void GC_CALL GC_enable_incremental(void);
 
 /* Does incremental mode write-protect pages?  Returns zero or */
 /* more of the following, or'ed together:                      */
@@ -432,7 +477,7 @@ GC_API void GC_enable_incremental(void);
 #define GC_PROTECTS_STACK        8 /* Probably impractical.            */
 
 #define GC_PROTECTS_NONE 0
-GC_API int GC_incremental_protection_needs(void);
+GC_API int GC_CALL GC_incremental_protection_needs(void);
 
 /* Perform some garbage collection work, if appropriate.       */
 /* Return 0 if there is no more work to be done.               */
@@ -441,7 +486,7 @@ GC_API int GC_incremental_protection_needs(void);
 /* progress requires it, e.g. if incremental collection is     */
 /* disabled.  It is reasonable to call this in a wait loop     */
 /* until it returns 0.                                         */
-GC_API int GC_collect_a_little(void);
+GC_API int GC_CALL GC_collect_a_little(void);
 
 /* Allocate an object of size lb bytes.  The client guarantees that    */
 /* as long as the object is live, it will be referenced by a pointer   */
@@ -457,8 +502,8 @@ GC_API int GC_collect_a_little(void);
 /* for arrays likely to be larger than 100K or so.  For other systems, */
 /* or if the collector is not configured to recognize all interior     */
 /* pointers, the threshold is normally much higher.                    */
-GC_API void * GC_malloc_ignore_off_page(size_t lb);
-GC_API void * GC_malloc_atomic_ignore_off_page(size_t lb);
+GC_API void * GC_CALL GC_malloc_ignore_off_page(size_t lb);
+GC_API void * GC_CALL GC_malloc_atomic_ignore_off_page(size_t lb);
 
 #if defined(__sgi) && !defined(__GNUC__) && _COMPILER_VERSION >= 720
 #   define GC_ADD_CALLER
@@ -470,7 +515,7 @@ GC_API void * GC_malloc_atomic_ignore_off_page(size_t lb);
 # if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1 || __GLIBC__ > 2) \
      && !defined(__ia64__) && !defined(__UCLIBC__)
 #   ifndef GC_HAVE_BUILTIN_BACKTRACE
-/* #     define GC_HAVE_BUILTIN_BACKTRACE */
+#     define GC_HAVE_BUILTIN_BACKTRACE
 #   endif
 # endif
 # if defined(__i386__) || defined(__x86_64__)
@@ -523,22 +568,23 @@ GC_API void * GC_malloc_atomic_ignore_off_page(size_t lb);
 
 /* Debugging (annotated) allocation.  GC_gcollect will check           */
 /* objects allocated in this way for overwrites, etc.                  */
-GC_API void * GC_debug_malloc(size_t size_in_bytes, GC_EXTRA_PARAMS);
-GC_API void * GC_debug_malloc_atomic(size_t size_in_bytes, GC_EXTRA_PARAMS);
-GC_API char * GC_debug_strdup(const char *str, GC_EXTRA_PARAMS);
-GC_API void * GC_debug_malloc_uncollectable
+GC_API void * GC_CALL GC_debug_malloc(size_t size_in_bytes, GC_EXTRA_PARAMS);
+GC_API void * GC_CALL GC_debug_malloc_atomic
+       (size_t size_in_bytes, GC_EXTRA_PARAMS);
+GC_API char * GC_CALL GC_debug_strdup(const char *str, GC_EXTRA_PARAMS);
+GC_API void * GC_CALL GC_debug_malloc_uncollectable
        (size_t size_in_bytes, GC_EXTRA_PARAMS);
-GC_API void * GC_debug_malloc_stubborn
+GC_API void * GC_CALL GC_debug_malloc_stubborn
        (size_t size_in_bytes, GC_EXTRA_PARAMS);
-GC_API void * GC_debug_malloc_ignore_off_page
+GC_API void * GC_CALL GC_debug_malloc_ignore_off_page
        (size_t size_in_bytes, GC_EXTRA_PARAMS);
-GC_API void * GC_debug_malloc_atomic_ignore_off_page
+GC_API void * GC_CALL GC_debug_malloc_atomic_ignore_off_page
        (size_t size_in_bytes, GC_EXTRA_PARAMS);
-GC_API void GC_debug_free (void * object_addr);
-GC_API void * GC_debug_realloc
+GC_API void GC_CALL GC_debug_free (void * object_addr);
+GC_API void * GC_CALL GC_debug_realloc
        (void * old_object, size_t new_size_in_bytes, GC_EXTRA_PARAMS);
-GC_API void GC_debug_change_stubborn(void *);
-GC_API void GC_debug_end_stubborn_change(void *);
+GC_API void GC_CALL GC_debug_change_stubborn(void *);
+GC_API void GC_CALL GC_debug_end_stubborn_change(void *);
 
 /* Routines that allocate objects with debug information (like the     */
 /* above), but just fill in dummy file and line number information.    */
@@ -552,8 +598,8 @@ GC_API void GC_debug_end_stubborn_change(void *);
 /*    platforms it may be more convenient not to recompile, e.g. for   */
 /*    leak detection.  This can be accomplished by instructing the     */
 /*    linker to replace malloc/realloc with these.                     */
-GC_API void * GC_debug_malloc_replacement (size_t size_in_bytes);
-GC_API void * GC_debug_realloc_replacement
+GC_API void * GC_CALL GC_debug_malloc_replacement (size_t size_in_bytes);
+GC_API void * GC_CALL GC_debug_realloc_replacement
              (void * object_addr, size_t size_in_bytes);
                                 
 # ifdef GC_DEBUG
@@ -609,7 +655,7 @@ GC_API void * GC_debug_realloc_replacement
 #   define GC_REGISTER_DISPLACEMENT(n) GC_register_displacement(n)
 # endif
 /* The following are included because they are often convenient, and   */
-/* reduce the chance for a misspecifed size argument.  But calls may   */
+/* reduce the chance for a misspecified size argument.  But calls may  */
 /* expand to something syntactically incorrect if t is a complicated   */
 /* type expression.                                                    */
 # define GC_NEW(t) (t *)GC_MALLOC(sizeof (t))
@@ -624,12 +670,13 @@ GC_API void * GC_debug_realloc_replacement
 /* with Alan Demers, Dan Greene, Carl Hauser, Barry Hayes,             */
 /* Christian Jacobi, and Russ Atkinson.  It's not perfect, and         */
 /* probably nobody else agrees with it.            Hans-J. Boehm  3/13/92      */
-typedef void (*GC_finalization_proc) (void * obj, void * client_data);
+typedef void (GC_CALLBACK * GC_finalization_proc) (void * obj,
+                                               void * client_data);
 
-GC_API void GC_register_finalizer(void * obj, GC_finalization_proc fn,
+GC_API void GC_CALL GC_register_finalizer(void * obj, GC_finalization_proc fn,
                                  void * cd, GC_finalization_proc *ofn,
                                  void * *ocd);
-GC_API void GC_debug_register_finalizer
+GC_API void GC_CALL GC_debug_register_finalizer
                 (void * obj, GC_finalization_proc fn, void * cd,
                  GC_finalization_proc *ofn, void * *ocd);
        /* When obj is no longer accessible, invoke             */
@@ -646,10 +693,14 @@ GC_API void GC_debug_register_finalizer
        /* All but the last finalizer registered for an object  */
        /* is ignored.                                          */
        /* Finalization may be removed by passing 0 as fn.      */
-       /* Finalizers are implicitly unregistered just before   */
-       /* they are invoked.                                    */
+       /* Finalizers are implicitly unregistered when they are */
+       /* enqueued for finalization (i.e. become ready to be   */
+       /* finalized).                                          */
        /* The old finalizer and client data are stored in      */
-       /* *ofn and *ocd.                                       */ 
+       /* *ofn and *ocd.  (ofn and/or ocd may be NULL.         */
+       /* The allocation lock is held while *ofn and *ocd are  */
+       /* updated.  In case of error (no memory to register    */
+       /* new finalizer), *ofn and *ocd remain unchanged.)     */
        /* Fn is never invoked on an accessible object,         */
        /* provided hidden pointers are converted to real       */
        /* pointers only if the allocation lock is held, and    */
@@ -659,8 +710,10 @@ GC_API void GC_debug_register_finalizer
        /* a signal, the object may be left with no             */
        /* finalization, even if neither the old nor new        */
        /* finalizer were NULL.                                 */
-       /* Obj should be the nonNULL starting address of an     */
-       /* object allocated by GC_malloc or friends.            */
+       /* Obj should be the starting address of an object      */
+       /* allocated by GC_malloc or friends. Obj may also be   */
+       /* NULL or point to something outside GC heap (in this  */
+       /* case, fn is ignored, *ofn and *ocd are set to NULL). */
        /* Note that any garbage collectable object referenced  */
        /* by cd will be considered accessible until the        */
        /* finalizer is invoked.                                */
@@ -674,10 +727,10 @@ GC_API void GC_debug_register_finalizer
 /* avoid cycles.                                               */
 /* Note that cd will still be viewed as accessible, even if it */
 /* refers to the object itself.                                        */
-GC_API void GC_register_finalizer_ignore_self
+GC_API void GC_CALL GC_register_finalizer_ignore_self
                (void * obj, GC_finalization_proc fn, void * cd,
                 GC_finalization_proc *ofn, void * *ocd);
-GC_API void GC_debug_register_finalizer_ignore_self
+GC_API void GC_CALL GC_debug_register_finalizer_ignore_self
                (void * obj, GC_finalization_proc fn, void * cd,
                 GC_finalization_proc *ofn, void * *ocd);
 
@@ -685,10 +738,10 @@ GC_API void GC_debug_register_finalizer_ignore_self
 /* It should probably only be used by Java implementations.     */
 /* Note that cd will still be viewed as accessible, even if it */
 /* refers to the object itself.                                        */
-GC_API void GC_register_finalizer_no_order
+GC_API void GC_CALL GC_register_finalizer_no_order
                (void * obj, GC_finalization_proc fn, void * cd,
                 GC_finalization_proc *ofn, void * *ocd);
-GC_API void GC_debug_register_finalizer_no_order
+GC_API void GC_CALL GC_debug_register_finalizer_no_order
                (void * obj, GC_finalization_proc fn, void * cd,
                 GC_finalization_proc *ofn, void * *ocd);
 
@@ -708,10 +761,10 @@ GC_API void GC_debug_register_finalizer_no_order
 /* Only works if GC_java_finalization is set.  Probably only   */
 /* of interest when implementing a language that requires      */
 /* unordered finalization (e.g. Java, C#).                     */
-GC_API void GC_register_finalizer_unreachable
+GC_API void GC_CALL GC_register_finalizer_unreachable
                 (void * obj, GC_finalization_proc fn, void * cd,
                  GC_finalization_proc *ofn, void * *ocd);
-GC_API void GC_debug_register_finalizer_unreachable
+GC_API void GC_CALL GC_debug_register_finalizer_unreachable
                 (void * obj, GC_finalization_proc fn, void * cd,
                  GC_finalization_proc *ofn, void * *ocd);
 
@@ -722,7 +775,7 @@ GC_API void GC_debug_register_finalizer_unreachable
 /* where p is a pointer that is not followed by finalization   */
 /* code, and should not be considered in determining           */
 /* finalization order.                                         */
-GC_API int GC_register_disappearing_link(void * * link );
+GC_API int GC_CALL GC_register_disappearing_link(void * * link );
        /* Link should point to a field of a heap allocated     */
        /* object obj.  *link will be cleared when obj is       */
        /* found to be inaccessible.  This happens BEFORE any   */
@@ -743,7 +796,8 @@ GC_API int GC_register_disappearing_link(void * * link );
        /* memory, and GC_oom_fn did not handle the problem.    */
        /* Only exists for backward compatibility.  See below:  */
        
-GC_API int GC_general_register_disappearing_link (void * * link, void * obj);
+GC_API int GC_CALL GC_general_register_disappearing_link (void * * link,
+                                                       void * obj);
        /* A slight generalization of the above. *link is       */
        /* cleared when obj first becomes inaccessible.  This   */
        /* can be used to implement weak pointers easily and    */
@@ -763,29 +817,27 @@ GC_API int GC_general_register_disappearing_link (void * * link, void * obj);
        /* cleared.                                             */
        /* This can be used to implement certain types of       */
        /* weak pointers.  Note however that this generally     */
-       /* requires that thje allocation lock is held (see      */
-       /* GC_call_with_allock_lock() below) when the disguised */
+       /* requires that the allocation lock is held (see       */
+       /* GC_call_with_alloc_lock() below) when the disguised  */
        /* pointer is accessed.  Otherwise a strong pointer     */
        /* could be recreated between the time the collector    */
        /* decides to reclaim the object and the link is        */
        /* cleared.                                             */
 
-GC_API int GC_unregister_disappearing_link (void * * link);
-       /* Returns 0 if link was not actually registered.       */
+GC_API int GC_CALL GC_unregister_disappearing_link (void * * link);
        /* Undoes a registration by either of the above two     */
-       /* routines.                                            */
-
-GC_API void GC_finalize_all();
+       /* routines.  Returns 0 if link was not actually        */
+       /* registered (otherwise returns 1).                    */
 
-/* Returns !=0  if GC_invoke_finalizers has something to do.           */
-GC_API int GC_should_invoke_finalizers(void);
+/* Returns !=0 if GC_invoke_finalizers has something to do.    */
+GC_API int GC_CALL GC_should_invoke_finalizers(void);
 
-GC_API int GC_invoke_finalizers(void);
+GC_API int GC_CALL GC_invoke_finalizers(void);
        /* Run finalizers for all objects that are ready to     */
        /* be finalized.  Return the number of finalizers       */
        /* that were run.  Normally this is also called         */
        /* implicitly during some allocations.  If              */
-       /* GC-finalize_on_demand is nonzero, it must be called  */
+       /* GC_finalize_on_demand is nonzero, it must be called  */
        /* explicitly.                                          */
 
 /* Explicitly tell the collector that an object is reachable   */
@@ -801,20 +853,22 @@ GC_API int GC_invoke_finalizers(void);
 #   define GC_reachable_here(ptr) \
     __asm__ volatile(" " : : "X"(ptr) : "memory");
 # else
-    GC_API void GC_noop1(GC_word x);
+    GC_API void GC_CALL GC_noop1(GC_word x);
 #   define GC_reachable_here(ptr) GC_noop1((GC_word)(ptr));
 #endif
 
 /* GC_set_warn_proc can be used to redirect or filter warning messages.        */
 /* p may not be a NULL pointer.                                                */
-typedef void (*GC_warn_proc) (char *msg, GC_word arg);
-GC_API GC_warn_proc GC_set_warn_proc(GC_warn_proc p);
-    /* Returns old warning procedure.  */
+typedef void (GC_CALLBACK * GC_warn_proc) (char *msg, GC_word arg);
+GC_API void GC_CALL GC_set_warn_proc(GC_warn_proc p);
+/* GC_get_warn_proc returns the current warn_proc.                     */
+GC_API GC_warn_proc GC_CALL GC_get_warn_proc(void);
+
+    /* GC_ignore_warn_proc may be used as an argument for    */
+    /* GC_set_warn_proc() to suppress all warnings (unless   */
+    /* statistics printing is turned on).                   */
+GC_API void GC_CALLBACK GC_ignore_warn_proc(char *msg, GC_word arg);
 
-GC_API GC_word GC_set_free_space_divisor(GC_word value);
-    /* Set free_space_divisor.  See above for definition.      */
-    /* Returns old value.                                      */
-       
 /* The following is intended to be used by a higher level      */
 /* (e.g. Java-like) finalization facility.  It is expected     */
 /* that finalization code will arrange for hidden pointers to  */
@@ -832,8 +886,9 @@ GC_API GC_word GC_set_free_space_divisor(GC_word value);
     /* allocator lock to avoid a race with the collector.              */
 # endif /* I_HIDE_POINTERS */
 
-typedef void * (*GC_fn_type) (void * client_data);
-GC_API void * GC_call_with_alloc_lock (GC_fn_type fn, void * client_data);
+typedef void * (GC_CALLBACK * GC_fn_type) (void * client_data);
+GC_API void * GC_CALL GC_call_with_alloc_lock (GC_fn_type fn,
+                                               void * client_data);
 
 /* These routines are intended to explicitly notify the collector      */
 /* of new threads.  Often this is unnecessary because thread creation  */
@@ -849,40 +904,61 @@ GC_API void * GC_call_with_alloc_lock (GC_fn_type fn, void * client_data);
 /* platforms this contains just a single address.                      */
 struct GC_stack_base {
        void * mem_base;        /* Base of memory stack.        */
-#      if defined(__ia64) || defined(__ia64__)
+#      if defined(__ia64) || defined(__ia64__) || defined(_M_IA64)
          void * reg_base;      /* Base of separate register stack.     */
 #      endif
 };
 
-typedef void * (*GC_stack_base_func)(struct GC_stack_base *sb, void *arg);
+typedef void * (GC_CALLBACK * GC_stack_base_func)(struct GC_stack_base *sb,
+                                               void *arg);
 
 /* Call a function with a stack base structure corresponding to                */
 /* somewhere in the GC_call_with_stack_base frame.  This often can     */
 /* be used to provide a sufficiently accurate stack base.  And we      */
 /* implement it everywhere.                                            */
-GC_API void * GC_call_with_stack_base(GC_stack_base_func fn, void *arg);
+GC_API void * GC_CALL GC_call_with_stack_base(GC_stack_base_func fn,
+                                               void *arg);
+
+/* Explicitly enable GC_register_my_thread() invocation.               */
+/* Done implicitly if a GC thread-creation function is called (or      */
+/* DllMain-based thread registration is enabled).  Otherwise, it must  */
+/* be called from the main (or any previously registered) thread       */
+/* between the collector initialization and the first explicit         */
+/* registering of a thread (it should be called as late as possible).  */
+GC_API void GC_CALL GC_allow_register_threads(void);
 
 /* Register the current thread, with the indicated stack base, as      */
-/* a new thread whose stack(s) should be traced by the GC.  If       */
-/* platform does not implicitly do so, this must be called before a    */
+/* a new thread whose stack(s) should be traced by the GC.  If it      */
+/* is not implicitly called by the GC, this must be called before a    */
 /* thread can allocate garbage collected memory, or assign pointers    */
 /* to the garbage collected heap.  Once registered, a thread will be   */
 /* stopped during garbage collections.                                 */
-/* Return codes:       */
+/* This call must be previously enabled (see above).                   */
+/* This should never be called from the main thread, where it is       */
+/* always done implicitly.  This is normally done implicitly if GC_    */
+/* functions are called to create the thread, e.g. by defining         */
+/* GC_THREADS and including gc.h (which redefines some system          */
+/* functions) before calling the system thread creation function.      */
+/* It is also always done implicitly under win32 with DllMain-based    */
+/* thread registration enabled.  Except in this latter case, explicit  */
+/* calls are normally required for threads created by third-party      */
+/* libraries.                                                          */
 #define GC_SUCCESS 0
 #define GC_DUPLICATE 1 /* Was already registered.      */
 #define GC_NO_THREADS 2        /* No thread support in GC.     */
 #define GC_UNIMPLEMENTED 3     /* Not yet implemented on this platform. */
-GC_API int GC_register_my_thread(struct GC_stack_base *);
+GC_API int GC_CALL GC_register_my_thread(struct GC_stack_base *);
 
-/* Unregister the current thread.  The thread may no longer allocate   */
-/* garbage collected memory or manipulate pointers to the              */
-/* garbage collected heap after making this call.                      */
+/* Unregister the current thread.  Only an explicity registered thread */
+/* (i.e. for which GC_register_my_thread() returns GC_SUCCESS) is      */
+/* allowed (and required) to call this function.  The thread may no    */
+/* longer allocate garbage collected memory or manipulate pointers to  */
+/* the garbage collected heap after making this call.                  */
 /* 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.                            */
-GC_API int GC_unregister_my_thread(void);
+GC_API int GC_CALL GC_unregister_my_thread(void);
 
 /* Attempt to fill in the GC_stack_base structure with the stack base  */
 /* for this thread.  This appears to be required to implement anything */
@@ -890,7 +966,7 @@ GC_API int GC_unregister_my_thread(void);
 /* threads are not automatically registered with the collector.                */
 /* It is also unfortunately hard to implement well on many platforms.  */
 /* Returns GC_SUCCESS or GC_UNIMPLEMENTED.                             */
-GC_API int GC_get_stack_base(struct GC_stack_base *);
+GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *);
 
 /* The following routines are primarily intended for use with a        */
 /* preprocessor which inserts calls to check C pointer arithmetic.     */
@@ -901,14 +977,14 @@ GC_API int GC_get_stack_base(struct GC_stack_base *);
 /* Returns the first argument.                                 */
 /* Succeeds if neither p nor q points to the heap.             */
 /* May succeed if both p and q point to between heap objects.  */
-GC_API void * GC_same_obj (void * p, void * q);
+GC_API void * GC_CALL GC_same_obj (void * p, void * q);
 
 /* Checked pointer pre- and post- increment operations.  Note that     */
 /* the second argument is in units of bytes, not multiples of the      */
 /* object size.  This should either be invoked from a macro, or the    */
 /* call should be automatically generated.                             */
-GC_API void * GC_pre_incr (void * *p, size_t how_much);
-GC_API void * GC_post_incr (void * *p, size_t how_much);
+GC_API void * GC_CALL GC_pre_incr (void * *p, ptrdiff_t how_much);
+GC_API void * GC_CALL GC_post_incr (void * *p, ptrdiff_t how_much);
 
 /* Check that p is visible                                             */
 /* to the collector as a possibly pointer containing location.         */
@@ -918,53 +994,56 @@ GC_API void * GC_post_incr (void * *p, size_t how_much);
 /* untyped allocations.  The idea is that it should be possible, though        */
 /* slow, to add such a call to all indirect pointer stores.)           */
 /* Currently useless for multithreaded worlds.                         */
-GC_API void * GC_is_visible (void * p);
+GC_API void * GC_CALL GC_is_visible (void * p);
 
 /* Check that if p is a pointer to a heap page, then it points to      */
 /* a valid displacement within a heap object.                          */
 /* Fail conspicuously if this property does not hold.                  */
 /* Uninteresting with GC_all_interior_pointers.                                */
 /* Always returns its argument.                                                */
-GC_API void * GC_is_valid_displacement (void * p);
+GC_API void * GC_CALL GC_is_valid_displacement (void * p);
 
 /* Explicitly dump the GC state.  This is most often called from the   */
 /* debugger, or by setting the GC_DUMP_REGULARLY environment variable, */
 /* but it may be useful to call it from client code during debugging.  */
-void GC_dump(void);
+/* Defined only if the library has been compiled without NO_DEBUGGING. */
+GC_API void GC_CALL GC_dump(void);
 
 /* Safer, but slow, pointer addition.  Probably useful mainly with     */
 /* a preprocessor.  Useful only for heap pointers.                     */
-#ifdef GC_DEBUG
+/* Only the macros without trailing digits are meant to be used                */
+/* by clients.  These are designed to model the available C pointer    */
+/* arithmetic expressions.                                             */
+/* Even then, these are probably more useful as                        */
+/* documentation than as part of the API.                              */
+/* Note that GC_PTR_ADD evaluates the first argument more than once.   */
+#if defined(GC_DEBUG) && defined(__GNUC__)
 #   define GC_PTR_ADD3(x, n, type_of_result) \
        ((type_of_result)GC_same_obj((x)+(n), (x)))
 #   define GC_PRE_INCR3(x, n, type_of_result) \
-       ((type_of_result)GC_pre_incr(&(x), (n)*sizeof(*x))
-#   define GC_POST_INCR2(x, type_of_result) \
-       ((type_of_result)GC_post_incr(&(x), sizeof(*x))
-#   ifdef __GNUC__
-#       define GC_PTR_ADD(x, n) \
+       ((type_of_result)GC_pre_incr((void **)(&(x)), (n)*sizeof(*x)))
+#   define GC_POST_INCR3(x, n, type_of_result) \
+       ((type_of_result)GC_post_incr((void **)(&(x)), (n)*sizeof(*x)))
+#   define GC_PTR_ADD(x, n) \
            GC_PTR_ADD3(x, n, typeof(x))
-#       define GC_PRE_INCR(x, n) \
+#   define GC_PRE_INCR(x, n) \
            GC_PRE_INCR3(x, n, typeof(x))
-#       define GC_POST_INCR(x, n) \
-           GC_POST_INCR3(x, typeof(x))
-#   else
+#   define GC_POST_INCR(x) \
+           GC_POST_INCR3(x, 1, typeof(x))
+#   define GC_POST_DECR(x) \
+           GC_POST_INCR3(x, -1, typeof(x))
+#else  /* !GC_DEBUG || !__GNUC__ */
        /* We can't do this right without typeof, which ANSI    */
-       /* decided was not sufficiently useful.  Repeatedly     */
-       /* mentioning the arguments seems too dangerous to be   */
-       /* useful.  So does not casting the result.             */
-#      define GC_PTR_ADD(x, n) ((x)+(n))
-#   endif
-#else  /* !GC_DEBUG */
-#   define GC_PTR_ADD3(x, n, type_of_result) ((x)+(n))
+       /* decided was not sufficiently useful.  Without it     */
+       /* we resort to the non-debug version.                  */
+       /* FIXME: This should eventually support C++0x decltype */
 #   define GC_PTR_ADD(x, n) ((x)+(n))
-#   define GC_PRE_INCR3(x, n, type_of_result) ((x) += (n))
 #   define GC_PRE_INCR(x, n) ((x) += (n))
-#   define GC_POST_INCR2(x, n, type_of_result) ((x)++)
-#   define GC_POST_INCR(x, n) ((x)++)
+#   define GC_POST_INCR(x) ((x)++)
+#   define GC_POST_DECR(x) ((x)--)
 #endif
 
-/* Safer assignment of a pointer to a nonstack location.       */
+/* Safer assignment of a pointer to a non-stack location.      */
 #ifdef GC_DEBUG
 #   define GC_PTR_STORE(p, q) \
        (*(void **)GC_is_visible(p) = GC_is_valid_displacement(q))
@@ -973,11 +1052,11 @@ void GC_dump(void);
 #endif
 
 /* Functions called to report pointer checking errors */
-GC_API void (*GC_same_obj_print_proc) (void * p, void * q);
+GC_API void (GC_CALLBACK * GC_same_obj_print_proc) (void * p, void * q);
 
-GC_API void (*GC_is_valid_displacement_print_proc) (void * p);
+GC_API void (GC_CALLBACK * GC_is_valid_displacement_print_proc) (void * p);
 
-GC_API void (*GC_is_visible_print_proc) (void * p);
+GC_API void (GC_CALLBACK * GC_is_visible_print_proc) (void * p);
 
 
 /* For pthread support, we generally need to intercept a number of     */
@@ -994,9 +1073,7 @@ GC_API void (*GC_is_visible_print_proc) (void * p);
 /* This returns a list of objects, linked through their first          */
 /* word.  Its use can greatly reduce lock contention problems, since   */
 /* the allocation lock can be acquired and released many fewer times.  */
-/* It is used internally by gc_local_alloc.h, which provides a simpler */
-/* programming interface on Linux.                                     */
-void * GC_malloc_many(size_t lb);
+GC_API void * GC_CALL GC_malloc_many(size_t lb);
 #define GC_NEXT(p) (*(void * *)(p))    /* Retrieve the next element    */
                                        /* in returned list.            */
 
@@ -1007,20 +1084,24 @@ void * GC_malloc_many(size_t lb);
    first call a user-supplied routine with filename of the library and
    the address and length of the memory region.  This routine should
    return nonzero if that region should be scanned.  */
-GC_API void 
-GC_register_has_static_roots_callback
-  (int (*callback)(const char *, void *, size_t));
+GC_API void GC_CALL GC_register_has_static_roots_callback
+  (int (GC_CALLBACK * callback)(const char *, void *, size_t));
 
 
 #if defined(GC_WIN32_THREADS) && !defined(__CYGWIN32__) \
        && !defined(__CYGWIN__) \
        && !defined(GC_PTHREADS)
 
+#ifndef GC_NO_THREAD_DECLS
+
 #ifdef __cplusplus
     }  /* Including windows.h in an extern "C" context no longer works. */
 #endif
 
-#ifndef GC_NO_THREAD_DECLS
+# if !defined(_WIN32_WCE)
+#   include <process.h>        /* For _beginthreadex, _endthreadex */
+# endif
+
 # include <windows.h>
 
 #ifdef __cplusplus
@@ -1028,7 +1109,8 @@ GC_register_has_static_roots_callback
 #endif
   /*
    * All threads must be created using GC_CreateThread or GC_beginthreadex,
-   * or must explicitly call GC_register_my_thread,
+   * or must explicitly call GC_register_my_thread
+   * (and call GC_unregister_my_thread before thread termination),
    * so that they will be recorded in the thread table.
    * For backwards compatibility, it is possible to build the GC
    * with GC_DLL defined, and to call GC_use_DllMain().
@@ -1037,25 +1119,26 @@ GC_register_has_static_roots_callback
    *
    * Currently the collector expects all threads to fall through and
    * terminate normally, or call GC_endthreadex() or GC_ExitThread,
-   * so that the thread is properly unregistered.  (An explicit call
-   * to GC_unregister_my_thread() should also work, but risks unregistering
-   * the thread twice.)
+   * so that the thread is properly unregistered.
    */
    GC_API HANDLE WINAPI GC_CreateThread(
       LPSECURITY_ATTRIBUTES lpThreadAttributes,
       DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress,
       LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId );
 
-#  if defined(_MSC_VER) && _MSC_VER >= 1200 && !defined(_UINTPTR_T_DEFINED)
-     typedef unsigned long uintptr_t;
+#  if !defined(_UINTPTR_T) && !defined(_UINTPTR_T_DEFINED) \
+        && !defined(UINTPTR_MAX)
+     typedef GC_word GC_uintptr_t;
+#  else
+     typedef uintptr_t GC_uintptr_t;
 #  endif
 
-   GC_API uintptr_t GC_beginthreadex(
+   GC_API GC_uintptr_t GC_CALL GC_beginthreadex(
      void *security, unsigned stack_size,
      unsigned ( __stdcall *start_address )( void * ),
      void *arglist, unsigned initflag, unsigned *thrdaddr);
 
-   GC_API void GC_endthreadex(unsigned retval);
+   GC_API void GC_CALL GC_endthreadex(unsigned retval);
 
    GC_API void WINAPI GC_ExitThread(DWORD dwExitCode);
 
@@ -1081,14 +1164,16 @@ GC_register_has_static_roots_callback
    * Should be avoided if GC_beginthreadex and friends can be called
    * instead.
    */
-GC_API void GC_use_DllMain(void);
+GC_API void GC_CALL GC_use_DllMain(void);
 
 # ifndef GC_NO_THREAD_REDIRECTS
 #   define CreateThread GC_CreateThread
 #   define ExitThread GC_ExitThread
+#   undef _beginthreadex
 #   define _beginthreadex GC_beginthreadex
+#   undef _endthreadex
 #   define _endthreadex GC_endthreadex
-#   define _beginthread { > "Please use _beginthreadex instead of _beginthread" < }
+/* #   define _beginthread { > "Please use _beginthreadex instead of _beginthread" < } */
 # endif /* !GC_NO_THREAD_REDIRECTS */
 
 #endif /* defined(GC_WIN32_THREADS)  && !cygwin */
@@ -1130,22 +1215,19 @@ GC_API void GC_use_DllMain(void);
 #   define GC_INIT() { GC_init(); }
 #endif
 
-#if !defined(_WIN32_WCE) \
-    && ((defined(_MSDOS) || defined(_MSC_VER)) && (_M_IX86 >= 300) \
-        || defined(_WIN32) && !defined(__CYGWIN32__) && !defined(__CYGWIN__))
   /* win32S may not free all resources on process exit.  */
   /* This explicitly deallocates the heap.              */
-    GC_API void GC_win32_free_heap ();
-#endif
+GC_API void GC_CALL GC_win32_free_heap(void);
 
 #if ( defined(_AMIGA) && !defined(GC_AMIGA_MAKINGLIB) )
   /* Allocation really goes through GC_amiga_allocwrapper_do */
 # include "gc_amiga_redirects.h"
 #endif
 
-#if defined(GC_REDIRECT_TO_LOCAL)
-  /* Now redundant; that's the default with THREAD_LOCAL_ALLOC */
-#endif
+  /*
+   * GC_REDIRECT_TO_LOCAL is now redundant;
+   * that's the default with THREAD_LOCAL_ALLOC.
+   */
 
 #ifdef __cplusplus
     }  /* end of extern "C" */