aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
Diffstat (limited to 'erts')
-rw-r--r--erts/aclocal.m429
-rw-r--r--erts/configure.in9
-rw-r--r--erts/emulator/beam/beam_debug.c31
-rw-r--r--erts/emulator/beam/break.c4
-rw-r--r--erts/emulator/beam/erl_db_hash.c60
-rw-r--r--erts/emulator/beam/erl_debug.c3
-rw-r--r--erts/emulator/beam/erl_map.c5
-rw-r--r--erts/emulator/beam/erl_printf_term.c8
-rw-r--r--erts/emulator/beam/erl_process.c43
-rw-r--r--erts/emulator/beam/erl_term.c1
-rw-r--r--erts/emulator/beam/erl_term.h3
-rw-r--r--erts/emulator/beam/erl_threads.h10
-rw-r--r--erts/emulator/beam/utils.c1
-rw-r--r--erts/emulator/drivers/unix/unix_efile.c10
-rw-r--r--erts/emulator/hipe/hipe_bif0.c2
-rw-r--r--erts/emulator/hipe/hipe_bif_list.m432
-rw-r--r--erts/emulator/hipe/hipe_mkliterals.c10
-rw-r--r--erts/emulator/test/erts_debug_SUITE.erl47
-rw-r--r--erts/emulator/test/map_SUITE.erl44
-rw-r--r--erts/emulator/test/match_spec_SUITE.erl60
-rwxr-xr-xerts/emulator/utils/make_alloc_types2
-rwxr-xr-xerts/emulator/utils/make_version6
-rw-r--r--erts/emulator/utils/mkver.c6
-rw-r--r--erts/include/internal/pthread/ethr_event.h11
-rw-r--r--erts/include/internal/win/ethr_event.h1
-rw-r--r--erts/lib_src/pthread/ethr_event.c97
-rw-r--r--erts/lib_src/win/ethr_event.c6
27 files changed, 413 insertions, 128 deletions
diff --git a/erts/aclocal.m4 b/erts/aclocal.m4
index 0714ce6030..390d6cfc4d 100644
--- a/erts/aclocal.m4
+++ b/erts/aclocal.m4
@@ -750,8 +750,8 @@ AC_DEFUN(ERL_MONOTONIC_CLOCK,
prefer_resolution_clock_gettime_monotonic="$2"
;;
*)
- check_msg=""
- prefer_resolution_clock_gettime_monotonic=
+ check_msg="custom "
+ prefer_resolution_clock_gettime_monotonic="$2"
;;
esac
@@ -940,16 +940,16 @@ AC_DEFUN(ERL_WALL_CLOCK,
erl_wall_clock_low_resolution=no
erl_wall_clock_id=
- case $erl_cv_clock_gettime_wall_$1-$erl_cv_mach_clock_get_time_wall-$ac_cv_func_gettimeofday-$host_os in
- *-*-*-win32)
+ case $1-$erl_cv_clock_gettime_wall_$1-$erl_cv_mach_clock_get_time_wall-$ac_cv_func_gettimeofday-$host_os in
+ *-*-*-*-win32)
erl_wall_clock_func=WindowsAPI
erl_wall_clock_low_resolution=yes
;;
- no-yes-*-*)
+ high_resolution-no-yes-*-*)
erl_wall_clock_func=mach_clock_get_time
erl_wall_clock_id=CALENDAR_CLOCK
;;
- CLOCK_*-*-*-*)
+ *-CLOCK_*-*-*-*)
erl_wall_clock_func=clock_gettime
erl_wall_clock_id=$erl_cv_clock_gettime_wall_$1
for low_res_id in $low_resolution_clock_gettime_wall; do
@@ -959,7 +959,7 @@ AC_DEFUN(ERL_WALL_CLOCK,
fi
done
;;
- no-no-yes-*)
+ *-no-*-yes-*)
erl_wall_clock_func=gettimeofday
;;
*)
@@ -1472,7 +1472,7 @@ AC_ARG_WITH(with_sparc_memory_order,
LM_CHECK_THR_LIB
ERL_INTERNAL_LIBS
-ERL_MONOTONIC_CLOCK(high_resolution, undefined, no)
+ERL_MONOTONIC_CLOCK(try_find_pthread_compatible, CLOCK_HIGHRES CLOCK_MONOTONIC, no)
case $erl_monotonic_clock_func in
clock_gettime)
@@ -1906,7 +1906,7 @@ case "$THR_LIB_NAME" in
#define _DARWIN_C_SOURCE
#include <pthread.h>],
[char buff[256]; pthread_getname_np(pthread_self(), buff, 256);],
- pthread_getname=normal)
+ pthread_getname=linux)
AC_TRY_LINK([#define __USE_GNU
#define _DARWIN_C_SOURCE
#include <pthread.h>],
@@ -2219,10 +2219,10 @@ AS_HELP_STRING([--with-clock-gettime-monotonic-id=CLOCKID],
[specify clock id to use with clock_gettime() for monotonic time)]))
AC_ARG_ENABLE(prefer-elapsed-monotonic-time-during-suspend,
- AS_HELP_STRING([--enable-prefer-elapsed-monotonic-time-during-suspend],
- [Prefer an OS monotonic time source with elapsed time during suspend])
- AS_HELP_STRING([--disable-prefer-elapsed-monotonic-time-during-suspend],
- [Do not prefer an OS monotonic time source with elapsed time during suspend]),
+AS_HELP_STRING([--enable-prefer-elapsed-monotonic-time-during-suspend],
+ [Prefer an OS monotonic time source with elapsed time during suspend])
+AS_HELP_STRING([--disable-prefer-elapsed-monotonic-time-during-suspend],
+ [Do not prefer an OS monotonic time source with elapsed time during suspend]),
[ case "$enableval" in
yes) prefer_elapsed_monotonic_time_during_suspend=yes ;;
*) prefer_elapsed_monotonic_time_during_suspend=no ;;
@@ -2296,6 +2296,9 @@ case "$erl_wall_clock_func-$erl_wall_clock_id-$with_clock_gettime_realtime_id" i
esac
case $erl_wall_clock_func in
+ none)
+ AC_MSG_ERROR([No wall clock source found])
+ ;;
mach_clock_get_time)
AC_DEFINE(OS_SYSTEM_TIME_USING_MACH_CLOCK_GET_TIME, [1], [Define if you want to implement erts_os_system_time() using mach clock_get_time()])
;;
diff --git a/erts/configure.in b/erts/configure.in
index 22ca7ec17d..4fb725ff00 100644
--- a/erts/configure.in
+++ b/erts/configure.in
@@ -342,6 +342,15 @@ AS_HELP_STRING([--enable-systemd], [enable systemd support in epmd]),
[],
[enable_systemd=no])
+AC_ARG_ENABLE(saved-compile-time,
+AS_HELP_STRING([--disable-saved-compile-time], [disable saved compile time]),
+[ case "$enableval" in
+ no) save_compile_time=0 ;;
+ *) save_compile_time=1 ;;
+ esac ], save_compile_time=1)
+
+AC_DEFINE_UNQUOTED(ERTS_SAVED_COMPILE_TIME, $save_compile_time, [Save compile time?])
+
dnl Magic test for clearcase.
OTP_RELEASE=
if test "${ERLANG_COMMERCIAL_BUILD}" != ""; then
diff --git a/erts/emulator/beam/beam_debug.c b/erts/emulator/beam/beam_debug.c
index c756de8c8e..c774a70d4c 100644
--- a/erts/emulator/beam/beam_debug.c
+++ b/erts/emulator/beam/beam_debug.c
@@ -298,8 +298,8 @@ erts_debug_disassemble_1(BIF_ALIST_1)
(void) erts_bld_uword(NULL, &hsz, (BeamInstr) code_ptr);
hp = HAlloc(p, hsz);
addr = erts_bld_uword(&hp, NULL, (BeamInstr) code_ptr);
- ASSERT(is_atom(funcinfo[0]));
- ASSERT(is_atom(funcinfo[1]));
+ ASSERT(is_atom(funcinfo[0]) || funcinfo[0] == NIL);
+ ASSERT(is_atom(funcinfo[1]) || funcinfo[1] == NIL);
mfa = TUPLE3(hp, (Eterm) funcinfo[0], (Eterm) funcinfo[1], make_small((Eterm) funcinfo[2]));
hp += 4;
return TUPLE3(hp, addr, bin, mfa);
@@ -669,7 +669,6 @@ print_op(int to, void *to_arg, int op, int size, BeamInstr* addr)
case op_new_map_dII:
case op_update_map_assoc_jsdII:
case op_update_map_exact_jsdII:
- case op_i_get_map_elements_fsI:
{
int n = unpacked[-1];
@@ -693,6 +692,32 @@ print_op(int to, void *to_arg, int op, int size, BeamInstr* addr)
}
}
break;
+ case op_i_get_map_elements_fsI:
+ {
+ int n = unpacked[-1];
+
+ while (n > 0) {
+ if (n % 3 == 1) {
+ erts_print(to, to_arg, " %X", ap[0]);
+ } else if (!is_header(ap[0])) {
+ erts_print(to, to_arg, " %T", (Eterm) ap[0]);
+ } else {
+ switch ((ap[0] >> 2) & 0x03) {
+ case R_REG_DEF:
+ erts_print(to, to_arg, " x(0)");
+ break;
+ case X_REG_DEF:
+ erts_print(to, to_arg, " x(%d)", ap[0] >> 4);
+ break;
+ case Y_REG_DEF:
+ erts_print(to, to_arg, " y(%d)", ap[0] >> 4);
+ break;
+ }
+ }
+ ap++, size++, n--;
+ }
+ }
+ break;
}
erts_print(to, to_arg, "\n");
diff --git a/erts/emulator/beam/break.c b/erts/emulator/beam/break.c
index 64c8bc5e58..4ce9d24479 100644
--- a/erts/emulator/beam/break.c
+++ b/erts/emulator/beam/break.c
@@ -536,7 +536,9 @@ do_break(void)
erts_printf("Erlang (%s) emulator version "
ERLANG_VERSION "\n",
EMULATOR);
+#if ERTS_SAVED_COMPILE_TIME
erts_printf("Compiled on " ERLANG_COMPILE_DATE "\n");
+#endif
return;
case 'd':
distribution_info(ERTS_PRINT_STDOUT, NULL);
@@ -774,7 +776,9 @@ erl_crash_dump_v(char *file, int line, char* fmt, va_list args)
}
erts_fdprintf(fd, "System version: ");
erts_print_system_version(fd, NULL, NULL);
+#if ERTS_SAVED_COMPILE_TIME
erts_fdprintf(fd, "%s\n", "Compiled: " ERLANG_COMPILE_DATE);
+#endif
erts_fdprintf(fd, "Taints: ");
erts_print_nif_taints(fd, NULL);
diff --git a/erts/emulator/beam/erl_db_hash.c b/erts/emulator/beam/erl_db_hash.c
index 81b0c4465c..98a2e2842a 100644
--- a/erts/emulator/beam/erl_db_hash.c
+++ b/erts/emulator/beam/erl_db_hash.c
@@ -148,8 +148,11 @@ static ERTS_INLINE Uint hash_to_ix(DbTableHash* tb, HashValue hval)
}
/* Remember a slot containing a pseudo-deleted item (INVALID_HASH)
-*/
-static ERTS_INLINE void add_fixed_deletion(DbTableHash* tb, int ix)
+ * Return false if we got raced by unfixing thread
+ * and the object should be deleted for real.
+ */
+static ERTS_INLINE int add_fixed_deletion(DbTableHash* tb, int ix,
+ erts_aint_t fixated_by_me)
{
erts_aint_t was_next;
erts_aint_t exp_next;
@@ -160,12 +163,18 @@ static ERTS_INLINE void add_fixed_deletion(DbTableHash* tb, int ix)
fixd->slot = ix;
was_next = erts_smp_atomic_read_acqb(&tb->fixdel);
do { /* Lockless atomic insertion in linked list: */
- exp_next = was_next;
+ if (NFIXED(tb) <= fixated_by_me) {
+ erts_db_free(ERTS_ALC_T_DB_FIX_DEL, (DbTable*)tb,
+ fixd, sizeof(FixedDeletion));
+ return 0; /* raced by unfixer */
+ }
+ exp_next = was_next;
fixd->next = (FixedDeletion*) exp_next;
- was_next = erts_smp_atomic_cmpxchg_relb(&tb->fixdel,
- (erts_aint_t) fixd,
- exp_next);
+ was_next = erts_smp_atomic_cmpxchg_mb(&tb->fixdel,
+ (erts_aint_t) fixd,
+ exp_next);
}while (was_next != exp_next);
+ return 1;
}
@@ -607,8 +616,8 @@ void db_unfix_table_hash(DbTableHash *tb)
|| (erts_smp_lc_rwmtx_is_rlocked(&tb->common.rwlock)
&& !tb->common.is_thread_safe));
restart:
- fixdel = (FixedDeletion*) erts_smp_atomic_xchg_acqb(&tb->fixdel,
- (erts_aint_t) NULL);
+ fixdel = (FixedDeletion*) erts_smp_atomic_xchg_mb(&tb->fixdel,
+ (erts_aint_t) NULL);
while (fixdel != NULL) {
FixedDeletion *fx = fixdel;
int ix = fx->slot;
@@ -1142,9 +1151,9 @@ int db_erase_hash(DbTable *tbl, Eterm key, Eterm *ret)
while(b != 0) {
if (has_live_key(tb,b,key,hval)) {
--nitems_diff;
- if (nitems_diff == -1 && IS_FIXED(tb)) {
+ if (nitems_diff == -1 && IS_FIXED(tb)
+ && add_fixed_deletion(tb, ix, 0)) {
/* Pseudo remove (no need to keep several of same key) */
- add_fixed_deletion(tb, ix);
b->hvalue = INVALID_HASH;
} else {
*bp = b->next;
@@ -1196,9 +1205,8 @@ static int db_erase_object_hash(DbTable *tbl, Eterm object, Eterm *ret)
++nkeys;
if (db_eq(&tb->common,object, &b->dbterm)) {
--nitems_diff;
- if (nkeys==1 && IS_FIXED(tb)) { /* Pseudo remove */
- add_fixed_deletion(tb,ix);
- b->hvalue = INVALID_HASH;
+ if (nkeys==1 && IS_FIXED(tb) && add_fixed_deletion(tb,ix,0)) {
+ b->hvalue = INVALID_HASH; /* Pseudo remove */
bp = &b->next;
b = b->next;
} else {
@@ -1820,14 +1828,17 @@ static int db_select_delete_hash(Process *p,
int did_erase = 0;
if (db_match_dbterm(&tb->common, p, mpi.mp, 0,
&(*current)->dbterm, NULL, 0) == am_true) {
+ HashDbTerm *del;
if (NFIXED(tb) > fixated_by_me) { /* fixated by others? */
if (slot_ix != last_pseudo_delete) {
- add_fixed_deletion(tb, slot_ix);
- last_pseudo_delete = slot_ix;
+ if (!add_fixed_deletion(tb, slot_ix, fixated_by_me))
+ goto do_erase;
+ last_pseudo_delete = slot_ix;
}
(*current)->hvalue = INVALID_HASH;
} else {
- HashDbTerm *del = *current;
+ do_erase:
+ del = *current;
*current = (*current)->next;
free_term(tb, del);
did_erase = 1;
@@ -1931,14 +1942,17 @@ static int db_select_delete_continue_hash(Process *p,
int did_erase = 0;
if (db_match_dbterm(&tb->common, p, mp, 0,
&(*current)->dbterm, NULL, 0) == am_true) {
+ HashDbTerm *del;
if (NFIXED(tb) > fixated_by_me) { /* fixated by others? */
if (slot_ix != last_pseudo_delete) {
- add_fixed_deletion(tb, slot_ix);
+ if (!add_fixed_deletion(tb, slot_ix, fixated_by_me))
+ goto do_erase;
last_pseudo_delete = slot_ix;
}
(*current)->hvalue = INVALID_HASH;
} else {
- HashDbTerm *del = *current;
+ do_erase:
+ del = *current;
*current = (*current)->next;
free_term(tb, del);
did_erase = 1;
@@ -2089,9 +2103,9 @@ static int db_take_hash(Process *p, DbTable *tbl, Eterm key, Eterm *ret)
*ret = get_term_list(p, tb, key, hval, b, &bend);
while (b != bend) {
--nitems_diff;
- if (nitems_diff == -1 && IS_FIXED(tb)) {
+ if (nitems_diff == -1 && IS_FIXED(tb)
+ && add_fixed_deletion(tb, ix, 0)) {
/* Pseudo remove (no need to keep several of same key) */
- add_fixed_deletion(tb, ix);
bp = &b->next;
b->hvalue = INVALID_HASH;
b = b->next;
@@ -2131,7 +2145,7 @@ int db_mark_all_deleted_hash(DbTable *tbl)
for (i = 0; i < NACTIVE(tb); i++) {
if ((list = BUCKET(tb,i)) != NULL) {
- add_fixed_deletion(tb, i);
+ add_fixed_deletion(tb, i, 0);
do {
list->hvalue = INVALID_HASH;
list = list->next;
@@ -2908,8 +2922,8 @@ db_finalize_dbterm_hash(int cret, DbUpdateHandle* handle)
ASSERT((&b->dbterm == handle->dbterm) == !(tb->common.compress && handle->flags & DB_MUST_RESIZE));
if (handle->flags & DB_NEW_OBJECT && cret != DB_ERROR_NONE) {
- if (IS_FIXED(tb)) {
- add_fixed_deletion(tb, hash_to_ix(tb, b->hvalue));
+ if (IS_FIXED(tb) && add_fixed_deletion(tb, hash_to_ix(tb, b->hvalue),
+ 0)) {
b->hvalue = INVALID_HASH;
} else {
*bp = b->next;
diff --git a/erts/emulator/beam/erl_debug.c b/erts/emulator/beam/erl_debug.c
index 77a1e3d7cb..2dcfb79f00 100644
--- a/erts/emulator/beam/erl_debug.c
+++ b/erts/emulator/beam/erl_debug.c
@@ -189,6 +189,9 @@ pdisplay1(int to, void *to_arg, Process* p, Eterm obj)
case BINARY_DEF:
erts_print(to, to_arg, "#Bin");
break;
+ case MATCHSTATE_DEF:
+ erts_print(to, to_arg, "#Matchstate");
+ break;
default:
erts_print(to, to_arg, "unknown object %x", obj);
}
diff --git a/erts/emulator/beam/erl_map.c b/erts/emulator/beam/erl_map.c
index a91e36e3c5..ff2a355309 100644
--- a/erts/emulator/beam/erl_map.c
+++ b/erts/emulator/beam/erl_map.c
@@ -32,7 +32,9 @@
#include "global.h"
#include "erl_process.h"
#include "error.h"
+#define ERL_WANT_HIPE_BIF_WRAPPER__
#include "bif.h"
+#undef ERL_WANT_HIPE_BIF_WRAPPER__
#include "erl_binary.h"
#include "erl_map.h"
@@ -952,8 +954,11 @@ BIF_RETTYPE maps_keys_1(BIF_ALIST_1) {
BIF_P->fvalue = BIF_ARG_1;
BIF_ERROR(BIF_P, BADMAP);
}
+
/* maps:merge/2 */
+HIPE_WRAPPER_BIF_DISABLE_GC(maps_merge, 2)
+
BIF_RETTYPE maps_merge_2(BIF_ALIST_2) {
if (is_flatmap(BIF_ARG_1)) {
if (is_flatmap(BIF_ARG_2)) {
diff --git a/erts/emulator/beam/erl_printf_term.c b/erts/emulator/beam/erl_printf_term.c
index 267c0b3ff4..2917d58932 100644
--- a/erts/emulator/beam/erl_printf_term.c
+++ b/erts/emulator/beam/erl_printf_term.c
@@ -467,10 +467,7 @@ print_term(fmtfn_t fn, void* arg, Eterm obj, long *dcount,
}
break;
case BINARY_DEF:
- if (header_is_bin_matchstate(*boxed_val(wobj))) {
- PRINT_STRING(res, fn, arg, "#MatchState");
- }
- else {
+ {
byte* bytep;
Uint bytesize = binary_size_rel(obj,obj_base);
Uint bitoffs;
@@ -633,6 +630,9 @@ print_term(fmtfn_t fn, void* arg, Eterm obj, long *dcount,
}
}
break;
+ case MATCHSTATE_DEF:
+ PRINT_STRING(res, fn, arg, "#MatchState");
+ break;
default:
PRINT_STRING(res, fn, arg, "<unknown:");
PRINT_POINTER(res, fn, arg, wobj);
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index ee1dd36d48..3b1b593d1c 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -7938,11 +7938,16 @@ sched_thread_func(void *vesdp)
ErtsThrPrgrCallbacks callbacks;
ErtsSchedulerData *esdp = vesdp;
Uint no = esdp->no;
+#ifdef ERTS_SMP
+ erts_tse_t *tse;
+#endif
erts_sched_init_time_sup(esdp);
#ifdef ERTS_SMP
- ERTS_SCHED_SLEEP_INFO_IX(no - 1)->event = erts_tse_fetch();
+ tse = erts_tse_fetch();
+ erts_tse_prepare_timed(tse);
+ ERTS_SCHED_SLEEP_INFO_IX(no - 1)->event = tse;
callbacks.arg = (void *) esdp->ssi;
callbacks.wakeup = thr_prgr_wakeup;
callbacks.prepare_wait = thr_prgr_prep_wait;
@@ -9177,6 +9182,10 @@ erts_set_process_priority(Process *p, Eterm value)
a = erts_smp_atomic32_cmpxchg_mb(&p->state, n, e);
} while (a != e);
+
+ if (slocked)
+ erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
+
}
switch (oprio) {
@@ -11522,10 +11531,14 @@ save_pending_exiter(Process *p)
{
ErtsProcList *plp;
ErtsRunQueue *rq;
+ ErtsSchedulerData *esdp = erts_get_scheduler_data();
ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_STATUS & erts_proc_lc_my_proc_locks(p));
- rq = erts_get_runq_current(NULL);
+ if (!esdp)
+ rq = RUNQ_READ_RQ(&p->run_queue);
+ else
+ rq = esdp->run_queue;
plp = proclist_create(p);
@@ -11542,6 +11555,7 @@ save_pending_exiter(Process *p)
else
#endif
wake_scheduler(rq);
+
}
#endif
@@ -11730,23 +11744,21 @@ send_exit_signal(Process *c_p, /* current process if and only
if (need_locks
&& erts_smp_proc_trylock(rp, need_locks) == EBUSY) {
/* ... but we havn't got all locks on it ... */
- save_pending_exiter(rp);
+ save_pending_exiter(rp);
/*
* The pending exit will be discovered when next
* process is scheduled in
*/
- goto set_pending_exit;
- }
- else {
- /* ...and we have all locks on it... */
- *rp_locks = ERTS_PROC_LOCKS_ALL;
- set_proc_exiting(rp,
- state,
- (is_immed(rsn)
- ? rsn
- : copy_object(rsn, rp)),
- NULL);
+ goto set_pending_exit;
}
+ /* ...and we have all locks on it... */
+ *rp_locks = ERTS_PROC_LOCKS_ALL;
+ set_proc_exiting(rp,
+ state,
+ (is_immed(rsn)
+ ? rsn
+ : copy_object(rsn, rp)),
+ NULL);
}
else { /* Process running... */
@@ -12126,7 +12138,8 @@ erts_do_exit_process(Process* p, Eterm reason)
#endif
if (p->static_flags & ERTS_STC_FLG_SYSTEM_PROC)
- erl_exit(1, "System process %T terminated: %T\n", p->common.id, reason);
+ erl_exit(ERTS_DUMP_EXIT, "System process %T terminated: %T\n",
+ p->common.id, reason);
#ifdef ERTS_SMP
ERTS_SMP_CHK_HAVE_ONLY_MAIN_PROC_LOCK(p);
diff --git a/erts/emulator/beam/erl_term.c b/erts/emulator/beam/erl_term.c
index 89459fb278..e5050bfaa5 100644
--- a/erts/emulator/beam/erl_term.c
+++ b/erts/emulator/beam/erl_term.c
@@ -91,6 +91,7 @@ unsigned tag_val_def(Wterm x)
case (_TAG_HEADER_REFC_BIN >> _TAG_PRIMARY_SIZE): return BINARY_DEF;
case (_TAG_HEADER_HEAP_BIN >> _TAG_PRIMARY_SIZE): return BINARY_DEF;
case (_TAG_HEADER_SUB_BIN >> _TAG_PRIMARY_SIZE): return BINARY_DEF;
+ case (_TAG_HEADER_BIN_MATCHSTATE >> _TAG_PRIMARY_SIZE): return MATCHSTATE_DEF;
}
break;
diff --git a/erts/emulator/beam/erl_term.h b/erts/emulator/beam/erl_term.h
index 90e35151b0..d5e91d80d9 100644
--- a/erts/emulator/beam/erl_term.h
+++ b/erts/emulator/beam/erl_term.h
@@ -1136,8 +1136,9 @@ _ET_DECLARE_CHECKED(Uint,y_reg_index,Uint)
#define FLOAT_DEF 0xe
#define BIG_DEF 0xf
#define SMALL_DEF 0x10
+#define MATCHSTATE_DEF 0x11 /* not a "real" term */
-#define FIRST_VACANT_TAG_DEF 0x11
+#define FIRST_VACANT_TAG_DEF 0x12
#if ET_DEBUG
extern unsigned tag_val_def_debug(Wterm, const char*, unsigned);
diff --git a/erts/emulator/beam/erl_threads.h b/erts/emulator/beam/erl_threads.h
index 5347979372..34f91e2ec8 100644
--- a/erts/emulator/beam/erl_threads.h
+++ b/erts/emulator/beam/erl_threads.h
@@ -649,6 +649,7 @@ ERTS_GLB_INLINE void erts_tsd_set(erts_tsd_key_t key, void *value);
ERTS_GLB_INLINE void * erts_tsd_get(erts_tsd_key_t key);
ERTS_GLB_INLINE erts_tse_t *erts_tse_fetch(void);
ERTS_GLB_INLINE void erts_tse_return(erts_tse_t *ep);
+ERTS_GLB_INLINE void erts_tse_prepare_timed(erts_tse_t *ep);
ERTS_GLB_INLINE void erts_tse_set(erts_tse_t *ep);
ERTS_GLB_INLINE void erts_tse_reset(erts_tse_t *ep);
ERTS_GLB_INLINE int erts_tse_wait(erts_tse_t *ep);
@@ -3461,6 +3462,15 @@ ERTS_GLB_INLINE void erts_tse_return(erts_tse_t *ep)
#endif
}
+ERTS_GLB_INLINE void erts_tse_prepare_timed(erts_tse_t *ep)
+{
+#ifdef USE_THREADS
+ int res = ethr_event_prepare_timed(&((ethr_ts_event *) ep)->event);
+ if (res != 0)
+ erts_thr_fatal_error(res, "prepare timed");
+#endif
+}
+
ERTS_GLB_INLINE void erts_tse_set(erts_tse_t *ep)
{
#ifdef USE_THREADS
diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c
index 342e91e983..e9d7c91ac9 100644
--- a/erts/emulator/beam/utils.c
+++ b/erts/emulator/beam/utils.c
@@ -844,7 +844,6 @@ Uint32 make_hash(Eterm term_arg)
Eterm hash = 0;
unsigned op;
- /* Must not collide with the real tag_val_def's: */
#define MAKE_HASH_TUPLE_OP (FIRST_VACANT_TAG_DEF)
#define MAKE_HASH_TERM_ARRAY_OP (FIRST_VACANT_TAG_DEF+1)
#define MAKE_HASH_CDR_PRE_OP (FIRST_VACANT_TAG_DEF+2)
diff --git a/erts/emulator/drivers/unix/unix_efile.c b/erts/emulator/drivers/unix/unix_efile.c
index 06ba986044..46eccc6568 100644
--- a/erts/emulator/drivers/unix/unix_efile.c
+++ b/erts/emulator/drivers/unix/unix_efile.c
@@ -45,10 +45,10 @@
#endif
#if defined(__APPLE__) && defined(__MACH__) && !defined(__DARWIN__)
-#define DARWIN 1
+#define __DARWIN__ 1
#endif
-#if defined(DARWIN) || defined(HAVE_LINUX_FALLOC_H) || defined(HAVE_POSIX_FALLOCATE)
+#if defined(__DARWIN__) || defined(HAVE_LINUX_FALLOC_H) || defined(HAVE_POSIX_FALLOCATE)
#include <fcntl.h>
#endif
@@ -476,11 +476,11 @@ efile_fsync(Efile_error *errInfo, /* Where to return error codes. */
#ifdef NO_FSYNC
undefined fsync /* XXX: Really? */
#else
-#if defined(DARWIN) && defined(F_FULLFSYNC)
+#if defined(__DARWIN__) && defined(F_FULLFSYNC)
return check_error(fcntl(fd, F_FULLFSYNC), errInfo);
#else
return check_error(fsync(fd), errInfo);
-#endif /* DARWIN */
+#endif /* __DARWIN__ */
#endif /* NO_FSYNC */
}
@@ -962,7 +962,7 @@ efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd,
retval = len;
}
} while (len == SENDFILE_CHUNK_SIZE);
-#elif defined(DARWIN)
+#elif defined(__DARWIN__)
int retval;
off_t len;
do {
diff --git a/erts/emulator/hipe/hipe_bif0.c b/erts/emulator/hipe/hipe_bif0.c
index efbe951ce5..cc68e1f74d 100644
--- a/erts/emulator/hipe/hipe_bif0.c
+++ b/erts/emulator/hipe/hipe_bif0.c
@@ -1741,7 +1741,7 @@ BIF_RETTYPE hipe_bifs_check_crc_1(BIF_ALIST_1)
if (!term_to_Uint(BIF_ARG_1, &crc))
BIF_ERROR(BIF_P, BADARG);
- if (crc == HIPE_SYSTEM_CRC)
+ if (crc == HIPE_ERTS_CHECKSUM)
BIF_RET(am_true);
BIF_RET(am_false);
}
diff --git a/erts/emulator/hipe/hipe_bif_list.m4 b/erts/emulator/hipe/hipe_bif_list.m4
index b3bd5e4357..6aa0c9a32e 100644
--- a/erts/emulator/hipe/hipe_bif_list.m4
+++ b/erts/emulator/hipe/hipe_bif_list.m4
@@ -269,21 +269,23 @@ noproc_primop_interface_1(nbif_atomic_inc, hipe_atomic_inc)
/* BIFs that disable GC while trapping are called via a wrapper
* to reserve stack space for the "trap frame".
*/
-define(CFUN,`ifelse($1,term_to_binary_1,hipe_wrapper_term_to_binary_1,
-ifelse($1,term_to_binary_2,hipe_wrapper_term_to_binary_2,
-ifelse($1,binary_to_term_1,hipe_wrapper_binary_to_term_1,
-ifelse($1,binary_to_term_2,hipe_wrapper_binary_to_term_2,
-ifelse($1,binary_to_list_1,hipe_wrapper_binary_to_list_1,
-ifelse($1,binary_to_list_3,hipe_wrapper_binary_to_list_3,
-ifelse($1,bitstring_to_list_1,hipe_wrapper_bitstring_to_list_1,
-ifelse($1,list_to_binary_1,hipe_wrapper_list_to_binary_1,
-ifelse($1,iolist_to_binary_1,hipe_wrapper_iolist_to_binary_1,
-ifelse($1,binary_list_to_bin_1,hipe_wrapper_binary_list_to_bin_1,
-ifelse($1,list_to_bitstring_1,hipe_wrapper_list_to_bitstring_1,
-ifelse($1,send_2,hipe_wrapper_send_2,
-ifelse($1,send_3,hipe_wrapper_send_3,
-ifelse($1,ebif_bang_2,hipe_wrapper_ebif_bang_2,
-$1))))))))))))))')
+define(CFUN,`ifelse(
+$1, term_to_binary_1, hipe_wrapper_$1,
+$1, term_to_binary_2, hipe_wrapper_$1,
+$1, binary_to_term_1, hipe_wrapper_$1,
+$1, binary_to_term_2, hipe_wrapper_$1,
+$1, binary_to_list_1, hipe_wrapper_$1,
+$1, binary_to_list_3, hipe_wrapper_$1,
+$1, bitstring_to_list_1, hipe_wrapper_$1,
+$1, list_to_binary_1, hipe_wrapper_$1,
+$1, iolist_to_binary_1, hipe_wrapper_$1,
+$1, binary_list_to_bin_1, hipe_wrapper_$1,
+$1, list_to_bitstring_1, hipe_wrapper_$1,
+$1, send_2, hipe_wrapper_$1,
+$1, send_3, hipe_wrapper_$1,
+$1, ebif_bang_2, hipe_wrapper_$1,
+$1, maps_merge_2, hipe_wrapper_$1,
+$1)')
define(BIF_LIST,`standard_bif_interface_$3(nbif_$4, CFUN($4))')
include(TARGET/`erl_bif_list.h')
diff --git a/erts/emulator/hipe/hipe_mkliterals.c b/erts/emulator/hipe/hipe_mkliterals.c
index aa12df2932..dfa5313739 100644
--- a/erts/emulator/hipe/hipe_mkliterals.c
+++ b/erts/emulator/hipe/hipe_mkliterals.c
@@ -269,9 +269,6 @@ static const struct literal {
/* freason codes */
{ "FREASON_TRAP", TRAP },
- /* special Erlang constants */
- { "THE_NON_VALUE", (int)THE_NON_VALUE },
-
/* funs */
#ifdef HIPE
{ "EFE_NATIVE_ADDRESS", offsetof(struct erl_fun_entry, native_address) },
@@ -526,6 +523,8 @@ static const struct rts_param rts_params[] = {
{ 49, "P_MSG_FIRST", 1, offsetof(struct process, msg.first) },
{ 50, "P_MSG_SAVE", 1, offsetof(struct process, msg.save) },
{ 51, "P_CALLEE_EXP", 1, offsetof(struct process, hipe.u.callee_exp) },
+
+ { 52, "THE_NON_VALUE", 1, (int)THE_NON_VALUE },
};
#define NR_PARAMS ARRAY_SIZE(rts_params)
@@ -543,6 +542,8 @@ static void compute_crc(void)
crc_value = crc_update_int(crc_value, &literals[i].value);
crc_value &= 0x07FFFFFF;
literals_crc = crc_value;
+
+ crc_value = crc_init();
for (i = 0; i < NR_PARAMS; ++i)
if (rts_params[i].is_defined)
crc_value = crc_update_int(crc_value, &rts_params[i].value);
@@ -628,6 +629,7 @@ static int do_c(FILE *fp, const char* this_exe)
print_params(fp, c_define_param);
fprintf(fp, "#define HIPE_LITERALS_CRC %uU\n", literals_crc);
fprintf(fp, "#define HIPE_SYSTEM_CRC %uU\n", system_crc);
+ fprintf(fp, "#define HIPE_ERTS_CHECKSUM (HIPE_LITERALS_CRC ^ HIPE_SYSTEM_CRC)\n");
fprintf(fp, "\n");
fprintf(fp, "#define RTS_PARAMS_CASES");
print_params(fp, c_case_param);
@@ -645,12 +647,14 @@ static int do_e(FILE *fp, const char* this_exe)
fprintf(fp, "\n");
print_params(fp, e_define_param);
fprintf(fp, "\n");
+ fprintf(fp, "-define(HIPE_LITERALS_CRC, %u).\n", literals_crc);
if (is_xcomp) {
fprintf(fp, "-define(HIPE_SYSTEM_CRC, %u).\n", system_crc);
}
else {
fprintf(fp, "-define(HIPE_SYSTEM_CRC, hipe_bifs:system_crc()).\n");
}
+ fprintf(fp, "-define(HIPE_ERTS_CHECKSUM, (?HIPE_LITERALS_CRC bxor ?HIPE_SYSTEM_CRC)).\n");
return 0;
}
diff --git a/erts/emulator/test/erts_debug_SUITE.erl b/erts/emulator/test/erts_debug_SUITE.erl
index 3dd77eb920..35677f9953 100644
--- a/erts/emulator/test/erts_debug_SUITE.erl
+++ b/erts/emulator/test/erts_debug_SUITE.erl
@@ -139,23 +139,48 @@ flat_size_big_1(Term, Size0, Limit) when Size0 < Limit ->
flat_size_big_1(_, _, _) -> ok.
df(Config) when is_list(Config) ->
- ?line P0 = pps(),
- ?line PrivDir = ?config(priv_dir, Config),
- ?line ok = file:set_cwd(PrivDir),
- ?line erts_debug:df(?MODULE),
- ?line Beam = filename:join(PrivDir, ?MODULE_STRING++".dis"),
- ?line {ok,Bin} = file:read_file(Beam),
- ?line ok = io:put_chars(binary_to_list(Bin)),
- ?line ok = file:delete(Beam),
- ?line true = (P0 == pps()),
+ P0 = pps(),
+ PrivDir = ?config(priv_dir, Config),
+ ok = file:set_cwd(PrivDir),
+
+ AllLoaded = [M || {M,_} <- code:all_loaded()],
+ {Pid,Ref} = spawn_monitor(fun() -> df_smoke(AllLoaded) end),
+ receive
+ {'DOWN',Ref,process,Pid,Status} ->
+ normal = Status
+ after 20*1000 ->
+ %% Not finished (i.e. a slow computer). Stop now.
+ Pid ! stop,
+ receive
+ {'DOWN',Ref,process,Pid,Status} ->
+ normal = Status,
+ io:format("...")
+ end
+ end,
+ io:nl(),
+ _ = [_ = file:delete(atom_to_list(M) ++ ".dis") ||
+ M <- AllLoaded],
+
+ true = (P0 == pps()),
ok.
+df_smoke([M|Ms]) ->
+ io:format("~p", [M]),
+ erts_debug:df(M),
+ receive
+ stop ->
+ ok
+ after 0 ->
+ df_smoke(Ms)
+ end;
+df_smoke([]) -> ok.
+
pps() ->
{erlang:ports()}.
instructions(Config) when is_list(Config) ->
- ?line Is = erts_debug:instructions(),
- ?line _ = [list_to_atom(I) || I <- Is],
+ Is = erts_debug:instructions(),
+ _ = [list_to_atom(I) || I <- Is],
ok.
id(I) ->
diff --git a/erts/emulator/test/map_SUITE.erl b/erts/emulator/test/map_SUITE.erl
index 1a89101916..886ae7d516 100644
--- a/erts/emulator/test/map_SUITE.erl
+++ b/erts/emulator/test/map_SUITE.erl
@@ -2391,6 +2391,9 @@ check_keys_exist([K|Ks],M) ->
check_keys_exist(Ks,M).
t_bif_merge_and_check(Config) when is_list(Config) ->
+
+ io:format("rand:export_seed() -> ~p\n",[rand:export_seed()]),
+
%% simple disjunct ones
%% make sure all keys are unique
Kss = [[a,b,c,d],
@@ -2438,8 +2441,49 @@ t_bif_merge_and_check(Config) when is_list(Config) ->
M41 = maps:merge(M4,M1),
ok = check_key_values(KVs1 ++ [{d,5}] ++ KVs, M41),
+ [begin Ma = random_map(SzA, a),
+ Mb = random_map(SzB, b),
+ ok = merge_maps(Ma, Mb)
+ end || SzA <- [3,10,20,100,200,1000], SzB <- [3,10,20,100,200,1000]],
+
ok.
+% Generate random map with an average of Sz number of pairs: K -> {V,K}
+random_map(Sz, V) ->
+ random_map_insert(#{}, 0, V, Sz*2).
+
+random_map_insert(M0, K0, _, Sz) when K0 > Sz ->
+ M0;
+random_map_insert(M0, K0, V, Sz) ->
+ Key = K0 + rand:uniform(3),
+ random_map_insert(M0#{Key => {V,Key}}, Key, V, Sz).
+
+
+merge_maps(A, B) ->
+ AB = maps:merge(A, B),
+ %%io:format("A=~p\nB=~p\n",[A,B]),
+ maps_foreach(fun(K,VB) -> VB = maps:get(K, AB)
+ end, B),
+ maps_foreach(fun(K,VA) ->
+ case {maps:get(K, AB),maps:find(K, B)} of
+ {VA, error} -> ok;
+ {VB, {ok, VB}} -> ok
+ end
+ end, A),
+
+ maps_foreach(fun(K,V) ->
+ case {maps:find(K, A),maps:find(K, B)} of
+ {{ok, V}, error} -> ok;
+ {error, {ok, V}} -> ok;
+ {{ok,_}, {ok, V}} -> ok
+ end
+ end, AB),
+ ok.
+
+maps_foreach(Fun, Map) ->
+ maps:fold(fun(K,V,_) -> Fun(K,V) end, void, Map).
+
+
check_key_values([],_) -> ok;
check_key_values([{K,V}|KVs],M) ->
V = maps:get(K,M),
diff --git a/erts/emulator/test/match_spec_SUITE.erl b/erts/emulator/test/match_spec_SUITE.erl
index c6cc414bba..3f986ca2ed 100644
--- a/erts/emulator/test/match_spec_SUITE.erl
+++ b/erts/emulator/test/match_spec_SUITE.erl
@@ -170,12 +170,11 @@ test_1(Config) when is_list(Config) ->
[{['$1','$1'],[{is_atom, '$1'}],[kakalorum]}],
[{call, {?MODULE, f2, [a, a]}}]),
-% case tr0(fun() -> ?MODULE:f2(a, a) end,
-% {?MODULE, f2, 2},
-% [{['$1','$1'],[{is_atom, '$1'}],[{message, {process_dump}}]}]) of
-% [{trace, _, call, {?MODULE, f2, [a, a]}, Bin}] ->
-% erlang:display(binary_to_list(Bin))
-% end,
+ %% Verify that 'process_dump' can handle a matchstate on the stack.
+ tr(fun() -> fbinmatch(<<0>>, 0) end,
+ {?MODULE, f1, 1},
+ [{['_'],[],[{message, {process_dump}}]}],
+ [fun({trace, _, call, {?MODULE, f1, [0]}, _Bin}) -> true end]),
% Error cases
?line errchk([{['$1','$1'],[{is_atom, '$1'}],[{banka, kanin}]}]),
@@ -999,14 +998,14 @@ tr(Fun, MFA, TraceFlags, Pat, PatFlags, Expected0) ->
erlang:trace(P, true, TraceFlags),
erlang:trace_pattern(MFA, Pat, PatFlags),
lists:map(
- fun(X) ->
- list_to_tuple([trace, P | tuple_to_list(X)])
+ fun(X) when is_function(X,1) -> X;
+ (X) -> list_to_tuple([trace, P | tuple_to_list(X)])
end,
Expected0)
end).
tr(RunFun, ControlFun) ->
- P = spawn(?MODULE, runner, [self(), RunFun]),
+ P = spawn_link(?MODULE, runner, [self(), RunFun]),
collect(P, ControlFun(P)).
collect(P, TMs) ->
@@ -1025,18 +1024,33 @@ collect([]) ->
collect([TM | TMs]) ->
?t:format( "Expecting: ~p~n", [TM]),
receive
- M ->
- case if element(1, M) == trace_ts ->
- list_to_tuple(lists:reverse(
- tl(lists:reverse(tuple_to_list(M)))));
- true -> M
- end of
- TM ->
- ?t:format("Got: ~p~n", [M]),
- collect(TMs);
- _ ->
- ?t:format("Got unexpected: ~p~n", [M]),
- flush({got_unexpected,M})
+ M0 ->
+ M = case element(1, M0) of
+ trace_ts ->
+ list_to_tuple(lists:reverse(
+ tl(lists:reverse(tuple_to_list(M0)))));
+ _ -> M0
+ end,
+ case is_function(TM,1) of
+ true ->
+ case (catch TM(M)) of
+ true ->
+ ?t:format("Got: ~p~n", [M]),
+ collect(TMs);
+ _ ->
+ ?t:format("Got unexpected: ~p~n", [M]),
+ flush({got_unexpected,M})
+ end;
+
+ false ->
+ case M of
+ TM ->
+ ?t:format("Got: ~p~n", [M]),
+ collect(TMs);
+ _ ->
+ ?t:format("Got unexpected: ~p~n", [M]),
+ flush({got_unexpected,M})
+ end
end
end.
@@ -1116,6 +1130,10 @@ fn(X, Y) ->
fn(X, Y, Z) ->
[X, Y, Z].
+fbinmatch(<<Int, Rest/binary>>, Acc) ->
+ fbinmatch(Rest, [?MODULE:f1(Int) | Acc]);
+fbinmatch(<<>>, Acc) -> Acc.
+
id(X) ->
X.
diff --git a/erts/emulator/utils/make_alloc_types b/erts/emulator/utils/make_alloc_types
index 88f537ea09..925b9d5810 100755
--- a/erts/emulator/utils/make_alloc_types
+++ b/erts/emulator/utils/make_alloc_types
@@ -246,7 +246,7 @@ print DST "
print DST "#define ERTS_ALC_C_MIN ($c_no)\n\n";
-foreach my $c (keys(%c_tab)) {
+foreach my $c (sort keys(%c_tab)) {
push(@c_order, $c);
set_number($c_tab{$c}, $c_no);
print DST "#define ERTS_ALC_C_$c ($c_no)\n";
diff --git a/erts/emulator/utils/make_version b/erts/emulator/utils/make_version
index 3461dc1637..37bdff181a 100755
--- a/erts/emulator/utils/make_version
+++ b/erts/emulator/utils/make_version
@@ -59,7 +59,11 @@ print FILE <<EOF;
#define ERLANG_OTP_RELEASE "$release"
#define ERLANG_OTP_VERSION "$otp_version"
#define ERLANG_VERSION "$version"
-#define ERLANG_COMPILE_DATE "$time_str"
+#if ERTS_SAVED_COMPILE_TIME
+# define ERLANG_COMPILE_DATE "$time_str"
+#else
+# define ERLANG_COMPILE_DATE ""
+#endif
#define ERLANG_ARCHITECTURE "$architecture"
EOF
diff --git a/erts/emulator/utils/mkver.c b/erts/emulator/utils/mkver.c
index 96cd315a95..6641873712 100644
--- a/erts/emulator/utils/mkver.c
+++ b/erts/emulator/utils/mkver.c
@@ -35,8 +35,10 @@ int argc;
char** argv;
{
FILE *file;
+#if ERTS_SAVED_COMPILE_TIME
time_t now;
- char *cnow;
+#endif
+ char *cnow = "";
if (argc != 2) {
fprintf(stderr, "usage: mkver version\n");
@@ -48,9 +50,11 @@ char** argv;
exit(1);
}
+#if ERTS_SAVED_COMPILE_TIME
time(&now);
cnow = ctime(&now);
cnow[24] = '\0'; /* tidelipom */
+#endif
fprintf(file, "/* This file was created by mkver -- don't modify.*/\n");
fprintf(file, "#define ERLANG_VERSION \"%s\"\n", argv[1]);
fprintf(file, "#define ERLANG_COMPILE_DATE \"%s\"\n", cnow);
diff --git a/erts/include/internal/pthread/ethr_event.h b/erts/include/internal/pthread/ethr_event.h
index 74cfa68e16..deb4b29686 100644
--- a/erts/include/internal/pthread/ethr_event.h
+++ b/erts/include/internal/pthread/ethr_event.h
@@ -83,12 +83,22 @@ ETHR_INLINE_FUNC_NAME_(ethr_event_reset)(ethr_event *e)
#elif defined(ETHR_PTHREADS)
/* --- Posix mutex/cond pipe/select implementation of events ---------------- */
+#if defined(__APPLE__) && defined(__MACH__) && !defined(__DARWIN__)
+# define __DARWIN__ 1
+#endif
+
+#ifdef __DARWIN__
+typedef struct ethr_event_fdsets___ ethr_event_fdsets__;
+#endif
typedef struct {
ethr_atomic32_t state;
pthread_mutex_t mtx;
pthread_cond_t cnd;
int fd[2];
+#ifdef __DARWIN__
+ ethr_event_fdsets__ *fdsets;
+#endif
} ethr_event;
#define ETHR_EVENT_OFF_WAITER_SELECT__ ((ethr_sint32_t) -2)
@@ -148,6 +158,7 @@ ETHR_INLINE_FUNC_NAME_(ethr_event_reset)(ethr_event *e)
#endif
int ethr_event_init(ethr_event *e);
+int ethr_event_prepare_timed(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);
diff --git a/erts/include/internal/win/ethr_event.h b/erts/include/internal/win/ethr_event.h
index bf110e10f9..458565b9ea 100644
--- a/erts/include/internal/win/ethr_event.h
+++ b/erts/include/internal/win/ethr_event.h
@@ -56,6 +56,7 @@ ETHR_INLINE_FUNC_NAME_(ethr_event_reset)(ethr_event *e)
#endif
int ethr_event_init(ethr_event *e);
+int ethr_event_prepare_timed(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);
diff --git a/erts/lib_src/pthread/ethr_event.c b/erts/lib_src/pthread/ethr_event.c
index ba664236f6..0629b4dfcd 100644
--- a/erts/lib_src/pthread/ethr_event.c
+++ b/erts/lib_src/pthread/ethr_event.c
@@ -29,6 +29,13 @@
#include "config.h"
#endif
+#if defined(__APPLE__) && defined(__MACH__) && !defined(__DARWIN__)
+# define __DARWIN__ 1
+#endif
+#ifdef __DARWIN__
+# define _DARWIN_UNLIMITED_SELECT
+#endif
+
#include "ethread.h"
#undef ETHR_INCLUDE_MONOTONIC_CLOCK__
#define ETHR_INCLUDE_MONOTONIC_CLOCK__
@@ -56,6 +63,12 @@ ethr_event_init(ethr_event *e)
}
int
+ethr_event_prepare_timed(ethr_event *e)
+{
+ return 0;
+}
+
+int
ethr_event_destroy(ethr_event *e)
{
return 0;
@@ -171,6 +184,17 @@ return_event_on:
#include <errno.h>
#include <string.h>
+#ifdef __DARWIN__
+
+struct ethr_event_fdsets___ {
+ fd_set *rsetp;
+ fd_set *esetp;
+ size_t mem_size;
+ fd_mask mem[1];
+};
+
+#endif
+
static void
setup_nonblocking_pipe(ethr_event *e)
{
@@ -188,6 +212,35 @@ setup_nonblocking_pipe(ethr_event *e)
flgs = fcntl(e->fd[1], F_GETFL, 0);
fcntl(e->fd[1], F_SETFL, flgs | O_NONBLOCK);
+
+#ifndef __DARWIN__
+ if (e->fd[0] >= FD_SETSIZE)
+ ETHR_FATAL_ERROR__(ENOTSUP);
+#else
+ {
+ int nmasks;
+ ethr_event_fdsets__ *fdsets;
+ size_t mem_size;
+
+ nmasks = (e->fd[0]+NFDBITS)/NFDBITS;
+ mem_size = 2*nmasks*sizeof(fd_mask);
+ if (mem_size < 2*sizeof(fd_set)) {
+ mem_size = 2*sizeof(fd_set);
+ nmasks = mem_size/(2*sizeof(fd_mask));
+ }
+
+ fdsets = malloc(sizeof(ethr_event_fdsets__)
+ + mem_size
+ - sizeof(fd_mask));
+ if (!fdsets)
+ ETHR_FATAL_ERROR__(ENOMEM);
+ fdsets->rsetp = (fd_set *) (char *) &fdsets->mem[0];
+ fdsets->esetp = (fd_set *) (char *) &fdsets->mem[nmasks];
+ fdsets->mem_size = mem_size;
+ e->fdsets = fdsets;
+ }
+#endif
+
ETHR_MEMBAR(ETHR_StoreStore);
}
@@ -252,6 +305,19 @@ ethr_event_init(ethr_event *e)
e->fd[0] = e->fd[1] = ETHR_EVENT_INVALID_FD__;
+#ifdef __DARWIN__
+ e->fdsets = NULL;
+#endif
+
+ return 0;
+}
+
+int
+ethr_event_prepare_timed(ethr_event *e)
+{
+ if (e->fd[0] == ETHR_EVENT_INVALID_FD__)
+ setup_nonblocking_pipe(e);
+
return 0;
}
@@ -263,13 +329,14 @@ ethr_event_destroy(ethr_event *e)
close(e->fd[0]);
close(e->fd[1]);
}
+#ifdef __DARWIN__
+ if (e->fdsets)
+ free(e->fdsets);
+#endif
res = pthread_mutex_destroy(&e->mtx);
if (res != 0)
return res;
- res = pthread_cond_destroy(&e->cnd);
- if (res != 0)
- return res;
- return 0;
+ return pthread_cond_destroy(&e->cnd);
}
static ETHR_INLINE int
@@ -403,8 +470,10 @@ wait__(ethr_event *e, int spincount, ethr_sint64_t timeout)
int fd;
int sres;
ssize_t rres;
- fd_set rset;
- fd_set eset;
+#ifndef __DARWIN__
+ fd_set rset, eset;
+#endif
+ fd_set *rsetp, *esetp;
struct timeval select_timeout;
#ifdef ETHR_HAVE_ETHR_GET_MONOTONIC_TIME
@@ -457,12 +526,22 @@ wait__(ethr_event *e, int spincount, ethr_sint64_t timeout)
ETHR_ASSERT(act == val);
}
+
+#ifdef __DARWIN__
+ rsetp = e->fdsets->rsetp;
+ esetp = e->fdsets->esetp;
+ memset((void *) &e->fdsets->mem[0], 0, e->fdsets->mem_size);
+#else
FD_ZERO(&rset);
- FD_SET(fd, &rset);
FD_ZERO(&eset);
- FD_SET(fd, &eset);
+ rsetp = &rset;
+ esetp = &eset;
+#endif
+
+ FD_SET(fd, rsetp);
+ FD_SET(fd, esetp);
- sres = select(fd + 1, &rset, NULL, &eset, &select_timeout);
+ sres = select(fd + 1, rsetp, NULL, esetp, &select_timeout);
if (sres == 0)
res = ETIMEDOUT;
else {
diff --git a/erts/lib_src/win/ethr_event.c b/erts/lib_src/win/ethr_event.c
index c88c8784a2..6951a216c5 100644
--- a/erts/lib_src/win/ethr_event.c
+++ b/erts/lib_src/win/ethr_event.c
@@ -47,6 +47,12 @@ ethr_event_init(ethr_event *e)
}
int
+ethr_event_prepare_timed(ethr_event *e)
+{
+ return 0;
+}
+
+int
ethr_event_destroy(ethr_event *e)
{
BOOL res = CloseHandle(e->handle);