summaryrefslogtreecommitdiff
path: root/erts/include
diff options
context:
space:
mode:
authorRickard Green <rickard@erlang.org>2020-07-20 13:17:29 +0200
committerRickard Green <rickard@erlang.org>2020-07-20 13:17:29 +0200
commite1aaf36382a136e84ede44f0c46f9623beaf7cc1 (patch)
treedf3dd3970efd407102d12c72cc6b621606866727 /erts/include
parent6b876666b9c59ef40f0d1400f56b54b8245929e3 (diff)
parent0fa0505fb6e9ad6cc1232b291d0b2e722c70eb9a (diff)
downloaderlang-e1aaf36382a136e84ede44f0c46f9623beaf7cc1.tar.gz
Merge branch 'rickard/tse/OTP-16766/ERL-1304' into maint
* rickard/tse/OTP-16766/ERL-1304: Fix multiple usage of same thread specific event at the same time
Diffstat (limited to 'erts/include')
-rw-r--r--erts/include/internal/ethread.h85
1 files changed, 68 insertions, 17 deletions
diff --git a/erts/include/internal/ethread.h b/erts/include/internal/ethread.h
index 2fe826226c..d6644185f9 100644
--- a/erts/include/internal/ethread.h
+++ b/erts/include/internal/ethread.h
@@ -629,12 +629,18 @@ struct ethr_ts_event_ {
#define ETHR_TS_EV_INITED (((unsigned) 1) << 1)
#define ETHR_TS_EV_TMP (((unsigned) 1) << 2)
#define ETHR_TS_EV_MAIN_THR (((unsigned) 1) << 3)
+#define ETHR_TS_EV_BUSY (((unsigned) 1) << 4)
+#define ETHR_TS_EV_PEEK (((unsigned) 1) << 5)
-int ethr_get_tmp_ts_event__(ethr_ts_event **tsepp);
+ethr_sint64_t ethr_no_used_tse(void);
int ethr_free_ts_event__(ethr_ts_event *tsep);
-int ethr_make_ts_event__(ethr_ts_event **tsepp);
+int ethr_make_ts_event__(ethr_ts_event **tsepp, int tmp);
#if !defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHREAD_IMPL__)
+ethr_ts_event *ethr_lookup_ts_event__(int busy_dup);
+ethr_ts_event *ethr_peek_ts_event(void);
+void ethr_unpeek_ts_event(ethr_ts_event *);
+ethr_ts_event *ethr_use_ts_event(ethr_ts_event *tsep);
ethr_ts_event *ethr_get_ts_event(void);
void ethr_leave_ts_event(ethr_ts_event *);
#endif
@@ -646,11 +652,11 @@ void ethr_leave_ts_event(ethr_ts_event *);
extern pthread_key_t ethr_ts_event_key__;
static ETHR_INLINE ethr_ts_event *
-ETHR_INLINE_FUNC_NAME_(ethr_get_ts_event)(void)
+ETHR_INLINE_FUNC_NAME_(ethr_lookup_ts_event__)(int busy_dup)
{
ethr_ts_event *tsep = pthread_getspecific(ethr_ts_event_key__);
- if (!tsep) {
- int res = ethr_make_ts_event__(&tsep);
+ if (!tsep || (busy_dup && (tsep->iflgs & ETHR_TS_EV_BUSY))) {
+ int res = ethr_make_ts_event__(&tsep, 0);
if (res != 0)
ETHR_FATAL_ERROR__(res);
ETHR_ASSERT(tsep);
@@ -658,12 +664,6 @@ ETHR_INLINE_FUNC_NAME_(ethr_get_ts_event)(void)
return tsep;
}
-static ETHR_INLINE void
-ETHR_INLINE_FUNC_NAME_(ethr_leave_ts_event)(ethr_ts_event *tsep)
-{
-
-}
-
#endif
#elif defined(ETHR_WIN32_THREADS)
@@ -673,11 +673,11 @@ ETHR_INLINE_FUNC_NAME_(ethr_leave_ts_event)(ethr_ts_event *tsep)
extern DWORD ethr_ts_event_key__;
static ETHR_INLINE ethr_ts_event *
-ETHR_INLINE_FUNC_NAME_(ethr_get_ts_event)(void)
+ETHR_INLINE_FUNC_NAME_(ethr_lookup_ts_event__)(int busy_dup)
{
ethr_ts_event *tsep = TlsGetValue(ethr_ts_event_key__);
- if (!tsep) {
- int res = ethr_get_tmp_ts_event__(&tsep);
+ if (!tsep || (busy_dup && (tsep->iflgs & ETHR_TS_EV_BUSY))) {
+ int res = ethr_make_ts_event__(&tsep, !0);
if (res != 0)
ETHR_FATAL_ERROR__(res);
ETHR_ASSERT(tsep);
@@ -685,17 +685,68 @@ ETHR_INLINE_FUNC_NAME_(ethr_get_ts_event)(void)
return tsep;
}
+#endif
+
+#endif
+
+#if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHREAD_IMPL__)
+
+static ETHR_INLINE ethr_ts_event *
+ETHR_INLINE_FUNC_NAME_(ethr_get_ts_event)(void)
+{
+ ethr_ts_event *tsep = ethr_lookup_ts_event__(!0);
+ ETHR_ASSERT(!(tsep->iflgs & ETHR_TS_EV_BUSY));
+ tsep->iflgs |= ETHR_TS_EV_BUSY;
+ return tsep;
+}
+
+static ETHR_INLINE ethr_ts_event *
+ETHR_INLINE_FUNC_NAME_(ethr_peek_ts_event)(void)
+{
+ ethr_ts_event *tsep = ethr_lookup_ts_event__(0);
+ ETHR_ASSERT(!(tsep->iflgs & ETHR_TS_EV_PEEK));
+ tsep->iflgs |= ETHR_TS_EV_PEEK;
+ return tsep;
+}
+
static ETHR_INLINE void
-ETHR_INLINE_FUNC_NAME_(ethr_leave_ts_event)(ethr_ts_event *tsep)
+ETHR_INLINE_FUNC_NAME_(ethr_unpeek_ts_event)(ethr_ts_event *tsep)
{
- if (tsep->iflgs & ETHR_TS_EV_TMP) {
+ ETHR_ASSERT(tsep->iflgs & ETHR_TS_EV_PEEK);
+ tsep->iflgs &= ~ETHR_TS_EV_PEEK;
+ if ((tsep->iflgs & (ETHR_TS_EV_TMP|ETHR_TS_EV_BUSY)) == ETHR_TS_EV_TMP) {
int res = ethr_free_ts_event__(tsep);
if (res != 0)
ETHR_FATAL_ERROR__(res);
}
}
-#endif
+static ETHR_INLINE ethr_ts_event *
+ETHR_INLINE_FUNC_NAME_(ethr_use_ts_event)(ethr_ts_event *tsep)
+{
+ ethr_ts_event *tmp_tsep = tsep;
+ if (tmp_tsep->iflgs & ETHR_TS_EV_BUSY) {
+ int res = ethr_make_ts_event__(&tmp_tsep, !0);
+ if (res != 0)
+ ETHR_FATAL_ERROR__(res);
+ ETHR_ASSERT(tmp_tsep && tsep != tmp_tsep);
+ }
+ ETHR_ASSERT(!(tmp_tsep->iflgs & ETHR_TS_EV_BUSY));
+ tmp_tsep->iflgs |= ETHR_TS_EV_BUSY;
+ return tmp_tsep;
+}
+
+static ETHR_INLINE void
+ETHR_INLINE_FUNC_NAME_(ethr_leave_ts_event)(ethr_ts_event *tsep)
+{
+ ETHR_ASSERT(tsep->iflgs & ETHR_TS_EV_BUSY);
+ tsep->iflgs &= ~ETHR_TS_EV_BUSY;
+ if ((tsep->iflgs & (ETHR_TS_EV_TMP|ETHR_TS_EV_PEEK)) == ETHR_TS_EV_TMP) {
+ int res = ethr_free_ts_event__(tsep);
+ if (res != 0)
+ ETHR_FATAL_ERROR__(res);
+ }
+}
#endif