/* -----------------------------------------------------------------------------
- * $Id: Storage.h,v 1.39 2002/02/01 10:50:35 simonmar Exp $
+ * $Id: Storage.h,v 1.45 2002/10/21 11:38:54 simonmar Exp $
*
* (c) The GHC Team, 1998-1999
*
/*
* Storage manager mutex
*/
-#ifdef SMP
-extern pthread_mutex_t sm_mutex;
+#if defined(SMP)
+extern Mutex sm_mutex;
+#define ACQUIRE_SM_LOCK ACQUIRE_LOCK(&sm_mutex)
+#define RELEASE_SM_LOCK RELEASE_LOCK(&sm_mutex)
+#else
+#define ACQUIRE_SM_LOCK
+#define RELEASE_SM_LOCK
#endif
/* ToDo: shouldn't recordMutable and recordOldToNewPtrs acquire some
} else { \
((StgIndOldGen *)p1)->indirectee = p2; \
if (info != &stg_BLACKHOLE_BQ_info) { \
- ACQUIRE_LOCK(&sm_mutex); \
+ ACQUIRE_SM_LOCK; \
((StgIndOldGen *)p1)->mut_link = generations[bd->gen_no].mut_once_list; \
generations[bd->gen_no].mut_once_list = (StgMutClosure *)p1; \
- RELEASE_LOCK(&sm_mutex); \
+ RELEASE_SM_LOCK; \
} \
SET_INFO(p1,&stg_IND_OLDGEN_info); \
TICK_UPD_OLD_IND(); \
} else { \
((StgIndOldGen *)p1)->indirectee = p2; \
if (info != &stg_BLACKHOLE_BQ_info) { \
- ACQUIRE_LOCK(&sm_mutex); \
+ ACQUIRE_SM_LOCK; \
((StgIndOldGen *)p1)->mut_link = generations[bd->gen_no].mut_once_list; \
generations[bd->gen_no].mut_once_list = (StgMutClosure *)p1; \
- RELEASE_LOCK(&sm_mutex); \
+ RELEASE_SM_LOCK; \
} \
SET_INFO(p1,&stg_IND_OLDGEN_info); \
LDV_recordCreate((p1)); \
} \
} \
} \
- ACQUIRE_LOCK(&sm_mutex); \
+ ACQUIRE_SM_LOCK; \
((StgIndOldGen *)p1)->mut_link = generations[bd->gen_no].mut_once_list; \
generations[bd->gen_no].mut_once_list = (StgMutClosure *)p1; \
- RELEASE_LOCK(&sm_mutex); \
+ RELEASE_SM_LOCK; \
} \
((StgIndOldGen *)p1)->indirectee = p2; \
SET_INFO(p1,&stg_IND_OLDGEN_info); \
ASSERT( p1 != p2 && !closure_IND(p1) ); \
ASSERT( ((StgMutClosure*)p1)->mut_link == NULL ); \
\
- ACQUIRE_LOCK(&sm_mutex); \
+ ACQUIRE_SM_LOCK; \
((StgMutClosure *)p1)->mut_link = oldest_gen->mut_once_list; \
oldest_gen->mut_once_list = (StgMutClosure *)p1; \
- RELEASE_LOCK(&sm_mutex); \
+ RELEASE_SM_LOCK; \
\
((StgInd *)p1)->indirectee = p2; \
SET_INFO((StgInd *)p1, &stg_IND_STATIC_info); \
} else {
((StgIndOldGen *)p1)->indirectee = p2;
if (info != &stg_BLACKHOLE_BQ_info) {
- ACQUIRE_LOCK(&sm_mutex);
+ ACQUIRE_SM_LOCK;
((StgIndOldGen *)p1)->mut_link = generations[bd->gen_no].mut_once_list;
generations[bd->gen_no].mut_once_list = (StgMutClosure *)p1;
- RELEASE_LOCK(&sm_mutex);
+ RELEASE_SM_LOCK;
}
SET_INFO(p1,&stg_IND_OLDGEN_PERM_info);
#ifdef PROFILING
#undef TEXT_BEFORE_HEAP
-#ifndef mingw32_TARGET_OS
+#if !defined(mingw32_TARGET_OS) && !defined(cygwin32_TARGET_OS)
#define TEXT_BEFORE_HEAP 1
#endif
extern void* TEXT_SECTION_END_MARKER_DECL;
extern void* DATA_SECTION_END_MARKER_DECL;
+#ifdef darwin_TARGET_OS
+extern unsigned long macho_etext;
+extern unsigned long macho_edata;
+#define IS_CODE_PTR(p) ( ((P_)(p) < (P_)macho_etext) \
+ || is_dynamically_loaded_code_or_rodata_ptr((char *)p) )
+#define IS_DATA_PTR(p) ( ((P_)(p) >= (P_)macho_etext && \
+ (P_)(p) < (P_)macho_edata) \
+ || is_dynamically_loaded_rwdata_ptr((char *)p) )
+#define IS_USER_PTR(p) ( ((P_)(p) >= (P_)macho_edata) \
+ && is_not_dynamically_loaded_ptr((char *)p) )
+#else
/* Take into account code sections in dynamically loaded object files. */
#define IS_DATA_PTR(p) ( ((P_)(p) >= (P_)&TEXT_SECTION_END_MARKER && \
(P_)(p) < (P_)&DATA_SECTION_END_MARKER) \
|| is_dynamically_loaded_rwdata_ptr((char *)p) )
#define IS_USER_PTR(p) ( ((P_)(p) >= (P_)&DATA_SECTION_END_MARKER) \
&& is_not_dynamically_loaded_ptr((char *)p) )
-
-/* The HEAP_ALLOCED test below is called FOR EVERY SINGLE CLOSURE
- * during GC. It needs to be FAST.
- *
- * BEWARE: when we're dynamically loading code (for GHCi), make sure
- * that we don't load any code above HEAP_BASE, or this test won't work.
- */
-#ifdef TEXT_BEFORE_HEAP
-# define HEAP_ALLOCED(x) ((StgPtr)(x) >= (StgPtr)(HEAP_BASE))
-#else
-extern int is_heap_alloced(const void* x);
-# define HEAP_ALLOCED(x) (is_heap_alloced(x))
#endif
-
/* --------------------------------------------------------------------------
Macros for distinguishing data pointers from code pointers
--------------------------------------------------------------------------
(MAX_INTLIKE-MIN_INTLIKE) * sizeof(StgIntCharlikeClosure)) )
#define LOOKS_LIKE_STATIC_CLOSURE(r) (((*(((unsigned long *)(r))-1)) == 0) || IS_CHARLIKE_CLOSURE(r) || IS_INTLIKE_CLOSURE(r))
+
+#elif defined(darwin_TARGET_OS) && !defined(TABLES_NEXT_TO_CODE)
+
+#define LOOKS_LIKE_STATIC(r) (!(HEAP_ALLOCED(r)))
+#define LOOKS_LIKE_STATIC_CLOSURE(r) (IS_DATA_PTR(r) && !LOOKS_LIKE_GHC_INFO(r))
+
#else
+
#define LOOKS_LIKE_STATIC(r) IS_DATA_PTR(r)
#define LOOKS_LIKE_STATIC_CLOSURE(r) IS_DATA_PTR(r)
+
#endif
/* LOOKS_LIKE_GHC_INFO is called moderately often during GC, but
* Certainly not as often as HEAP_ALLOCED.
*/
+#if defined(darwin_TARGET_OS) && !defined(TABLES_NEXT_TO_CODE)
+ /* Plan C, see above */
+#define LOOKS_LIKE_GHC_INFO(info) IS_CODE_PTR(((StgInfoTable *)info).entry)
+#else
#define LOOKS_LIKE_GHC_INFO(info) (!HEAP_ALLOCED(info) \
&& !LOOKS_LIKE_STATIC_CLOSURE(info))
+#endif
/* -----------------------------------------------------------------------------
Macros for calculating how big a closure will be (used during allocation)