* Used for locking closures during updates (see lockClosure() below)
* and the MVar primops.
*/
-INLINE_HEADER StgWord xchg(StgPtr p, StgWord w);
+EXTERN_INLINE StgWord xchg(StgPtr p, StgWord w);
/*
* Compare-and-swap. Atomically does this:
* return r;
* }
*/
-INLINE_HEADER StgWord cas(StgVolatilePtr p, StgWord o, StgWord n);
+EXTERN_INLINE StgWord cas(StgVolatilePtr p, StgWord o, StgWord n);
/*
* Prevents write operations from moving across this call in either
* direction.
*/
-INLINE_HEADER void write_barrier(void);
+EXTERN_INLINE void write_barrier(void);
/* ----------------------------------------------------------------------------
Implementations
* NB: the xchg instruction is implicitly locked, so we do not need
* a lock prefix here.
*/
-INLINE_HEADER StgWord
+EXTERN_INLINE StgWord
xchg(StgPtr p, StgWord w)
{
StgWord result;
* CMPXCHG - the single-word atomic compare-and-exchange instruction. Used
* in the STM implementation.
*/
-INLINE_HEADER StgWord
+EXTERN_INLINE StgWord
cas(StgVolatilePtr p, StgWord o, StgWord n)
{
#if i386_HOST_ARCH || x86_64_HOST_ARCH
* control in C, and optionally a memory barrier instruction on CPUs
* that require it (not x86 or x86_64).
*/
-INLINE_HEADER void
+EXTERN_INLINE void
write_barrier(void) {
#if i386_HOST_ARCH || x86_64_HOST_ARCH
__asm__ __volatile__ ("" : : : "memory");
#ifndef SMPCLOSUREOPS_H
#define SMPCLOSUREOPS_H
+EXTERN_INLINE StgInfoTable *lockClosure(StgClosure *p);
+EXTERN_INLINE void unlockClosure(StgClosure *p, const StgInfoTable *info);
+
#if defined(THREADED_RTS)
/* -----------------------------------------------------------------------------
#define SPIN_COUNT 4000
-#ifdef KEEP_LOCKCLOSURE
// We want a callable copy of lockClosure() so that we can refer to it
// from .cmm files compiled using the native codegen.
-extern StgInfoTable *lockClosure(StgClosure *p);
-INLINE_ME
-#else
-INLINE_HEADER
-#endif
-StgInfoTable *
-lockClosure(StgClosure *p)
+EXTERN_INLINE StgInfoTable *lockClosure(StgClosure *p)
{
StgWord info;
do {
} while (1);
}
-INLINE_HEADER void
-unlockClosure(StgClosure *p, const StgInfoTable *info)
+EXTERN_INLINE void unlockClosure(StgClosure *p, const StgInfoTable *info)
{
// This is a strictly ordered write, so we need a write_barrier():
write_barrier();
#else /* !THREADED_RTS */
-INLINE_HEADER StgInfoTable *
+EXTERN_INLINE StgInfoTable *
lockClosure(StgClosure *p)
{ return (StgInfoTable *)p->header.info; }
-INLINE_HEADER void
+EXTERN_INLINE void
unlockClosure(StgClosure *p STG_UNUSED, const StgInfoTable *info STG_UNUSED)
{ /* nothing */ }
#endif /* THREADED_RTS */
// Handy specialised versions of lockClosure()/unlockClosure()
-INLINE_HEADER void lockTSO(StgTSO *tso)
+EXTERN_INLINE void lockTSO(StgTSO *tso);
+EXTERN_INLINE void lockTSO(StgTSO *tso)
{ lockClosure((StgClosure *)tso); }
-INLINE_HEADER void unlockTSO(StgTSO *tso)
+EXTERN_INLINE void unlockTSO(StgTSO *tso);
+EXTERN_INLINE void unlockTSO(StgTSO *tso)
{ unlockClosure((StgClosure*)tso, (const StgInfoTable *)&stg_TSO_info); }
#endif /* SMPCLOSUREOPS_H */
/*
* 'Portable' inlining:
- * INLINE_HEADER is for inline functions in header files
+ * INLINE_HEADER is for inline functions in header files (macros)
* STATIC_INLINE is for inline functions in source files
+ * EXTERN_INLINE is for functions that we want to inline sometimes
*/
#if defined(__GNUC__) || defined( __INTEL_COMPILER)
+
# define INLINE_HEADER static inline
# define INLINE_ME inline
# define STATIC_INLINE INLINE_HEADER
+
+# if defined(KEEP_INLINES)
+# define EXTERN_INLINE inline
+# else
+# define EXTERN_INLINE extern inline
+# endif
+
#elif defined(_MSC_VER)
+
# define INLINE_HEADER __inline static
# define INLINE_ME __inline
# define STATIC_INLINE INLINE_HEADER
+
+# if defined(KEEP_INLINES)
+# define EXTERN_INLINE __inline
+# else
+# define EXTERN_INLINE __inline extern
+# endif
+
#else
+
# error "Don't know how to inline functions with your C compiler."
+
#endif
+
/*
* GCC attributes
*/
#define GNUC3_ATTRIBUTE(at)
#endif
+#if __GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 3
+#define GNUC_ATTR_HOT __attribute__((hot))
+#else
+#define GNUC_ATTR_HOT /* nothing */
+#endif
+
#define STG_UNUSED GNUC3_ATTRIBUTE(__unused__)
/* -----------------------------------------------------------------------------
--- /dev/null
+// all functions declared with EXTERN_INLINE in the header files get
+// compiled for real here, just in case the definition was not inlined
+// at some call site:
+#define KEEP_INLINES
+#include "Rts.h"
* the band to which this closure's heap space is attributed in the
* heap profile.
* ------------------------------------------------------------------------- */
-STATIC_INLINE void *
+static void *
closureIdentity( StgClosure *p )
{
switch (RtsFlags.ProfFlags.doHeapProfile) {
The evacuate() code
-------------------------------------------------------------------------- */
-STATIC_INLINE void
+STATIC_INLINE GNUC_ATTR_HOT void
copy_tag(StgClosure **p, const StgInfoTable *info,
StgClosure *src, nat size, step *stp, StgWord tag)
{
/* Copy wrappers that don't tag the closure after copying */
-STATIC_INLINE void
+STATIC_INLINE GNUC_ATTR_HOT void
copy(StgClosure **p, const StgInfoTable *info,
StgClosure *src, nat size, step *stp)
{
extra reads/writes than we save.
------------------------------------------------------------------------- */
-REGPARM1 void
+REGPARM1 GNUC_ATTR_HOT void
evacuate(StgClosure **p)
{
bdescr *bd = NULL;
return p;
}
-STATIC_INLINE StgPtr
+STATIC_INLINE GNUC_ATTR_HOT StgPtr
scavenge_PAP_payload (StgClosure *fun, StgClosure **payload, StgWord size)
{
StgPtr p;
return p;
}
-STATIC_INLINE StgPtr
+STATIC_INLINE GNUC_ATTR_HOT StgPtr
scavenge_PAP (StgPAP *pap)
{
evacuate(&pap->fun);
* srt field in the info table. That's ok, because we'll
* never dereference it.
*/
-STATIC_INLINE void
+STATIC_INLINE GNUC_ATTR_HOT void
scavenge_srt (StgClosure **srt, nat srt_bitmap)
{
nat bitmap;
}
-STATIC_INLINE void
+STATIC_INLINE GNUC_ATTR_HOT void
scavenge_thunk_srt(const StgInfoTable *info)
{
StgThunkInfoTable *thunk_info;
scavenge_srt((StgClosure **)GET_SRT(thunk_info), thunk_info->i.srt_bitmap);
}
-STATIC_INLINE void
+STATIC_INLINE GNUC_ATTR_HOT void
scavenge_fun_srt(const StgInfoTable *info)
{
StgFunInfoTable *fun_info;
idea.
-------------------------------------------------------------------------- */
-static void
+static GNUC_ATTR_HOT void
scavenge_block (bdescr *bd)
{
StgPtr p, q;