aboutsummaryrefslogtreecommitdiffstats
path: root/erts/include
diff options
context:
space:
mode:
Diffstat (limited to 'erts/include')
-rw-r--r--erts/include/erl_native_features_config.h.in21
-rw-r--r--erts/include/internal/ethr_mutex.h8
-rw-r--r--erts/include/internal/ethread.h133
-rw-r--r--erts/include/internal/ethread_header_config.h.in2
-rw-r--r--erts/include/internal/ethread_inline.h49
-rw-r--r--erts/include/internal/ose/ethr_event.h113
-rw-r--r--erts/include/internal/win/ethr_membar.h8
7 files changed, 302 insertions, 32 deletions
diff --git a/erts/include/erl_native_features_config.h.in b/erts/include/erl_native_features_config.h.in
new file mode 100644
index 0000000000..d1674cb256
--- /dev/null
+++ b/erts/include/erl_native_features_config.h.in
@@ -0,0 +1,21 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2004-2011. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+/* Dirty scheduler support */
+#undef ERL_NIF_DIRTY_SCHEDULER_SUPPORT
diff --git a/erts/include/internal/ethr_mutex.h b/erts/include/internal/ethr_mutex.h
index 86a1e9fbdf..6c931e0cd4 100644
--- a/erts/include/internal/ethr_mutex.h
+++ b/erts/include/internal/ethr_mutex.h
@@ -97,7 +97,7 @@ void LeaveCriticalSection(CRITICAL_SECTION *);
#if 0
# define ETHR_MTX_Q_LOCK_SPINLOCK__
# define ETHR_MTX_QLOCK_TYPE__ ethr_spinlock_t
-#elif defined(ETHR_PTHREADS)
+#elif defined(ETHR_PTHREADS) || defined(ETHR_OSE_THREADS)
# define ETHR_MTX_Q_LOCK_PTHREAD_MUTEX__
# define ETHR_MTX_QLOCK_TYPE__ pthread_mutex_t
#elif defined(ETHR_WIN32_THREADS)
@@ -210,7 +210,7 @@ struct ethr_cond_ {
#endif
};
-#elif defined(ETHR_PTHREADS) && !defined(ETHR_DBG_WIN_MTX_WITH_PTHREADS)
+#elif (defined(ETHR_PTHREADS) || defined(ETHR_OSE_THREADS)) && !defined(ETHR_DBG_WIN_MTX_WITH_PTHREADS)
typedef struct ethr_mutex_ ethr_mutex;
struct ethr_mutex_ {
@@ -354,7 +354,7 @@ void ethr_rwmutex_rwunlock(ethr_rwmutex *);
#ifdef ETHR_MTX_HARD_DEBUG
#define ETHR_MTX_HARD_ASSERT(A) \
- ((void) ((A) ? 1 : ethr_assert_failed(__FILE__, __LINE__, #A)))
+ ((void) ((A) ? 1 : ethr_assert_failed(__FILE__, __LINE__, __func__,#A)))
#else
#define ETHR_MTX_HARD_ASSERT(A) ((void) 1)
#endif
@@ -633,7 +633,7 @@ ETHR_INLINE_MTX_FUNC_NAME_(ethr_mutex_unlock)(ethr_mutex *mtx)
#endif /* ETHR_TRY_INLINE_FUNCS */
-#elif defined(ETHR_PTHREADS) && !defined(ETHR_DBG_WIN_MTX_WITH_PTHREADS)
+#elif (defined(ETHR_PTHREADS) || defined(ETHR_OSE_THREADS)) && !defined(ETHR_DBG_WIN_MTX_WITH_PTHREADS)
#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_MUTEX_IMPL__)
diff --git a/erts/include/internal/ethread.h b/erts/include/internal/ethread.h
index 38b8e9e9b6..72c054b588 100644
--- a/erts/include/internal/ethread.h
+++ b/erts/include/internal/ethread.h
@@ -31,12 +31,18 @@
#endif
#include <stdlib.h>
+#include "ethread_inline.h"
#include "erl_errno.h"
#if defined(DEBUG)
# define ETHR_DEBUG
#endif
+#if defined(__PPC__) || defined (__POWERPC)
+/* OSE compiler should be fixed! */
+#define __ppc__
+#endif
+
#if defined(ETHR_DEBUG)
# undef ETHR_XCHK
# define ETHR_XCHK 1
@@ -46,21 +52,17 @@
# endif
#endif
-#undef ETHR_INLINE
-#if defined(__GNUC__)
-# define ETHR_INLINE __inline__
-#elif defined(__WIN32__)
-# define ETHR_INLINE __forceinline
-#endif
#if defined(ETHR_DEBUG) || !defined(ETHR_INLINE) || ETHR_XCHK \
|| (defined(__GNUC__) && defined(ERTS_MIXED_CYGWIN_VC))
# undef ETHR_INLINE
# define ETHR_INLINE
+# undef ETHR_FORCE_INLINE
+# define ETHR_FORCE_INLINE
# undef ETHR_TRY_INLINE_FUNCS
#endif
/* Assume 64-byte cache line size */
-#define ETHR_CACHE_LINE_SIZE 64
+#define ETHR_CACHE_LINE_SIZE ASSUMED_CACHE_LINE_SIZE
#define ETHR_CACHE_LINE_MASK (ETHR_CACHE_LINE_SIZE - 1)
#define ETHR_CACHE_LINE_ALIGN_SIZE(SZ) \
@@ -190,6 +192,30 @@ typedef DWORD ethr_tsd_key;
#define ETHR_YIELD() (Sleep(0), 0)
+#elif defined(ETHR_OSE_THREADS)
+
+#include "ose.h"
+#undef NIL
+
+#if defined(ETHR_HAVE_PTHREAD_H)
+#include <pthread.h>
+#endif
+
+typedef struct {
+ PROCESS id;
+ unsigned int tsd_key_index;
+ void *res;
+} ethr_tid;
+
+typedef OSPPDKEY ethr_tsd_key;
+
+#undef ETHR_HAVE_ETHR_SIG_FUNCS
+
+/* Out own RW mutexes are probably faster, but use OSEs mutexes */
+#define ETHR_USE_OWN_RWMTX_IMPL__
+
+#define ETHR_HAVE_THREAD_NAMES
+
#else /* No supported thread lib found */
#ifdef ETHR_NO_SUPP_THR_LIB_NOT_FATAL
@@ -256,19 +282,6 @@ ETHR_PROTO_NORETURN__ ethr_fatal_error__(const char *file,
const char *func,
int err);
-#if !defined(__GNUC__)
-# define ETHR_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) 0
-#elif !defined(__GNUC_MINOR__)
-# define ETHR_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) \
- ((__GNUC__ << 24) >= (((MAJ) << 24) | ((MIN) << 12) | (PL)))
-#elif !defined(__GNUC_PATCHLEVEL__)
-# define ETHR_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) \
- (((__GNUC__ << 24) | (__GNUC_MINOR__ << 12)) >= (((MAJ) << 24) | ((MIN) << 12) | (PL)))
-#else
-# define ETHR_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) \
- (((__GNUC__ << 24) | (__GNUC_MINOR__ << 12) | __GNUC_PATCHLEVEL__) >= (((MAJ) << 24) | ((MIN) << 12) | (PL)))
-#endif
-
#if !ETHR_AT_LEAST_GCC_VSN__(2, 96, 0)
#define __builtin_expect(X, Y) (X)
#endif
@@ -367,7 +380,19 @@ extern ethr_runtime_t ethr_runtime__;
#include "ethr_atomics.h" /* The atomics API */
-#if defined(__GNUC__)
+#if defined (ETHR_OSE_THREADS)
+static ETHR_INLINE void
+ose_yield(void)
+{
+ if (get_ptype(current_process()) == OS_PRI_PROC) {
+ set_pri(get_pri(current_process()));
+ } else {
+ delay(1);
+ }
+}
+#endif
+
+#if defined(__GNUC__) && !defined(ETHR_OSE_THREADS)
# ifndef ETHR_SPIN_BODY
# if defined(__i386__) || defined(__x86_64__)
# define ETHR_SPIN_BODY __asm__ __volatile__("rep;nop" : : : "memory")
@@ -383,9 +408,20 @@ extern ethr_runtime_t ethr_runtime__;
# ifndef ETHR_SPIN_BODY
# define ETHR_SPIN_BODY do {YieldProcessor();ETHR_COMPILER_BARRIER;} while(0)
# endif
+#elif defined(ETHR_OSE_THREADS)
+# ifndef ETHR_SPIN_BODY
+# define ETHR_SPIN_BODY ose_yield()
+# else
+# error "OSE should use ose_yield()"
+# endif
#endif
+#ifndef ETHR_OSE_THREADS
#define ETHR_YIELD_AFTER_BUSY_LOOPS 50
+#else
+#define ETHR_YIELD_AFTER_BUSY_LOOPS 0
+#endif
+
#ifndef ETHR_SPIN_BODY
# define ETHR_SPIN_BODY ETHR_COMPILER_BARRIER
@@ -408,12 +444,18 @@ extern ethr_runtime_t ethr_runtime__;
# else
# define ETHR_YIELD() (pthread_yield(), 0)
# endif
+# elif defined(ETHR_OSE_THREADS)
+# define ETHR_YIELD() (ose_yield(), 0)
# else
# define ETHR_YIELD() (ethr_compiler_barrier(), 0)
# endif
#endif
-#ifdef VALGRIND /* mutex as fallback for spinlock for VALGRIND */
+#if defined(VALGRIND) || defined(ETHR_OSE_THREADS)
+/* mutex as fallback for spinlock for VALGRIND and OSE.
+ OSE cannot use spinlocks as processes working on the
+ same execution unit have a tendency to deadlock.
+ */
# undef ETHR_HAVE_NATIVE_SPINLOCKS
# undef ETHR_HAVE_NATIVE_RWSPINLOCKS
#else
@@ -459,9 +501,19 @@ typedef struct {
typedef struct {
int detached; /* boolean (default false) */
int suggested_stack_size; /* kilo words (default sys dependent) */
+#ifdef ETHR_OSE_THREADS
+ char *name;
+ U32 coreNo;
+#endif
} ethr_thr_opts;
+#if defined(ETHR_OSE_THREADS)
+/* Default ethr name is big as we want to be able to sprint stuff in there */
+#define ETHR_THR_OPTS_DEFAULT_INITER \
+ {0, -1, "ethread", 0}
+#else
#define ETHR_THR_OPTS_DEFAULT_INITER {0, -1}
+#endif
#if !defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_AUX_IMPL__)
@@ -479,7 +531,7 @@ void ethr_thr_exit(void *);
ethr_tid ethr_self(void);
int ethr_equal_tids(ethr_tid, ethr_tid);
-int ethr_tsd_key_create(ethr_tsd_key *);
+int ethr_tsd_key_create(ethr_tsd_key *,char *);
int ethr_tsd_key_delete(ethr_tsd_key);
int ethr_tsd_set(ethr_tsd_key, void *);
void *ethr_tsd_get(ethr_tsd_key);
@@ -571,8 +623,10 @@ typedef struct ethr_ts_event_ ethr_ts_event; /* Needed by ethr_mutex.h */
#if defined(ETHR_WIN32_THREADS)
# include "win/ethr_event.h"
-#else
+#elif defined(ETHR_PTHREADS)
# include "pthread/ethr_event.h"
+#elif defined(ETHR_OSE_THREADS)
+# include "ose/ethr_event.h"
#endif
int ethr_set_main_thr_status(int, int);
@@ -662,6 +716,37 @@ ETHR_INLINE_FUNC_NAME_(ethr_leave_ts_event)(ethr_ts_event *tsep)
#endif
+#elif defined (ETHR_OSE_THREADS)
+
+#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHREAD_IMPL__)
+
+extern ethr_tsd_key ethr_ts_event_key__;
+
+static ETHR_INLINE ethr_ts_event *
+ETHR_INLINE_FUNC_NAME_(ethr_get_ts_event)(void)
+{
+ ethr_ts_event *tsep = *(ethr_ts_event**)ose_get_ppdata(ethr_ts_event_key__);
+ if (!tsep) {
+ int res = ethr_get_tmp_ts_event__(&tsep);
+ if (res != 0)
+ ETHR_FATAL_ERROR__(res);
+ ETHR_ASSERT(tsep);
+ }
+ return tsep;
+}
+
+static ETHR_INLINE void
+ETHR_INLINE_FUNC_NAME_(ethr_leave_ts_event)(ethr_ts_event *tsep)
+{
+ if (tsep->iflgs & ETHR_TS_EV_TMP) {
+ int res = ethr_free_ts_event__(tsep);
+ if (res != 0)
+ ETHR_FATAL_ERROR__(res);
+ }
+}
+
+#endif
+
#endif
#include "ethr_mutex.h" /* Need atomic declarations and tse */
diff --git a/erts/include/internal/ethread_header_config.h.in b/erts/include/internal/ethread_header_config.h.in
index dd3599f86d..b36322490a 100644
--- a/erts/include/internal/ethread_header_config.h.in
+++ b/erts/include/internal/ethread_header_config.h.in
@@ -235,3 +235,5 @@
/* Define if you want to turn on extra sanity checking in the ethread library */
#undef ETHR_XCHK
+/* Assumed cache-line size (in bytes) */
+#undef ASSUMED_CACHE_LINE_SIZE
diff --git a/erts/include/internal/ethread_inline.h b/erts/include/internal/ethread_inline.h
new file mode 100644
index 0000000000..ffb756c84f
--- /dev/null
+++ b/erts/include/internal/ethread_inline.h
@@ -0,0 +1,49 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2004-2014. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#ifndef ETHREAD_INLINE_H__
+#define ETHREAD_INLINE_H__
+
+#if !defined(__GNUC__)
+# define ETHR_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) 0
+#elif !defined(__GNUC_MINOR__)
+# define ETHR_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) \
+ ((__GNUC__ << 24) >= (((MAJ) << 24) | ((MIN) << 12) | (PL)))
+#elif !defined(__GNUC_PATCHLEVEL__)
+# define ETHR_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) \
+ (((__GNUC__ << 24) | (__GNUC_MINOR__ << 12)) >= (((MAJ) << 24) | ((MIN) << 12) | (PL)))
+#else
+# define ETHR_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) \
+ (((__GNUC__ << 24) | (__GNUC_MINOR__ << 12) | __GNUC_PATCHLEVEL__) >= (((MAJ) << 24) | ((MIN) << 12) | (PL)))
+#endif
+
+#undef ETHR_INLINE
+#if defined(__GNUC__)
+# define ETHR_INLINE __inline__
+# if ETHR_AT_LEAST_GCC_VSN__(3, 1, 1)
+# define ETHR_FORCE_INLINE __inline__ __attribute__((__always_inline__))
+# else
+# define ETHR_FORCE_INLINE __inline__
+# endif
+#elif defined(__WIN32__)
+# define ETHR_INLINE __forceinline
+# define ETHR_FORCE_INLINE __forceinline
+#endif
+
+#endif /* #ifndef ETHREAD_INLINE_H__ */
diff --git a/erts/include/internal/ose/ethr_event.h b/erts/include/internal/ose/ethr_event.h
new file mode 100644
index 0000000000..000a600813
--- /dev/null
+++ b/erts/include/internal/ose/ethr_event.h
@@ -0,0 +1,113 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2009-2011. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Author: Rickard Green
+ */
+
+//#define USE_PTHREAD_API
+
+#define ETHR_EVENT_OFF_WAITER__ -1L
+#define ETHR_EVENT_OFF__ 1L
+#define ETHR_EVENT_ON__ 0L
+
+#ifdef USE_PTHREAD_API
+
+typedef struct {
+ ethr_atomic32_t state;
+ pthread_mutex_t mtx;
+ pthread_cond_t cnd;
+} ethr_event;
+
+#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_EVENT_IMPL__)
+
+static void ETHR_INLINE
+ETHR_INLINE_FUNC_NAME_(ethr_event_set)(ethr_event *e)
+{
+ ethr_sint32_t val;
+ val = ethr_atomic32_xchg_mb(&e->state, ETHR_EVENT_ON__);
+ if (val == ETHR_EVENT_OFF_WAITER__) {
+ int res = pthread_mutex_lock(&e->mtx);
+ if (res != 0)
+ ETHR_FATAL_ERROR__(res);
+ res = pthread_cond_signal(&e->cnd);
+ if (res != 0)
+ ETHR_FATAL_ERROR__(res);
+ res = pthread_mutex_unlock(&e->mtx);
+ if (res != 0)
+ ETHR_FATAL_ERROR__(res);
+ }
+}
+
+static void ETHR_INLINE
+ETHR_INLINE_FUNC_NAME_(ethr_event_reset)(ethr_event *e)
+{
+ ethr_atomic32_set(&e->state, ETHR_EVENT_OFF__);
+ ETHR_MEMORY_BARRIER;
+}
+
+#endif
+
+#else
+
+typedef struct {
+ ethr_atomic32_t state;
+ PROCESS proc;
+} ethr_event;
+
+#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_EVENT_IMPL__)
+
+static void ETHR_INLINE
+ETHR_INLINE_FUNC_NAME_(ethr_event_set)(ethr_event *e)
+{
+ ethr_sint32_t val = ethr_atomic32_xchg_mb(&e->state, ETHR_EVENT_ON__);
+ if (val == ETHR_EVENT_OFF_WAITER__) {
+#ifdef DEBUG
+ OSFSEMVAL fsem_val = get_fsem(e->proc);
+
+ /* There is a race in this assert.
+ This is because the state is set before the wait call in wait__.
+ We hope that a delay of 10 ms is enough */
+ if (fsem_val == 0)
+ delay(10);
+ ETHR_ASSERT(get_fsem(e->proc) == -1);
+#endif
+ signal_fsem(e->proc);
+ }
+}
+
+static void ETHR_INLINE
+ETHR_INLINE_FUNC_NAME_(ethr_event_reset)(ethr_event *e)
+{
+ ethr_atomic32_set(&e->state, ETHR_EVENT_OFF__);
+ ETHR_MEMORY_BARRIER;
+}
+
+#endif
+
+#endif
+
+int ethr_event_init(ethr_event *e);
+int ethr_event_destroy(ethr_event *e);
+int ethr_event_wait(ethr_event *e);
+int ethr_event_swait(ethr_event *e, int spincount);
+#if !defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_EVENT_IMPL__)
+void ethr_event_set(ethr_event *e);
+void ethr_event_reset(ethr_event *e);
+#endif
diff --git a/erts/include/internal/win/ethr_membar.h b/erts/include/internal/win/ethr_membar.h
index 8237660b2c..a17f2459fc 100644
--- a/erts/include/internal/win/ethr_membar.h
+++ b/erts/include/internal/win/ethr_membar.h
@@ -63,13 +63,13 @@ do { \
#pragma intrinsic(_mm_sfence)
#pragma intrinsic(_mm_lfence)
-static __forceinline void
+static ETHR_FORCE_INLINE void
ethr_cfence__(void)
{
_ReadWriteBarrier();
}
-static __forceinline void
+static ETHR_FORCE_INLINE void
ethr_mfence__(void)
{
#if ETHR_SIZEOF_PTR == 4
@@ -80,7 +80,7 @@ ethr_mfence__(void)
_mm_mfence();
}
-static __forceinline void
+static ETHR_FORCE_INLINE void
ethr_sfence__(void)
{
#if ETHR_SIZEOF_PTR == 4
@@ -91,7 +91,7 @@ ethr_sfence__(void)
_mm_sfence();
}
-static __forceinline void
+static ETHR_FORCE_INLINE void
ethr_lfence__(void)
{
#if ETHR_SIZEOF_PTR == 4