From: Ivan Maidanski Date: Sun, 18 Mar 2012 12:04:58 +0000 (+0400) Subject: Merge with symbian_libgc_7x branch X-Git-Tag: gc7_3alpha2~50^2~3 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ea176a3ab6d5af6e14e7e035f9e75f2668b453c9;p=gc Merge with symbian_libgc_7x branch --- ea176a3ab6d5af6e14e7e035f9e75f2668b453c9 diff --cc build/s60v3/bld.inf index 00000000,4c3855ea..491fcf43 mode 000000,100644..100644 --- a/build/s60v3/bld.inf +++ b/build/s60v3/bld.inf @@@ -1,0 -1,15 +1,11 @@@ -/* -============================================================================ - Name : bld.inf - Author : - Copyright : - Description : This file provides the information required for building the - whole of a libgc. -============================================================================ -*/ - -PRJ_PLATFORMS -default armv5 - -PRJ_MMPFILES -libgc.mmp ++/* ++ 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 diff --cc build/s60v3/libgc.mmp index 00000000,bbee121f..f707ab29 mode 000000,100644..100644 --- a/build/s60v3/libgc.mmp +++ b/build/s60v3/libgc.mmp @@@ -1,0 -1,70 +1,72 @@@ -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 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 ++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 00000000,f47e19a2..2980747e mode 000000,100644..100644 --- a/global_end.cpp +++ b/global_end.cpp @@@ -1,0 -1,16 +1,15 @@@ + + // INCLUDE FILES -#include "gcconfig.h" ++#include "private/gcconfig.h" + + #ifdef __cplusplus + extern "C" { + #endif + + int winscw_data_end; + + #ifdef __cplusplus - } ++ } + #endif + + // End Of File - diff --cc global_start.cpp index 00000000,8d0ca20e..1406a508 mode 000000,100644..100644 --- a/global_start.cpp +++ b/global_start.cpp @@@ -1,0 -1,16 +1,15 @@@ + + // INCLUDE FILES -#include "gcconfig.h" ++#include "private/gcconfig.h" + + #ifdef __cplusplus + extern "C" { + #endif + + int winscw_data_start; + + #ifdef __cplusplus - } ++ } + #endif + + // End Of File - diff --cc include/gc_config_macros.h index d4b72313,7328d66f..728216a4 --- a/include/gc_config_macros.h +++ b/include/gc_config_macros.h @@@ -123,113 -120,40 +123,120 @@@ # 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 +# if defined(__MINGW32__) && !defined(_WIN32_WCE) +# include + /* 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 /* 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 -# if defined(__MINGW32__) -# include - /* 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 /* 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 diff --cc include/init_global_static_roots.h index 00000000,cfc4b0d5..32fdce5c mode 000000,100644..100644 --- a/include/init_global_static_roots.h +++ b/include/init_global_static_roots.h @@@ -1,0 -1,13 +1,15 @@@ ++ + #ifndef __INIT_GLOBAL_STATIC_ROOTS_H_ + #define __INIT_GLOBAL_STATIC_ROOTS_H_ + + #ifdef __cplusplus -extern "C" { ++ extern "C" { + #endif -void init_global_static_roots(); ++ ++void init_global_static_roots(void); + + #ifdef __cplusplus - } ++ } + #endif + -#endif // __INIT_GLOBAL_STATIC_ROOTS_H_ ++#endif diff --cc include/private/gc_priv.h index ebceb32d,7eea1c1a..7749f0ac --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@@ -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 . - * 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 . */ + /* 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 -# if defined(SUNOS5SIGS) && !defined(FREEBSD) +# if defined(SUNOS5SIGS) && !defined(FREEBSD) && !defined(LINUX) # include # 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 diff --cc include/private/gcconfig.h index 5b5929ae,03c6f53f..d128b834 --- a/include/private/gcconfig.h +++ b/include/private/gcconfig.h @@@ -37,15 -38,21 +37,22 @@@ /* 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: */ @@@ -64,21 -71,10 +71,22 @@@ # 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 @@@ -309,12 -290,12 +317,14 @@@ # 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 @@@ -414,10 -382,11 +424,11 @@@ # 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 @@@ -502,18 -471,17 +513,22 @@@ # 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." @@@ -689,6 -657,17 +704,15 @@@ # define HAVE_BUILTIN_UNWIND_INIT # endif + # ifdef SYMBIAN -# 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 - ++# 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" diff --cc init_global_static_roots.cpp index 00000000,a39b3807..cba50cad mode 000000,100644..100644 --- a/init_global_static_roots.cpp +++ b/init_global_static_roots.cpp @@@ -1,0 -1,36 +1,32 @@@ + + // INCLUDE FILES + #include + -#include -#include - -#include "init_global_static_roots.h" ++#include "private/gcconfig.h" ++#include "gc.h" + + #ifdef __cplusplus + extern "C" { + #endif + - + 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 //__WINS__ - - GC_add_roots(dataStart, dataEnd); ++ 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 index 841689e3,22fc0f5d..8d9bce3e --- a/misc.c +++ b/misc.c @@@ -26,16 -28,14 +26,16 @@@ #ifdef GC_SOLARIS_THREADS # include #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 -# include #endif - #if defined(UNIX_LIKE) || defined(CYGWIN32) -#if defined (UNIX_LIKE) || defined(SYMBIAN) ++#if defined(UNIX_LIKE) || defined(CYGWIN32) || defined(SYMBIAN) # include # include # include @@@ -45,38 -47,39 +45,40 @@@ # include #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 + 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 index c06728d6,96737a01..04154edb --- a/os_dep.c +++ b/os_dep.c @@@ -14,54 -14,57 +14,55 @@@ * 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 +# 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 +# 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 +# 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 +# endif /* 0 == __GLIBC_MINOR__ */ +# else /* not 2 <= __GLIBC__ */ + /* libc5 doesn't have : go directly with the kernel */ + /* one. Check LINUX_VERSION_CODE to see which we should reference. */ +# include +# endif /* 2 <= __GLIBC__ */ # endif +#endif -# if defined(LINUX) && !defined(POWERPC) -# include -# 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 -# 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 -# 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 -# endif /* 0 == __GLIBC_MINOR__ */ -# else /* not 2 <= __GLIBC__ */ - /* libc5 doesn't have : go directly with the kernel */ - /* one. Check LINUX_VERSION_CODE to see which we should reference. */ -# include -# endif /* 2 <= __GLIBC__ */ -# endif -# endif -# if !defined(OS2) && !defined(PCR) && !defined(AMIGA) && !defined(MACOS) \ - && !defined(MSWINCE) -# include -# include -# if !defined(MSWIN32) -# include -# endif +#if !defined(OS2) && !defined(PCR) && !defined(AMIGA) && !defined(MACOS) \ + && !defined(MSWINCE) && !defined(__CC_ARM) +# include +# if !defined(MSWIN32) +# include # endif +#endif -# include -# if defined(MSWINCE) -# define SIGSEGV 0 /* value is irrelevant */ -# else -# include -# endif +#include +#if defined(MSWINCE) || defined(SN_TARGET_PS3) +# define SIGSEGV 0 /* value is irrelevant */ +#else +# include +#endif - #if defined(UNIX_LIKE) || defined(CYGWIN32) || defined(NACL) -#ifdef UNIX_LIKE ++#if defined(UNIX_LIKE) || defined(CYGWIN32) || defined(NACL) \ ++ || defined(SYMBIAN) # include #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 +# 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 +# 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 +#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 + /* 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 + #ifdef SYMBIAN -extern char* GC_get_private_path_and_zero_file(); ++ extern char* GC_get_private_path_and_zero_file(void); + #endif + -ptr_t GC_unix_mmap_get_mem(word bytes) +STATIC ptr_t GC_unix_mmap_get_mem(word bytes) { void *result; static ptr_t last_addr = HEAP_START; @@@ -2063,10 -1780,16 +2075,16 @@@ # 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