Merge with symbian_libgc_7x branch
authorIvan Maidanski <ivmai@mail.ru>
Sun, 18 Mar 2012 12:04:58 +0000 (16:04 +0400)
committerIvan Maidanski <ivmai@mail.ru>
Sun, 18 Mar 2012 13:34:09 +0000 (17:34 +0400)
1  2 
build/s60v3/bld.inf
build/s60v3/libgc.mmp
global_end.cpp
global_start.cpp
include/gc_config_macros.h
include/init_global_static_roots.h
include/private/gc_priv.h
include/private/gcconfig.h
init_global_static_roots.cpp
misc.c
os_dep.c

index 0000000,4c3855e..491fcf4
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,15 +1,11 @@@
 -/*\r
 -============================================================================\r
 - Name         : bld.inf\r
 - Author         : \r
 - Copyright   : \r
 - Description : This file provides the information required for building the\r
 -                              whole of a libgc.\r
 -============================================================================\r
 -*/\r
 -\r
 -PRJ_PLATFORMS\r
 -default armv5\r
 -\r
 -PRJ_MMPFILES\r
 -libgc.mmp\r
++/*
++ Name : bld.inf
++ Description : This file provides the information required for building the
++ whole of a libgc.
++*/
++
++PRJ_PLATFORMS
++default armv5
++
++PRJ_MMPFILES
++libgc.mmp
index 0000000,bbee121..f707ab2
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,70 +1,72 @@@
 -TARGET     libgc.dll\r
 -\r
 -TARGETTYPE        dll\r
 -UID       0x1000008d 0x200107C2 // check uid\r
 -\r
 -EXPORTUNFROZEN\r
 -EPOCALLOWDLLDATA\r
 -//ALWAYS_BUILD_AS_ARM\r
 -//nocompresstarget\r
 -//srcdbg\r
 -//baseaddress 00500000\r
 -//LINKEROPTION CW -map libgc.map\r
 -//LINKEROPTION CW -filealign 0x10000\r
 -\r
 -CAPABILITY PowerMgmt ReadDeviceData ReadUserData WriteDeviceData WriteUserData SwEvent LocalServices NetworkServices UserEnvironment\r
 -\r
 -\r
 -MACRO ALL_INTERIOR_POINTERS\r
 -MACRO GC_DLL\r
 -MACRO GC_BUILD\r
 -MACRO SYMBIAN\r
 -\r
 -USERINCLUDE    ..\..\include\r
 -USERINCLUDE    ..\..\include\private\r
 -\r
 -SYSTEMINCLUDE   \epoc32\include\r
 -SYSTEMINCLUDE   \epoc32\include\stdapis\r
 -\r
 -SOURCEPATH      ..\..\\r
 -\r
 -SOURCE                  allchblk.c\r
 -SOURCE                        alloc.c\r
 -SOURCE                        blacklst.c\r
 -SOURCE                        dbg_mlc.c\r
 -SOURCE                        dyn_load.c\r
 -SOURCE                        finalize.c\r
 -//SOURCE                      gc_cpp.cpp\r
 -SOURCE                        headers.c\r
 -SOURCE                        mach_dep.c\r
 -SOURCE                        malloc.c\r
 -SOURCE                        mallocx.c\r
 -SOURCE                        mark.c\r
 -SOURCE                        mark_rts.c\r
 -SOURCE                        misc.c\r
 -SOURCE                        new_hblk.c\r
 -SOURCE                        obj_map.c\r
 -SOURCE                        os_dep.c\r
 -SOURCE                        symbian.cpp\r
 -SOURCE                        ptr_chck.c\r
 -SOURCE                        reclaim.c\r
 -SOURCE                        stubborn.c\r
 -SOURCE                        typd_mlc.c\r
 -\r
 -/*\r
 -#ifdef ENABLE_ABIV2_MODE\r
 -  DEBUGGABLE_UDEBONLY\r
 -#endif\r
 -*/\r
 -\r
 -// Using main() as entry point\r
 -STATICLIBRARY   libcrt0.lib\r
 -\r
 -// libc and euser are always needed when using main() entry point\r
 -LIBRARY         libc.lib \r
 -\r
 -\r
 -LIBRARY euser.lib\r
 -LIBRARY efsrv.lib\r
 -LIBRARY avkon.lib\r
++TARGET     libgc.dll
++
++TARGETTYPE        dll
++UID       0x1000008d 0x200107C2 // check uid
++
++EXPORTUNFROZEN
++EPOCALLOWDLLDATA
++//ALWAYS_BUILD_AS_ARM
++//nocompresstarget
++//srcdbg
++//baseaddress   00500000
++//LINKEROPTION CW -map libgc.map
++//LINKEROPTION CW -filealign 0x10000
++
++CAPABILITY PowerMgmt ReadDeviceData ReadUserData WriteDeviceData WriteUserData SwEvent LocalServices NetworkServices UserEnvironment
++
++
++MACRO ALL_INTERIOR_POINTERS
++MACRO NO_EXECUTE_PERMISSION
++MACRO USE_MMAP
++MACRO GC_DLL
++MACRO GC_BUILD
++MACRO SYMBIAN
++
++USERINCLUDE      ..\..\include
++USERINCLUDE      ..\..\include\private
++
++SYSTEMINCLUDE   \epoc32\include
++SYSTEMINCLUDE   \epoc32\include\stdapis
++
++SOURCEPATH        ..\..\
++
++SOURCE          allchblk.c
++SOURCE          alloc.c
++SOURCE          blacklst.c
++SOURCE          dbg_mlc.c
++SOURCE          dyn_load.c
++SOURCE          finalize.c
++//SOURCE        gc_cpp.cpp
++SOURCE          headers.c
++SOURCE          mach_dep.c
++SOURCE          malloc.c
++SOURCE          mallocx.c
++SOURCE          mark.c
++SOURCE          mark_rts.c
++SOURCE          misc.c
++SOURCE          new_hblk.c
++SOURCE          obj_map.c
++SOURCE          os_dep.c
++SOURCE          symbian.cpp
++SOURCE          ptr_chck.c
++SOURCE          reclaim.c
++SOURCE          stubborn.c
++SOURCE          typd_mlc.c
++
++/*
++#ifdef ENABLE_ABIV2_MODE
++  DEBUGGABLE_UDEBONLY
++#endif
++*/
++
++// Using main() as entry point
++STATICLIBRARY   libcrt0.lib
++
++// libc and euser are always needed when using main() entry point
++LIBRARY         libc.lib
++
++
++LIBRARY euser.lib
++LIBRARY efsrv.lib
++LIBRARY avkon.lib
+ LIBRARY eikcore.lib
diff --cc global_end.cpp
index 0000000,f47e19a..2980747
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,16 +1,15 @@@
 -#include "gcconfig.h"
+ // INCLUDE FILES
 -      }
++#include "private/gcconfig.h"
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+ int winscw_data_end;
+ #ifdef __cplusplus
 -
++        }
+ #endif
+ // End Of File
index 0000000,8d0ca20..1406a50
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,16 +1,15 @@@
 -#include "gcconfig.h"
+ // INCLUDE FILES
 -      }
++#include "private/gcconfig.h"
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+ int winscw_data_start;
+ #ifdef __cplusplus
 -
++        }
+ #endif
+ // End Of File
  # endif
  #endif /* GC_THREADS */
  
 -#if defined(GC_THREADS) && !defined(GC_PTHREADS) && !defined(GC_WIN32_THREADS) \
 -    && (defined(_WIN32) || defined(_MSC_VER) || defined(__CYGWIN__) \
 -     || defined(__MINGW32__) || defined(__BORLANDC__) \
 -     || defined(_WIN32_WCE))
 -# define GC_WIN32_THREADS
 -# if defined(__CYGWIN__)
 -#   define GC_PTHREADS
 +#undef GC_PTHREADS
 +#if (!defined(GC_WIN32_THREADS) || defined(GC_WIN32_PTHREADS) \
 +     || defined(GC_RTEMS_PTHREADS) || defined(__CYGWIN32__) \
 +     || defined(__CYGWIN__)) && defined(GC_THREADS)
 +  /* Posix threads. */
 +# define GC_PTHREADS
 +#endif
 +
 +#if !defined(_PTHREADS) && defined(GC_NETBSD_THREADS)
 +# define _PTHREADS
 +#endif
 +
 +#if defined(GC_DGUX386_THREADS) && !defined(_POSIX4A_DRAFT10_SOURCE)
 +# define _POSIX4A_DRAFT10_SOURCE 1
 +#endif
 +
 +#if !defined(_REENTRANT) && defined(GC_PTHREADS) && !defined(GC_WIN32_THREADS)
 +  /* Better late than never.  This fails if system headers that depend  */
 +  /* on this were previously included.                                  */
 +# define _REENTRANT
 +#endif
 +
 +#define __GC
 +#if !defined(_WIN32_WCE) || defined(__GNUC__)
 +# include <stddef.h>
 +# if defined(__MINGW32__) && !defined(_WIN32_WCE)
 +#   include <stdint.h>
 +    /* We mention uintptr_t.                                            */
 +    /* Perhaps this should be included in pure msft environments        */
 +    /* as well?                                                         */
 +# endif
 +#else /* _WIN32_WCE */
 +  /* Yet more kludges for WinCE.        */
 +# include <stdlib.h> /* size_t is defined here */
 +# ifndef _PTRDIFF_T_DEFINED
 +    /* ptrdiff_t is not defined */
 +#   define _PTRDIFF_T_DEFINED
 +    typedef long ptrdiff_t;
  # endif
 +#endif /* _WIN32_WCE */
 +
 +#if !defined(GC_NOT_DLL) && !defined(GC_DLL) \
 +    && ((defined(_DLL) && !defined(__GNUC__)) \
 +        || (defined(DLL_EXPORT) && defined(GC_BUILD)))
 +# define GC_DLL
  #endif
  
 -# define __GC
 -# ifndef _WIN32_WCE
 -#   include <stddef.h>
 -#   if defined(__MINGW32__)
 -#     include <stdint.h>
 -      /* We mention uintptr_t.                                            */
 -      /* Perhaps this should be included in pure msft environments  */
 -      /* as well?                                                 */
 +#if defined(GC_DLL) && !defined(GC_API)
 +
 +# if defined(__MINGW32__) || defined(__CEGCC__)
 +#   ifdef GC_BUILD
 +#     define GC_API __declspec(dllexport)
 +#   else
 +#     define GC_API __declspec(dllimport)
 +#   endif
 +
 +# elif defined(_MSC_VER) || defined(__DMC__) || defined(__BORLANDC__) \
 +        || defined(__CYGWIN__)
 +#   ifdef GC_BUILD
 +#     define GC_API extern __declspec(dllexport)
 +#   else
 +#     define GC_API __declspec(dllimport)
 +#   endif
 +
 +# elif defined(__WATCOMC__)
 +#   ifdef GC_BUILD
 +#     define GC_API extern __declspec(dllexport)
 +#   else
 +#     define GC_API extern __declspec(dllimport)
 +#   endif
 +
++# elif defined(__SYMBIAN32__)
++#   ifdef GC_BUILD
++#     define GC_API extern EXPORT_C
++#   else
++#     define GC_API extern IMPORT_C
++#   endif
++
 +# elif defined(__GNUC__)
 +    /* Only matters if used in conjunction with -fvisibility=hidden option. */
 +#   if defined(GC_BUILD) && (__GNUC__ >= 4 \
 +                             || defined(GC_VISIBILITY_HIDDEN_SET))
 +#     define GC_API extern __attribute__((__visibility__("default")))
  #   endif
 -# else /* ! _WIN32_WCE */
 -/* Yet more kluges for WinCE */
 -#   include <stdlib.h>                /* size_t is defined here */
 -    typedef long ptrdiff_t;   /* ptrdiff_t is not defined */
  # endif
 +#endif /* GC_DLL */
  
 -#if defined(_DLL) && !defined(GC_NOT_DLL) && !defined(GC_DLL)
 -# define GC_DLL
 +#ifndef GC_API
 +# define GC_API extern
  #endif
  
 -#if defined(__MINGW32__) && defined(GC_DLL)
 -# ifdef GC_BUILD
 -#   define GC_API __declspec(dllexport)
 +#ifndef GC_CALL
 +# define GC_CALL
 +#endif
 +
 +#ifndef GC_CALLBACK
 +# define GC_CALLBACK GC_CALL
 +#endif
 +
 +#ifndef GC_ATTR_MALLOC
 +  /* 'malloc' attribute should be used for all malloc-like functions    */
 +  /* (to tell the compiler that a function may be treated as if any     */
 +  /* non-NULL pointer it returns cannot alias any other pointer valid   */
 +  /* when the function returns).  If the client code violates this rule */
 +  /* by using custom GC_oom_func then define GC_OOM_FUNC_RETURNS_ALIAS. */
 +# ifdef GC_OOM_FUNC_RETURNS_ALIAS
 +#   define GC_ATTR_MALLOC /* empty */
 +# elif defined(__GNUC__) && (__GNUC__ > 3 \
 +                             || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
 +#   define GC_ATTR_MALLOC __attribute__((__malloc__))
 +# elif defined(_MSC_VER) && _MSC_VER >= 14
 +#   define GC_ATTR_MALLOC __declspec(noalias) __declspec(restrict)
  # else
 -#   define GC_API __declspec(dllimport)
 +#   define GC_ATTR_MALLOC
  # endif
  #endif
  
index 0000000,cfc4b0d..32fdce5
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,13 +1,15 @@@
 -extern "C" {
++
+ #ifndef __INIT_GLOBAL_STATIC_ROOTS_H_
+ #define __INIT_GLOBAL_STATIC_ROOTS_H_
+ #ifdef __cplusplus
 -void init_global_static_roots();
++  extern "C" {
+ #endif
 -      }
++
++void init_global_static_roots(void);
+ #ifdef __cplusplus
 -#endif // __INIT_GLOBAL_STATIC_ROOTS_H_
++  }
+ #endif
++#endif
@@@ -1983,317 -1906,140 +1983,325 @@@ extern word GC_fo_entries; /* should b
  #endif
  
  /* Make arguments appear live to compiler */
 -# ifdef __WATCOMC__
 -    void GC_noop(void*, ...);
 +#if defined(__BORLANDC__) || defined(__WATCOMC__) || defined(__CC_ARM)
 +  void GC_noop(void*, ...);
 +#else
 +# ifdef __DMC__
 +    void GC_noop(...);
  # else
 -#   ifdef __DMC__
 -      GC_API void GC_noop(...);
 -#   else
 -      GC_API void GC_noop();
 -#   endif
 +    void GC_noop();
  # endif
 +#endif
  
 -void GC_noop1(word);
 +GC_API void GC_CALL GC_noop1(word);
  
 -/* Logging and diagnostic output:     */
 -GC_API void GC_printf (const char * format, ...);
 -                      /* A version of printf that doesn't allocate,   */
 -                      /* 1K total output length.                      */
 -                      /* (We use sprintf.  Hopefully that doesn't     */
 -                      /* allocate for long arguments.)                */
 -GC_API void GC_err_printf(const char * format, ...);
 +#ifndef GC_ATTR_FORMAT_PRINTF
 +# if defined(__GNUC__) && __GNUC__ >= 3
 +#   define GC_ATTR_FORMAT_PRINTF(spec_argnum, first_checked) \
 +        __attribute__((__format__(__printf__, spec_argnum, first_checked)))
 +# else
 +#   define GC_ATTR_FORMAT_PRINTF(spec_argnum, first_checked)
 +# endif
 +#endif
  
 -#ifdef __cplusplus
 -extern "C" {
 +/* Logging and diagnostic output:       */
 +GC_API_PRIV void GC_printf(const char * format, ...)
 +                        GC_ATTR_FORMAT_PRINTF(1, 2);
 +                        /* A version of printf that doesn't allocate,   */
 +                        /* 1K total output length.                      */
 +                        /* (We use sprintf.  Hopefully that doesn't     */
 +                        /* allocate for long arguments.)                */
 +GC_API_PRIV void GC_err_printf(const char * format, ...)
 +                        GC_ATTR_FORMAT_PRINTF(1, 2);
++
++#if defined(__cplusplus) && defined(SYMBIAN)
++  extern "C" {
+ #endif
 -GC_API void GC_log_printf(const char * format, ...);
 -#ifdef __cplusplus
 -      }
 +GC_API_PRIV void GC_log_printf(const char * format, ...)
 +                        GC_ATTR_FORMAT_PRINTF(1, 2);
++#if defined(__cplusplus) && defined(SYMBIAN)
++  }
+ #endif
  void GC_err_puts(const char *s);
 -                      /* Write s to stderr, don't buffer, don't add   */
 -                      /* newlines, don't ...                          */
 +                        /* Write s to stderr, don't buffer, don't add   */
 +                        /* newlines, don't ...                          */
 +
 +GC_EXTERN unsigned GC_fail_count;
 +                        /* How many consecutive GC/expansion failures?  */
 +                        /* Reset by GC_allochblk(); defined in alloc.c. */
 +
 +GC_EXTERN long GC_large_alloc_warn_interval; /* defined in misc.c */
  
 -#if defined(LINUX) && !defined(SMALL_CONFIG)
 -  void GC_err_write(const char *buf, size_t len);
 -                      /* Write buf to stderr, don't buffer, don't add */
 -                      /* newlines, don't ...                          */
 +GC_EXTERN signed_word GC_bytes_found;
 +                /* Number of reclaimed bytes after garbage collection;  */
 +                /* protected by GC lock; defined in reclaim.c.          */
 +
 +#ifdef USE_MUNMAP
 +  GC_EXTERN int GC_unmap_threshold; /* defined in allchblk.c */
 +  GC_EXTERN GC_bool GC_force_unmap_on_gcollect; /* defined in misc.c */
 +#endif
 +
 +#ifdef MSWIN32
 +  GC_EXTERN GC_bool GC_no_win32_dlls; /* defined in os_dep.c */
 +  GC_EXTERN GC_bool GC_wnt;     /* Is Windows NT derivative;    */
 +                                /* defined and set in os_dep.c. */
  #endif
  
 +#ifdef THREADS
 +# if defined(MSWIN32) || defined(MSWINCE)
 +    GC_EXTERN CRITICAL_SECTION GC_write_cs; /* defined in misc.c */
 +#   ifdef GC_ASSERTIONS
 +      GC_EXTERN GC_bool GC_write_disabled;
 +                                /* defined in win32_threads.c;  */
 +                                /* protected by GC_write_cs.    */
 +
 +#   endif
 +# endif
 +# ifdef MPROTECT_VDB
 +    GC_EXTERN volatile AO_TS_t GC_fault_handler_lock;
 +                                        /* defined in os_dep.c */
 +# endif
 +# ifdef MSWINCE
 +    GC_EXTERN GC_bool GC_dont_query_stack_min;
 +                                /* Defined and set in os_dep.c. */
 +# endif
 +#elif defined(IA64)
 +  GC_EXTERN ptr_t GC_save_regs_ret_val; /* defined in mach_dep.c. */
 +                        /* Previously set to backing store pointer.     */
 +#endif /* !THREADS */
 +
 +#ifdef THREAD_LOCAL_ALLOC
 +  GC_EXTERN GC_bool GC_world_stopped; /* defined in alloc.c */
 +  GC_INNER void GC_mark_thread_local_free_lists(void);
 +#endif
  
 +#ifdef GC_GCJ_SUPPORT
  # ifdef GC_ASSERTIONS
 -#     define GC_ASSERT(expr) if(!(expr)) {\
 -              GC_err_printf("Assertion failure: %s:%ld\n", \
 -                              __FILE__, (unsigned long)__LINE__); \
 -              ABORT("assertion failure"); }
 -# else 
 -#     define GC_ASSERT(expr)
 +    GC_EXTERN GC_bool GC_gcj_malloc_initialized; /* defined in gcj_mlc.c */
 +# endif
 +  GC_EXTERN ptr_t * GC_gcjobjfreelist;
 +#endif
 +
 +#if defined(GWW_VDB) && defined(MPROTECT_VDB)
 +  GC_INNER GC_bool GC_gww_dirty_init(void);
 +  /* Defined in os_dep.c.  Returns TRUE if GetWriteWatch is available.  */
 +  /* May be called repeatedly.                                          */
 +#endif
 +
 +#if defined(CHECKSUMS) || defined(PROC_VDB)
 +  GC_INNER GC_bool GC_page_was_ever_dirty(struct hblk * h);
 +                        /* Could the page contain valid heap pointers?  */
 +#endif
 +
 +GC_INNER void GC_default_print_heap_obj_proc(ptr_t p);
 +
 +GC_INNER void GC_extend_size_map(size_t); /* in misc.c */
 +
 +GC_INNER void GC_setpagesize(void);
 +
 +GC_INNER void GC_initialize_offsets(void);      /* defined in obj_map.c */
 +
 +GC_INNER void GC_bl_init(void);
 +GC_INNER void GC_bl_init_no_interiors(void);    /* defined in blacklst.c */
 +
 +GC_INNER void GC_start_debugging(void); /* defined in dbg_mlc.c */
 +
 +/* Store debugging info into p.  Return displaced pointer.      */
 +/* Assumes we don't hold allocation lock.                       */
 +GC_INNER ptr_t GC_store_debug_info(ptr_t p, word sz, const char *str,
 +                                   int linenum);
 +
 +#ifdef REDIRECT_MALLOC
 +# ifdef GC_LINUX_THREADS
 +    GC_INNER GC_bool GC_text_mapping(char *nm, ptr_t *startp, ptr_t *endp);
 +                                                /* from os_dep.c */
 +# endif
 +#elif defined(USE_WINALLOC)
 +  GC_INNER void GC_add_current_malloc_heap(void);
 +#endif /* !REDIRECT_MALLOC */
 +
 +#ifdef MAKE_BACK_GRAPH
 +  GC_INNER void GC_build_back_graph(void);
 +  GC_INNER void GC_traverse_back_graph(void);
 +#endif
 +
 +#ifdef MSWIN32
 +  GC_INNER void GC_init_win32(void);
 +#endif
 +
 +#if !defined(MSWIN32) && !defined(MSWINCE) && !defined(CYGWIN32)
 +  GC_INNER void * GC_roots_present(ptr_t);
 +        /* The type is a lie, since the real type doesn't make sense here, */
 +        /* and we only test for NULL.                                      */
 +#endif
 +
 +#ifdef GC_WIN32_THREADS
 +  GC_INNER void GC_get_next_stack(char *start, char * limit, char **lo,
 +                                  char **hi);
 +# ifdef MPROTECT_VDB
 +    GC_INNER void GC_set_write_fault_handler(void);
 +# endif
 +#endif /* GC_WIN32_THREADS */
 +
 +#ifdef THREADS
 +  GC_INNER void GC_reset_finalizer_nested(void);
 +  GC_INNER unsigned char *GC_check_finalizer_nested(void);
 +  GC_INNER void GC_do_blocking_inner(ptr_t data, void * context);
 +  GC_INNER void GC_push_all_stacks(void);
 +# ifdef USE_PROC_FOR_LIBRARIES
 +    GC_INNER GC_bool GC_segment_is_thread_stack(ptr_t lo, ptr_t hi);
  # endif
 +# ifdef IA64
 +    GC_INNER ptr_t GC_greatest_stack_base_below(ptr_t bound);
 +# endif
 +#endif /* THREADS */
 +
 +#ifdef DYNAMIC_LOADING
 +  GC_INNER GC_bool GC_register_main_static_data(void);
 +# ifdef DARWIN
 +    GC_INNER void GC_init_dyld(void);
 +# endif
 +#endif /* DYNAMIC_LOADING */
 +
 +#ifdef SEARCH_FOR_DATA_START
 +  GC_INNER void GC_init_linux_data_start(void);
 +#endif
 +
 +#if defined(NETBSD) && defined(__ELF__)
 +  GC_INNER void GC_init_netbsd_elf(void);
 +#endif
 +
 +#ifdef UNIX_LIKE
 +  GC_INNER void GC_set_and_save_fault_handler(void (*handler)(int));
 +#endif
 +
 +#ifdef NEED_PROC_MAPS
 +# if defined(DYNAMIC_LOADING) && defined(USE_PROC_FOR_LIBRARIES)
 +    GC_INNER char *GC_parse_map_entry(char *buf_ptr, ptr_t *start, ptr_t *end,
 +                                      char **prot, unsigned int *maj_dev,
 +                                      char **mapping_name);
 +# endif
 +  GC_INNER char *GC_get_maps(void); /* from os_dep.c */
 +#endif /* NEED_PROC_MAPS */
  
 -/* Check a compile time assertion at compile time.  The error */
 -/* message for failure is a bit baroque, but ...              */
 +#ifdef GC_ASSERTIONS
 +# define GC_ASSERT(expr) \
 +                if (!(expr)) { \
 +                  GC_err_printf("Assertion failure: %s:%d\n", \
 +                                __FILE__, __LINE__); \
 +                  ABORT("assertion failure"); \
 +                }
 +  GC_INNER word GC_compute_large_free_bytes(void);
 +  GC_INNER word GC_compute_root_size(void);
 +#else
 +# define GC_ASSERT(expr)
 +#endif
 +
 +/* Check a compile time assertion at compile time.  The error   */
 +/* message for failure is a bit baroque, but ...                */
  #if defined(mips) && !defined(__GNUC__)
 -/* DOB: MIPSPro C gets an internal error taking the sizeof an array type. 
 +/* DOB: MIPSPro C gets an internal error taking the sizeof an array type.
     This code works correctly (ugliness is to avoid "unused var" warnings) */
 -# define GC_STATIC_ASSERT(expr) do { if (0) { char j[(expr)? 1 : -1]; j[0]='\0'; j[0]=j[0]; } } while(0)
 +# define GC_STATIC_ASSERT(expr) \
 +    do { if (0) { char j[(expr)? 1 : -1]; j[0]='\0'; j[0]=j[0]; } } while(0)
  #else
 -# define GC_STATIC_ASSERT(expr) sizeof(char[(expr)? 1 : -1])
 -#endif
 -
 -# if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
 -    /* We need additional synchronization facilities from the thread  */
 -    /* support.  We believe these are less performance critical               */
 -    /* than the main garbage collector lock; standard pthreads-based  */
 -    /* implementations should be sufficient.                          */
 -
 -    /* The mark lock and condition variable.  If the GC lock is also  */
 -    /* acquired, the GC lock must be acquired first.  The mark lock is        */
 -    /* used to both protect some variables used by the parallel               */
 -    /* marker, and to protect GC_fl_builder_count, below.             */
 -    /* GC_notify_all_marker() is called when                          */ 
 -    /* the state of the parallel marker changes                               */
 -    /* in some significant way (see gc_mark.h for details).  The      */
 -    /* latter set of events includes incrementing GC_mark_no.         */
 -    /* GC_notify_all_builder() is called when GC_fl_builder_count     */
 -    /* reaches 0.                                                     */
 -
 -     extern void GC_acquire_mark_lock();
 -     extern void GC_release_mark_lock();
 -     extern void GC_notify_all_builder();
 -     /* extern void GC_wait_builder(); */
 -     extern void GC_wait_for_reclaim();
 -
 -     extern word GC_fl_builder_count; /* Protected by mark lock.      */
 -# endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */
 -# ifdef PARALLEL_MARK
 -     extern void GC_notify_all_marker();
 -     extern void GC_wait_marker();
 -     extern word GC_mark_no;          /* Protected by mark lock.      */
 -
 -     extern void GC_help_marker(word my_mark_no);
 -              /* Try to help out parallel marker for mark cycle       */
 -              /* my_mark_no.  Returns if the mark cycle finishes or   */
 -              /* was already done, or there was nothing to do for     */
 -              /* some other reason.                                   */
 -# endif /* PARALLEL_MARK */
 -
 -# if defined(GC_PTHREADS)
 -  /* We define the thread suspension signal here, so that we can refer        */
 -  /* to it in the dirty bit implementation, if necessary.  Ideally we */
 -  /* would allocate a (real-time ?) signal using the standard mechanism.*/
 -  /* unfortunately, there is no standard mechanism.  (There is one    */
 -  /* in Linux glibc, but it's not exported.)  Thus we continue to use */
 -  /* the same hard-coded signals we've always used.                   */
 -#  if !defined(SIG_SUSPEND)
 -#   if defined(GC_LINUX_THREADS) || defined(GC_DGUX386_THREADS)
 -#    if defined(SPARC) && !defined(SIGPWR)
 -       /* SPARC/Linux doesn't properly define SIGPWR in <signal.h>.
 -        * It is aliased to SIGLOST in asm/signal.h, though.           */
 -#      define SIG_SUSPEND SIGLOST
 -#    else
 -       /* Linuxthreads itself uses SIGUSR1 and SIGUSR2.                       */
 -#      define SIG_SUSPEND SIGPWR
 -#    endif
 -#   else  /* !GC_LINUX_THREADS */
 -#     if defined(_SIGRTMIN)
 -#       define SIG_SUSPEND _SIGRTMIN + 6
 -#     else
 -#       define SIG_SUSPEND SIGRTMIN + 6
 -#     endif       
 +# define GC_STATIC_ASSERT(expr) (void)sizeof(char[(expr)? 1 : -1])
 +#endif
 +
 +#define COND_DUMP_CHECKS { \
 +          GC_ASSERT(GC_compute_large_free_bytes() == GC_large_free_bytes); \
 +          GC_ASSERT(GC_compute_root_size() == GC_root_size); }
 +
 +#ifndef NO_DEBUGGING
 +  GC_EXTERN GC_bool GC_dump_regularly;
 +                                /* Generate regular debugging dumps.    */
 +# define COND_DUMP { if (EXPECT(GC_dump_regularly, FALSE)) GC_dump(); \
 +                        else COND_DUMP_CHECKS; }
 +#else
 +# define COND_DUMP COND_DUMP_CHECKS
 +#endif
 +
 +#if defined(PARALLEL_MARK)
 +  /* We need additional synchronization facilities from the thread      */
 +  /* support.  We believe these are less performance critical           */
 +  /* than the main garbage collector lock; standard pthreads-based      */
 +  /* implementations should be sufficient.                              */
 +
 +# define GC_markers_m1 GC_parallel
 +                        /* Number of mark threads we would like to have */
 +                        /* excluding the initiating thread.             */
 +
 +  /* The mark lock and condition variable.  If the GC lock is also      */
 +  /* acquired, the GC lock must be acquired first.  The mark lock is    */
 +  /* used to both protect some variables used by the parallel           */
 +  /* marker, and to protect GC_fl_builder_count, below.                 */
 +  /* GC_notify_all_marker() is called when                              */
 +  /* the state of the parallel marker changes                           */
 +  /* in some significant way (see gc_mark.h for details).  The          */
 +  /* latter set of events includes incrementing GC_mark_no.             */
 +  /* GC_notify_all_builder() is called when GC_fl_builder_count         */
 +  /* reaches 0.                                                         */
 +
 +  GC_INNER void GC_acquire_mark_lock(void);
 +  GC_INNER void GC_release_mark_lock(void);
 +  GC_INNER void GC_notify_all_builder(void);
 +  GC_INNER void GC_wait_for_reclaim(void);
 +
 +  GC_EXTERN word GC_fl_builder_count;   /* Protected by mark lock.      */
 +
 +  GC_INNER void GC_notify_all_marker(void);
 +  GC_INNER void GC_wait_marker(void);
 +  GC_EXTERN word GC_mark_no;            /* Protected by mark lock.      */
 +
 +  GC_INNER void GC_help_marker(word my_mark_no);
 +              /* Try to help out parallel marker for mark cycle         */
 +              /* my_mark_no.  Returns if the mark cycle finishes or     */
 +              /* was already done, or there was nothing to do for       */
 +              /* some other reason.                                     */
 +#endif /* PARALLEL_MARK */
 +
 +#if defined(GC_PTHREADS) && !defined(GC_WIN32_THREADS) && !defined(NACL) \
 +    && !defined(SIG_SUSPEND)
 +  /* We define the thread suspension signal here, so that we can refer  */
 +  /* to it in the dirty bit implementation, if necessary.  Ideally we   */
 +  /* would allocate a (real-time?) signal using the standard mechanism. */
 +  /* unfortunately, there is no standard mechanism.  (There is one      */
 +  /* in Linux glibc, but it's not exported.)  Thus we continue to use   */
 +  /* the same hard-coded signals we've always used.                     */
 +# if defined(GC_LINUX_THREADS) || defined(GC_DGUX386_THREADS)
 +#   if defined(SPARC) && !defined(SIGPWR)
 +      /* SPARC/Linux doesn't properly define SIGPWR in <signal.h>.      */
 +      /* It is aliased to SIGLOST in asm/signal.h, though.              */
 +#     define SIG_SUSPEND SIGLOST
 +#   else
 +      /* Linuxthreads itself uses SIGUSR1 and SIGUSR2.                  */
 +#     define SIG_SUSPEND SIGPWR
  #   endif
 -#  endif /* !SIG_SUSPEND */
 -  
 -# endif
 -     
 -/* Some macros for setjmp that works across signal handlers   */
 -/* were possible, and a couple of routines to facilitate      */
 -/* catching accesses to bad addresses when that's             */
 -/* possible/needed.                                           */
 -#ifdef UNIX_LIKE
 +# elif !defined(GC_OPENBSD_THREADS) && !defined(GC_DARWIN_THREADS)
 +#   if defined(_SIGRTMIN)
 +#     define SIG_SUSPEND _SIGRTMIN + 6
 +#   else
 +#     define SIG_SUSPEND SIGRTMIN + 6
 +#   endif
 +# endif
 +#endif /* GC_PTHREADS && !SIG_SUSPEND */
 +
 +#if defined(GC_PTHREADS) && !defined(GC_SEM_INIT_PSHARED)
 +# define GC_SEM_INIT_PSHARED 0
 +#endif
 +
 +/* Some macros for setjmp that works across signal handlers     */
 +/* were possible, and a couple of routines to facilitate        */
 +/* catching accesses to bad addresses when that's               */
 +/* possible/needed.                                             */
 +#if defined(UNIX_LIKE) || (defined(NEED_FIND_LIMIT) && defined(CYGWIN32))
  # include <setjmp.h>
 -# if defined(SUNOS5SIGS) && !defined(FREEBSD)
 +# if defined(SUNOS5SIGS) && !defined(FREEBSD) && !defined(LINUX)
  #  include <sys/siginfo.h>
  # endif
 -  /* Define SETJMP and friends to be the version that restores        */
 -  /* the signal mask.                                         */
 +  /* Define SETJMP and friends to be the version that restores  */
 +  /* the signal mask.                                           */
  # define SETJMP(env) sigsetjmp(env, 1)
  # define LONGJMP(env, val) siglongjmp(env, val)
  # define JMP_BUF sigjmp_buf
  
  /* Machine specific parts contributed by various people.  See README file. */
  
 -/* SYMBIAN */
 -# if defined(__SYMBIAN32__)
 -#  ifndef SYMBIAN
 -#      define SYMBIAN
 -      #ifdef __WINS__
 -              #pragma data_seg(".data2")
 -      #endif  
 -#  endif
 +#if defined(__ANDROID__) && !defined(PLATFORM_ANDROID)
 +  /* __ANDROID__ macro is defined by Android NDK gcc.   */
 +# define PLATFORM_ANDROID 1
 +#endif
 +
++#if defined(__SYMBIAN32__) && !defined(SYMBIAN)
++# define SYMBIAN
++# ifdef __WINS__
++#   pragma data_seg(".data2")
+ # endif
 -    
++#endif
++
  /* First a unified test for Linux: */
 -# if defined(linux) || defined(__linux__)
 -#  ifndef LINUX
 -#    define LINUX
 -#  endif
 +# if (defined(linux) || defined(__linux__) || defined(PLATFORM_ANDROID)) \
 +     && !defined(LINUX) && !defined(__native_client__)
 +#   define LINUX
  # endif
  
  /* And one for NetBSD: */
  #    define FREEBSD
  # endif
  
 +/* And one for Darwin: */
 +# if defined(macosx) || (defined(__APPLE__) && defined(__MACH__))
 +#   define DARWIN
 +# endif
 +
  /* Determine the machine type: */
 -# if defined(__arm__) || defined(__thumb__)
 +# if defined(__native_client__)
 +#    define NACL
 +#    define I386
 +#    define mach_type_known
 +# endif
 +# if defined(__arm) || defined(__arm__) || defined(__thumb__)
  #    define ARM32
 -#    if !defined(LINUX) && !defined(NETBSD) && !defined(SYMBIAN)
 +#    if !defined(LINUX) && !defined(NETBSD) && !defined(OPENBSD) \
-         && !defined(DARWIN) && !defined(_WIN32) && !defined(__CEGCC__)
++        && !defined(DARWIN) && !defined(_WIN32) && !defined(__CEGCC__) \
++        && !defined(SYMBIAN)
  #      define NOSYS
  #      define mach_type_known
  #    endif
  #   define M68K
  #   define mach_type_known
  # endif
- # if defined(THINK_C) || defined(__MWERKS__) && !defined(__powerc)
 -# if defined(THINK_C) || defined(__MWERKS__) && !defined(__powerc) && !defined(SYMBIAN)
++# if defined(THINK_C) \
++     || (defined(__MWERKS__) && !defined(__powerc) && !defined(SYMBIAN))
  #   define M68K
  #   define MACOS
  #   define mach_type_known
  # endif
- # if defined(__MWERKS__) && defined(__powerc) && !defined(__MACH__)
 -# if defined(__MWERKS__) && defined(__powerc) && !defined(__MACH__) && !defined(SYMBIAN)
++# if defined(__MWERKS__) && defined(__powerc) && !defined(__MACH__) \
++     && !defined(SYMBIAN)
  #   define POWERPC
  #   define MACOS
  #   define mach_type_known
  #   define MSWINCE
  #   define mach_type_known
  # else
--#   if (defined(_MSDOS) || defined(_MSC_VER)) && (_M_IX86 >= 300) \
-         || defined(_WIN32) && !defined(__CYGWIN32__) && !defined(__CYGWIN__)
 -        || defined(_WIN32) && !defined(__CYGWIN32__) && !defined(__CYGWIN__) \
 -        && !defined(SYMBIAN)
++#   if ((defined(_MSDOS) || defined(_MSC_VER)) && (_M_IX86 >= 300)) \
++       || (defined(_WIN32) && !defined(__CYGWIN32__) && !defined(__CYGWIN__) \
++           && !defined(SYMBIAN))
  #     if defined(__LP64__) || defined(_WIN64)
 -#     define X86_64
 +#       define X86_64
  #     else
  #       define I386
  #     endif
  #   define NONSTOP
  #   define mach_type_known
  # endif
 +# if defined(__hexagon__) && defined(LINUX)
 +#    define HEXAGON
 +#    define mach_type_known
 +# endif
  
 -/* Feel free to add more clauses here */
+ # if defined(SYMBIAN)
 -#     define mach_type_known
 -# endif
 -    
 -/* Or manually define the machine type here.  A machine type is       */
 -/* characterized by the architecture.  Some                           */
 -/* machine types are further subdivided by OS.                                */
 -/* Macros such as LINUX, FREEBSD, etc. distinguish them.              */
 -/* SYSV on an M68K actually means A/UX.                                       */
++#   define mach_type_known
++# endif
++
 +/* Feel free to add more clauses here */
 +
 +/* Or manually define the machine type here.  A machine type is         */
 +/* characterized by the architecture.  Some                             */
 +/* machine types are further subdivided by OS.                          */
 +/* Macros such as LINUX, FREEBSD, etc. distinguish them.                */
 +/* SYSV on an M68K actually means A/UX.                                 */
  /* The distinction in these cases is usually the stack starting address */
  # ifndef mach_type_known
  #   error "The collector has not been ported to this machine/OS combination."
  #   define HAVE_BUILTIN_UNWIND_INIT
  # endif
  
 -#     define MACH_TYPE "SYMBIAN"
 -#     define OS_TYPE "SYMBIAN"
 -#     define CPP_WORDSZ 32
 -#     define ALIGNMENT 4
 -      #define DATASTART NULL
 -      #define DATAEND NULL
 -#   define USE_MMAP 
 -#   define NO_EXECUTE_PERMISSION
 -# endif
 -    
+ # ifdef SYMBIAN
++#   define MACH_TYPE "SYMBIAN"
++#   define OS_TYPE "SYMBIAN"
++#   define CPP_WORDSZ 32
++#   define ALIGNMENT 4
++#   define DATASTART NULL
++#   define DATAEND NULL
++# endif
++
  # define STACK_GRAN 0x1000000
  # ifdef M68K
  #   define MACH_TYPE "M68K"
index 0000000,a39b380..cba50ca
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,36 +1,32 @@@
 -#include <gc.h>
 -#include <gcconfig.h>
 -
 -#include "init_global_static_roots.h"
+ // INCLUDE FILES
+ #include <e32def.h>
 -
++#include "private/gcconfig.h"
++#include "gc.h"
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
 -      ptr_t dataStart = NULL;
 -      ptr_t dataEnd = NULL;   
 -      #if defined (__WINS__)
 -              extern int winscw_data_start, winscw_data_end;
 -              dataStart = ((ptr_t)&winscw_data_start);
 -              dataEnd   = ((ptr_t)&winscw_data_end);          
 -      #else
 -          extern int Image$$RW$$Limit[], Image$$RW$$Base[];
 -          dataStart = ((ptr_t)Image$$RW$$Base);
 -          dataEnd   = ((ptr_t)Image$$RW$$Limit);                              
 -      #endif //__WINS__       
 -      
 -      GC_add_roots(dataStart, dataEnd); 
+ void init_global_static_roots()
+ {
 -
++        ptr_t dataStart = NULL;
++        ptr_t dataEnd = NULL;
++#       if defined (__WINS__)
++                extern int winscw_data_start, winscw_data_end;
++                dataStart = ((ptr_t)&winscw_data_start);
++                dataEnd   = ((ptr_t)&winscw_data_end);
++#       else
++            extern int Image$$RW$$Limit[], Image$$RW$$Base[];
++            dataStart = ((ptr_t)Image$$RW$$Base);
++            dataEnd   = ((ptr_t)Image$$RW$$Limit);
++#       endif
++
++        GC_add_roots(dataStart, dataEnd);
+ }
 -      }
+ #ifdef __cplusplus
++        }
+ #endif
diff --cc misc.c
--- 1/misc.c
--- 2/misc.c
+++ b/misc.c
  #ifdef GC_SOLARIS_THREADS
  # include <sys/syscall.h>
  #endif
 -#if defined(MSWIN32) || defined(MSWINCE)
 -# define WIN32_LEAN_AND_MEAN
 +#if defined(MSWIN32) || defined(MSWINCE) \
 +    || (defined(CYGWIN32) && defined(GC_READ_ENV_FILE))
 +# ifndef WIN32_LEAN_AND_MEAN
 +#   define WIN32_LEAN_AND_MEAN 1
 +# endif
  # define NOSERVICE
  # include <windows.h>
 -# include <tchar.h>
  #endif
  
- #if defined(UNIX_LIKE) || defined(CYGWIN32)
 -#if defined (UNIX_LIKE) || defined(SYMBIAN)
++#if defined(UNIX_LIKE) || defined(CYGWIN32) || defined(SYMBIAN)
  # include <fcntl.h>
  # include <sys/types.h>
  # include <sys/stat.h>
  # include <floss.h>
  #endif
  
 -#if defined(THREADS) && defined(PCR)
 -# include "il/PCR_IL.h"
 -  PCR_Th_ML GC_allocate_ml;
 -#endif
 -/* For other platforms with threads, the lock and possibly            */
 -/* GC_lock_holder variables are defined in the thread support code.   */
 -
 -#if defined(NOSYS) || defined(ECOS)
 -#undef STACKBASE
 -#endif
 +#ifdef THREADS
 +# ifdef PCR
 +#   include "il/PCR_IL.h"
 +    GC_INNER PCR_Th_ML GC_allocate_ml;
 +# elif defined(SN_TARGET_PS3)
 +#   include <pthread.h>
 +    GC_INNER pthread_mutex_t GC_allocate_ml;
 +# endif
 +  /* For other platforms with threads, the lock and possibly            */
 +  /* GC_lock_holder variables are defined in the thread support code.   */
 +#endif /* THREADS */
  
 -/* Dont unnecessarily call GC_register_main_static_data() in case     */
 -/* dyn_load.c isn't linked in.                                                */
  #ifdef DYNAMIC_LOADING
 +  /* We need to register the main data segment.  Returns  TRUE unless   */
 +  /* this is done implicitly as part of dynamic library registration.   */
  # define GC_REGISTER_MAIN_STATIC_DATA() GC_register_main_static_data()
 -#else
 -#ifdef SYMBIAN
 +#elif defined(GC_DONT_REGISTER_MAIN_STATIC_DATA)
 +# define GC_REGISTER_MAIN_STATIC_DATA() FALSE
++#elif defined(SYMBIAN)
+ # define GC_REGISTER_MAIN_STATIC_DATA() FALSE
  #else
 +  /* Don't unnecessarily call GC_register_main_static_data() in case    */
 +  /* dyn_load.c isn't linked in.                                        */
  # define GC_REGISTER_MAIN_STATIC_DATA() TRUE
 -#endif //SYMBIAN
  #endif
  
 -GC_FAR struct _GC_arrays GC_arrays /* = { 0 } */;
 -
 -
 -GC_bool GC_debugging_started = FALSE;
 -      /* defined here so we don't have to load debug_malloc.o */
 +#ifdef NEED_CANCEL_DISABLE_COUNT
 +  __thread unsigned char GC_cancel_disable_count = 0;
 +#endif
  
 -void (*GC_check_heap) (void) = (void (*) (void))0;
 -void (*GC_print_all_smashed) (void) = (void (*) (void))0;
 +GC_FAR struct _GC_arrays GC_arrays /* = { 0 } */;
  
 -void (*GC_start_call_back) (void) = (void (*) (void))0;
 +GC_INNER GC_bool GC_debugging_started = FALSE;
 +        /* defined here so we don't have to load debug_malloc.o */
  
  ptr_t GC_stackbottom = 0;
  
@@@ -736,71 -504,40 +738,71 @@@ GC_API void GC_CALL GC_init(void
          if (pfn)
              pfn(&GC_allocate_ml, 4000);
          else
 -        InitializeCriticalSection (&GC_allocate_ml);
 -      }
 -#endif /* MSWIN32 */
 -#   if defined(MSWIN32) || defined(MSWINCE)
 +#     endif /* !MSWINCE */
 +        /* else */ InitializeCriticalSection (&GC_allocate_ml);
 +     }
 +#   endif /* GC_WIN32_THREADS */
 +#   if (defined(MSWIN32) || defined(MSWINCE)) && defined(THREADS)
        InitializeCriticalSection(&GC_write_cs);
  #   endif
 -#   if (!defined(SMALL_CONFIG))
 -      if (0 != GETENV("GC_PRINT_STATS")) {
 -        GC_print_stats = 1;
 -      } 
 -      if (0 != GETENV("GC_PRINT_VERBOSE_STATS")) {
 +    GC_setpagesize();
 +#   ifdef MSWIN32
 +      GC_init_win32();
 +#   endif
 +#   ifdef GC_READ_ENV_FILE
 +      GC_envfile_init();
 +#   endif
 +#   ifndef SMALL_CONFIG
 +#     ifdef GC_PRINT_VERBOSE_STATS
 +        /* This is useful for debugging and profiling on platforms with */
 +        /* missing getenv() (like WinCE).                               */
          GC_print_stats = VERBOSE;
 -      } 
 -#if defined (UNIX_LIKE) || defined(SYMBIAN)
 -        {       
 -        #if defined(SYMBIAN)
 -        char * file_name = "c:\\libgc.log";
 -        #else
 -        char * file_name = GETENV("GC_LOG_FILE");
 -        #endif
 -          if (0 != file_name) {
 -          int log_d = open(file_name, O_CREAT|O_WRONLY|O_APPEND, 0666);
 -          if (log_d < 0) {
 -            GC_log_printf("Failed to open %s as log file\n", file_name);
 -          } else {
 -            GC_log = log_d;
 -          }
 -        }
 -      }
 +#     else
 +        if (0 != GETENV("GC_PRINT_VERBOSE_STATS")) {
 +          GC_print_stats = VERBOSE;
 +        } else if (0 != GETENV("GC_PRINT_STATS")) {
 +          GC_print_stats = 1;
 +        }
  #     endif
- #     if defined(UNIX_LIKE) || defined(CYGWIN32)
 -#   endif
++#     if defined(UNIX_LIKE) || defined(CYGWIN32) || defined(SYMBIAN)
 +        {
 +          char * file_name = GETENV("GC_LOG_FILE");
 +#         ifdef GC_LOG_TO_FILE_ALWAYS
 +            if (NULL == file_name)
 +              file_name = GC_LOG_STD_NAME;
 +#         else
 +            if (0 != file_name)
 +#         endif
 +          {
 +            int log_d = open(file_name, O_CREAT|O_WRONLY|O_APPEND, 0666);
 +            if (log_d < 0) {
 +              GC_err_printf("Failed to open %s as log file\n", file_name);
 +            } else {
 +              char *str;
 +              GC_log = log_d;
 +              str = GETENV("GC_ONLY_LOG_TO_FILE");
 +#             ifdef GC_ONLY_LOG_TO_FILE
 +                /* The similar environment variable set to "0"  */
 +                /* overrides the effect of the macro defined.   */
 +                if (str != NULL && *str == '0' && *(str + 1) == '\0')
 +#             else
 +                /* Otherwise setting the environment variable   */
 +                /* to anything other than "0" will prevent from */
 +                /* redirecting stdout/err to the log file.      */
 +                if (str == NULL || (*str == '0' && *(str + 1) == '\0'))
 +#             endif
 +              {
 +                GC_stdout = log_d;
 +                GC_stderr = log_d;
 +              }
 +            }
 +          }
 +        }
 +#     endif
 +#   endif /* !SMALL_CONFIG */
  #   ifndef NO_DEBUGGING
        if (0 != GETENV("GC_DUMP_REGULARLY")) {
 -        GC_dump_regularly = 1;
 +        GC_dump_regularly = TRUE;
        }
  #   endif
  #   ifdef KEEP_BACK_PTRS
diff --cc os_dep.c
+++ b/os_dep.c
   * modified is included with the above copyright notice.
   */
  
 -# include "private/gc_priv.h"
 -# ifdef THREADS
 -#   include "atomic_ops.h"
 +#include "private/gc_priv.h"
 +
 +#if defined(LINUX) && !defined(POWERPC)
 +# include <linux/version.h>
 +# if (LINUX_VERSION_CODE <= 0x10400)
 +    /* Ugly hack to get struct sigcontext_struct definition.  Required  */
 +    /* for some early 1.3.X releases.  Will hopefully go away soon.     */
 +    /* in some later Linux releases, asm/sigcontext.h may have to       */
 +    /* be included instead.                                             */
 +#   define __KERNEL__
 +#   include <asm/signal.h>
 +#   undef __KERNEL__
 +# else
 +    /* Kernels prior to 2.1.1 defined struct sigcontext_struct instead of */
 +    /* struct sigcontext.  libc6 (glibc2) uses "struct sigcontext" in     */
 +    /* prototypes, so we have to include the top-level sigcontext.h to    */
 +    /* make sure the former gets defined to be the latter if appropriate. */
 +#   include <features.h>
 +#   if 2 <= __GLIBC__
 +#     if 2 == __GLIBC__ && 0 == __GLIBC_MINOR__
 +        /* glibc 2.1 no longer has sigcontext.h.  But signal.h          */
 +        /* has the right declaration for glibc 2.1.                     */
 +#       include <sigcontext.h>
 +#     endif /* 0 == __GLIBC_MINOR__ */
 +#   else /* not 2 <= __GLIBC__ */
 +      /* libc5 doesn't have <sigcontext.h>: go directly with the kernel   */
 +      /* one.  Check LINUX_VERSION_CODE to see which we should reference. */
 +#     include <asm/sigcontext.h>
 +#   endif /* 2 <= __GLIBC__ */
  # endif
 +#endif
  
 -# if defined(LINUX) && !defined(POWERPC)
 -#   include <linux/version.h>
 -#   if (LINUX_VERSION_CODE <= 0x10400)
 -      /* Ugly hack to get struct sigcontext_struct definition.  Required      */
 -      /* for some early 1.3.X releases.  Will hopefully go away soon. */
 -      /* in some later Linux releases, asm/sigcontext.h may have to   */
 -      /* be included instead.                                         */
 -#     define __KERNEL__
 -#     include <asm/signal.h>
 -#     undef __KERNEL__
 -#   else
 -      /* Kernels prior to 2.1.1 defined struct sigcontext_struct instead of */
 -      /* struct sigcontext.  libc6 (glibc2) uses "struct sigcontext" in     */
 -      /* prototypes, so we have to include the top-level sigcontext.h to    */
 -      /* make sure the former gets defined to be the latter if appropriate. */
 -#     include <features.h>
 -#     if 2 <= __GLIBC__
 -#       if 2 == __GLIBC__ && 0 == __GLIBC_MINOR__
 -        /* glibc 2.1 no longer has sigcontext.h.  But signal.h        */
 -        /* has the right declaration for glibc 2.1.                   */
 -#         include <sigcontext.h>
 -#       endif /* 0 == __GLIBC_MINOR__ */
 -#     else /* not 2 <= __GLIBC__ */
 -        /* libc5 doesn't have <sigcontext.h>: go directly with the kernel   */
 -        /* one.  Check LINUX_VERSION_CODE to see which we should reference. */
 -#       include <asm/sigcontext.h>
 -#     endif /* 2 <= __GLIBC__ */
 -#   endif
 -# endif
 -# if !defined(OS2) && !defined(PCR) && !defined(AMIGA) && !defined(MACOS) \
 -    && !defined(MSWINCE)
 -#   include <sys/types.h>
 -#     include <fcntl.h> 
 -#   if !defined(MSWIN32)
 -#     include <unistd.h>
 -#   endif
 +#if !defined(OS2) && !defined(PCR) && !defined(AMIGA) && !defined(MACOS) \
 +    && !defined(MSWINCE) && !defined(__CC_ARM)
 +# include <sys/types.h>
 +# if !defined(MSWIN32)
 +#   include <unistd.h>
  # endif
 +#endif
  
 -# include <stdio.h>
 -# if defined(MSWINCE)
 -#   define SIGSEGV 0 /* value is irrelevant */
 -# else
 -#   include <signal.h>
 -# endif
 +#include <stdio.h>
 +#if defined(MSWINCE) || defined(SN_TARGET_PS3)
 +# define SIGSEGV 0 /* value is irrelevant */
 +#else
 +# include <signal.h>
 +#endif
  
- #if defined(UNIX_LIKE) || defined(CYGWIN32) || defined(NACL)
 -#ifdef UNIX_LIKE
++#if defined(UNIX_LIKE) || defined(CYGWIN32) || defined(NACL) \
++    || defined(SYMBIAN)
  # include <fcntl.h>
  #endif
  
@@@ -1136,124 -1097,103 +1137,131 @@@ GC_INNER word GC_page_size = 0
      ptr_t base;
      size_t len = sizeof(ptr_t);
      int r = sysctl(nm, 2, &base, &len, NULL, 0);
 -    
 -    if (r) ABORT("Error getting stack base");
 -
 +    if (r) ABORT("Error getting main stack base");
      return base;
    }
 -
  #endif /* FREEBSD_STACKBOTTOM */
  
 -#ifdef SYMBIAN
 -ptr_t GC_get_main_stack_base(void)
 -{
 -      return (ptr_t)GC_get_main_symbian_stack_base();
 -}
 -#endif
 -
 -#if !defined(BEOS) && !defined(AMIGA) && !defined(MSWIN32) \
 -    && !defined(MSWINCE) && !defined(OS2) && !defined(NOSYS) && !defined(ECOS) \
 -    && !defined(CYGWIN32) && !defined(SYMBIAN)
 +#if defined(ECOS) || defined(NOSYS)
 +  ptr_t GC_get_main_stack_base(void)
 +  {
 +    return STACKBOTTOM;
 +  }
 +# define GET_MAIN_STACKBASE_SPECIAL
++#elif defined(SYMBIAN)
++  extern int GC_get_main_symbian_stack_base(void);
++  ptr_t GC_get_main_stack_base(void)
++  {
++    return (ptr_t)GC_get_main_symbian_stack_base();
++  }
++# define GET_MAIN_STACKBASE_SPECIAL
 +#elif !defined(BEOS) && !defined(AMIGA) && !defined(OS2) \
 +      && !defined(MSWIN32) && !defined(MSWINCE) && !defined(CYGWIN32) \
 +      && !defined(GC_OPENBSD_THREADS) \
 +      && (!defined(GC_SOLARIS_THREADS) || defined(_STRICT_STDC))
 +
 +# if defined(LINUX) && defined(USE_GET_STACKBASE_FOR_MAIN)
 +#   include <pthread.h>
 +# elif defined(DARWIN) && !defined(NO_PTHREAD_GET_STACKADDR_NP)
 +    /* We could use pthread_get_stackaddr_np even in case of a  */
 +    /* single-threaded gclib (there is no -lpthread on Darwin). */
 +#   include <pthread.h>
 +#   undef STACKBOTTOM
 +#   define STACKBOTTOM (ptr_t)pthread_get_stackaddr_np(pthread_self())
 +# endif
  
 -ptr_t GC_get_main_stack_base(void)
 -{
 -#   if defined(HEURISTIC1) || defined(HEURISTIC2)
 -      word dummy;
 +  ptr_t GC_get_main_stack_base(void)
 +  {
 +    ptr_t result; /* also used as "dummy" to get the approx. sp value */
 +#   if defined(LINUX) && !defined(NACL) \
 +       && (defined(USE_GET_STACKBASE_FOR_MAIN) \
 +           || (defined(THREADS) && !defined(REDIRECT_MALLOC)))
 +      pthread_attr_t attr;
 +      void *stackaddr;
 +      size_t size;
 +      if (pthread_getattr_np(pthread_self(), &attr) == 0) {
 +        if (pthread_attr_getstack(&attr, &stackaddr, &size) == 0
 +            && stackaddr != NULL) {
 +          pthread_attr_destroy(&attr);
 +#         ifdef STACK_GROWS_DOWN
 +            stackaddr = (char *)stackaddr + size;
 +#         endif
 +          return (ptr_t)stackaddr;
 +        }
 +        pthread_attr_destroy(&attr);
 +      }
 +      WARN("pthread_getattr_np or pthread_attr_getstack failed"
 +           " for main thread\n", 0);
  #   endif
 -    ptr_t result;
 -
 -#   define STACKBOTTOM_ALIGNMENT_M1 ((word)STACK_GRAN - 1)
 -
  #   ifdef STACKBOTTOM
 -      return(STACKBOTTOM);
 +      result = STACKBOTTOM;
  #   else
 -#     ifdef HEURISTIC1
 -#        ifdef STACK_GROWS_DOWN
 -           result = (ptr_t)((((word)(&dummy))
 -                             + STACKBOTTOM_ALIGNMENT_M1)
 -                            & ~STACKBOTTOM_ALIGNMENT_M1);
 -#        else
 -           result = (ptr_t)(((word)(&dummy))
 -                            & ~STACKBOTTOM_ALIGNMENT_M1);
 -#        endif
 -#     endif /* HEURISTIC1 */
 -#     ifdef LINUX_STACKBOTTOM
 -         result = GC_linux_stack_base();
 -#     endif
 -#     ifdef FREEBSD_STACKBOTTOM
 -         result = GC_freebsd_stack_base();
 -#     endif
 -#     ifdef HEURISTIC2
 -#         ifdef STACK_GROWS_DOWN
 -              result = GC_find_limit((ptr_t)(&dummy), TRUE);
 -#             ifdef HEURISTIC2_LIMIT
 -                  if (result > HEURISTIC2_LIMIT
 -                      && (ptr_t)(&dummy) < HEURISTIC2_LIMIT) {
 -                          result = HEURISTIC2_LIMIT;
 -                  }
 -#             endif
 -#         else
 -              result = GC_find_limit((ptr_t)(&dummy), FALSE);
 -#             ifdef HEURISTIC2_LIMIT
 -                  if (result < HEURISTIC2_LIMIT
 -                      && (ptr_t)(&dummy) > HEURISTIC2_LIMIT) {
 -                          result = HEURISTIC2_LIMIT;
 -                  }
 -#             endif
 -#         endif
 -
 -#     endif /* HEURISTIC2 */
 -#     ifdef STACK_GROWS_DOWN
 -          if (result == 0) result = (ptr_t)(signed_word)(-sizeof(ptr_t));
 -#     endif
 -      return(result);
 -#   endif /* STACKBOTTOM */
 -}
 -
 -# endif /* ! AMIGA, !OS 2, ! MS Windows, !BEOS, !NOSYS, !ECOS */
 -
 -#if defined(GC_LINUX_THREADS) && !defined(HAVE_GET_STACK_BASE)
 +#     define STACKBOTTOM_ALIGNMENT_M1 ((word)STACK_GRAN - 1)
 +#     ifdef HEURISTIC1
 +#       ifdef STACK_GROWS_DOWN
 +          result = (ptr_t)((((word)(&result)) + STACKBOTTOM_ALIGNMENT_M1)
 +                           & ~STACKBOTTOM_ALIGNMENT_M1);
 +#       else
 +          result = (ptr_t)(((word)(&result)) & ~STACKBOTTOM_ALIGNMENT_M1);
 +#       endif
 +#     endif /* HEURISTIC1 */
 +#     ifdef LINUX_STACKBOTTOM
 +         result = GC_linux_main_stack_base();
 +#     endif
 +#     ifdef FREEBSD_STACKBOTTOM
 +         result = GC_freebsd_main_stack_base();
 +#     endif
 +#     ifdef HEURISTIC2
 +#       ifdef STACK_GROWS_DOWN
 +          result = GC_find_limit((ptr_t)(&result), TRUE);
 +#         ifdef HEURISTIC2_LIMIT
 +            if ((word)result > (word)HEURISTIC2_LIMIT
 +                && (word)(&result) < (word)HEURISTIC2_LIMIT) {
 +              result = HEURISTIC2_LIMIT;
 +            }
 +#         endif
 +#       else
 +          result = GC_find_limit((ptr_t)(&result), FALSE);
 +#         ifdef HEURISTIC2_LIMIT
 +            if ((word)result < (word)HEURISTIC2_LIMIT
 +                && (word)(&result) > (word)HEURISTIC2_LIMIT) {
 +              result = HEURISTIC2_LIMIT;
 +            }
 +#         endif
 +#       endif
 +#     endif /* HEURISTIC2 */
 +#     ifdef STACK_GROWS_DOWN
 +        if (result == 0)
 +          result = (ptr_t)(signed_word)(-sizeof(ptr_t));
 +#     endif
 +#   endif
 +    GC_ASSERT((word)(&result) HOTTER_THAN (word)result);
 +    return(result);
 +  }
 +# define GET_MAIN_STACKBASE_SPECIAL
 +#endif /* !AMIGA, !BEOS, !OPENBSD, !OS2, !Windows */
  
 -#include <pthread.h>
 +#if (defined(GC_LINUX_THREADS) || defined(PLATFORM_ANDROID)) && !defined(NACL)
  
 -#ifdef IA64
 -  ptr_t GC_greatest_stack_base_below(ptr_t bound);
 -      /* From pthread_support.c */
 -#endif
 +# include <pthread.h>
 +  /* extern int pthread_getattr_np(pthread_t, pthread_attr_t *); */
  
 -int GC_get_stack_base(struct GC_stack_base *b)
 -{
 +  GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *b)
 +  {
      pthread_attr_t attr;
      size_t size;
 +#   ifdef IA64
 +      DCL_LOCK_STATE;
 +#   endif
  
      if (pthread_getattr_np(pthread_self(), &attr) != 0) {
 -      WARN("pthread_getattr_np failed\n", 0);
 -      return GC_UNIMPLEMENTED;
 +        WARN("pthread_getattr_np failed\n", 0);
 +        return GC_UNIMPLEMENTED;
      }
      if (pthread_attr_getstack(&attr, &(b -> mem_base), &size) != 0) {
 -      ABORT("pthread_attr_getstack failed");
 +        ABORT("pthread_attr_getstack failed");
      }
 +    pthread_attr_destroy(&attr);
  #   ifdef STACK_GROWS_DOWN
          b -> mem_base = (char *)(b -> mem_base) + size;
  #   endif
@@@ -2049,13 -1762,17 +2057,17 @@@ void GC_register_data_segments(void
  #else
    static int zero_fd;
  # define OPT_MAP_ANON 0
 -#endif 
 +#endif
  
  #ifndef HEAP_START
 -#   define HEAP_START 0
 +#   define HEAP_START ((ptr_t)0)
  #endif
  
 -extern char* GC_get_private_path_and_zero_file();
+ #ifdef SYMBIAN
 -ptr_t GC_unix_mmap_get_mem(word bytes)
++  extern char* GC_get_private_path_and_zero_file(void);
+ #endif
 +STATIC ptr_t GC_unix_mmap_get_mem(word bytes)
  {
      void *result;
      static ptr_t last_addr = HEAP_START;
  #   ifndef USE_MMAP_ANON
        static GC_bool initialized = FALSE;
  
 -      if (!initialized) {       
 -        #ifdef SYMBIAN
 -              char* path = GC_get_private_path_and_zero_file();
 -              zero_fd = open(path, O_RDWR | O_CREAT, 0666);
 -              free( path );
 -        #else
 -              zero_fd = open("/dev/zero", O_RDONLY);
 -        #endif          
 -        fcntl(zero_fd, F_SETFD, FD_CLOEXEC);
 -        initialized = TRUE;
 +      if (!EXPECT(initialized, TRUE)) {
++#       ifdef SYMBIAN
++          char* path = GC_get_private_path_and_zero_file();
++          zero_fd = open(path, O_RDWR | O_CREAT, 0666);
++          free(path);
++#       else
 +          zero_fd = open("/dev/zero", O_RDONLY);
++#       endif
 +          fcntl(zero_fd, F_SETFD, FD_CLOEXEC);
 +          initialized = TRUE;
        }
  #   endif