--- /dev/null
-/*\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
--- /dev/null
-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
--- /dev/null
-#include "gcconfig.h"
+
+ // INCLUDE FILES
- }
++#include "private/gcconfig.h"
+
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
+ int winscw_data_end;
+
+ #ifdef __cplusplus
-
++ }
+ #endif
+
+ // End Of File
--- /dev/null
-#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
--- /dev/null
-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
#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"
--- /dev/null
-#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
#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;
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
* 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
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
#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