aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/emulator/beam/break.c4
-rw-r--r--erts/emulator/beam/erl_init.c1
-rw-r--r--erts/emulator/beam/erl_thr_progress.c1
-rw-r--r--erts/emulator/beam/external.c25
-rw-r--r--erts/emulator/beam/io.c27
-rw-r--r--erts/emulator/sys/unix/erl_unix_sys.h1
-rw-r--r--erts/emulator/sys/unix/sys.c24
7 files changed, 56 insertions, 27 deletions
diff --git a/erts/emulator/beam/break.c b/erts/emulator/beam/break.c
index 0ddf7f4e6d..298b30fff3 100644
--- a/erts/emulator/beam/break.c
+++ b/erts/emulator/beam/break.c
@@ -684,7 +684,7 @@ erl_crash_dump_v(char *file, int line, char* fmt, va_list args)
crash dump. */
erts_thr_progress_fatal_error_block(&tpd_buf);
-#ifdef ERTS_THR_HAVE_SIG_FUNCS
+#ifdef ERTS_SYS_SUSPEND_SIGNAL
/*
* We suspend all scheduler threads so that we can dump some
* data about the currently running processes and scheduler data.
@@ -818,7 +818,7 @@ erl_crash_dump_v(char *file, int line, char* fmt, va_list args)
#ifdef ERTS_SMP
-#if defined(ERTS_THR_HAVE_SIG_FUNCS)
+#ifdef ERTS_SYS_SUSPEND_SIGNAL
/* We resume all schedulers so that we are in a known safe state
when we write the rest of the crash dump */
diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c
index b4d5bf8fb6..8b85613e18 100644
--- a/erts/emulator/beam/erl_init.c
+++ b/erts/emulator/beam/erl_init.c
@@ -2134,6 +2134,7 @@ erl_start(int argc, char **argv)
init_break_handler();
if (replace_intr)
erts_replace_intr();
+ sys_init_suspend_handler();
#endif
boot_argc = argc - i; /* Number of arguments to init */
diff --git a/erts/emulator/beam/erl_thr_progress.c b/erts/emulator/beam/erl_thr_progress.c
index 7b06fd840f..232a2d0fdc 100644
--- a/erts/emulator/beam/erl_thr_progress.c
+++ b/erts/emulator/beam/erl_thr_progress.c
@@ -700,6 +700,7 @@ leader_update(ErtsThrPrgrData *tpd)
tpd->leader_state.chk_next_ix = no_managed;
erts_atomic32_set_nob(&intrnl->misc.data.umrefc_ix.current,
(erts_aint32_t) new_umrefc_ix);
+ tpd->leader_state.umrefc_ix.current = new_umrefc_ix;
ETHR_MEMBAR(ETHR_StoreLoad);
refc = erts_atomic_read_nob(&intrnl->umrefc[umrefc_ix].refc);
ASSERT(refc >= 0);
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c
index ffe3303796..31ec12cccf 100644
--- a/erts/emulator/beam/external.c
+++ b/erts/emulator/beam/external.c
@@ -1206,6 +1206,7 @@ typedef struct B2TContext_t {
} u;
} B2TContext;
+static B2TContext* b2t_export_context(Process*, B2TContext* src);
static uLongf binary2term_uncomp_size(byte* data, Sint size)
{
@@ -1238,7 +1239,7 @@ static uLongf binary2term_uncomp_size(byte* data, Sint size)
static ERTS_INLINE int
binary2term_prepare(ErtsBinary2TermState *state, byte *data, Sint data_size,
- B2TContext* ctx)
+ B2TContext** ctxp, Process* p)
{
byte *bytes = data;
Sint size = data_size;
@@ -1252,8 +1253,8 @@ binary2term_prepare(ErtsBinary2TermState *state, byte *data, Sint data_size,
size--;
if (size < 5 || *bytes != COMPRESSED) {
state->extp = bytes;
- if (ctx)
- ctx->state = B2TSizeInit;
+ if (ctxp)
+ (*ctxp)->state = B2TSizeInit;
}
else {
uLongf dest_len = (Uint32) get_int32(bytes+1);
@@ -1270,16 +1271,26 @@ binary2term_prepare(ErtsBinary2TermState *state, byte *data, Sint data_size,
return -1;
}
state->extp = erts_alloc(ERTS_ALC_T_EXT_TERM_DATA, dest_len);
- ctx->reds -= dest_len;
+ if (ctxp)
+ (*ctxp)->reds -= dest_len;
}
state->exttmp = 1;
- if (ctx) {
+ if (ctxp) {
+ /*
+ * Start decompression by exporting trap context
+ * so we don't have to deal with deep-copying z_stream.
+ */
+ B2TContext* ctx = b2t_export_context(p, *ctxp);
+ ASSERT(state = &(*ctxp)->b2ts);
+ state = &ctx->b2ts;
+
if (erl_zlib_inflate_start(&ctx->u.uc.stream, bytes, size) != Z_OK)
return -1;
ctx->u.uc.dbytes = state->extp;
ctx->u.uc.dleft = dest_len;
ctx->state = B2TUncompressChunk;
+ *ctxp = ctx;
}
else {
uLongf dlen = dest_len;
@@ -1323,7 +1334,7 @@ erts_binary2term_prepare(ErtsBinary2TermState *state, byte *data, Sint data_size
{
Sint res;
- if (binary2term_prepare(state, data, data_size, NULL) < 0 ||
+ if (binary2term_prepare(state, data, data_size, NULL, NULL) < 0 ||
(res=decoded_size(state->extp, state->extp + state->extsize, 0, NULL)) < 0) {
if (state->exttmp)
@@ -1469,7 +1480,7 @@ static BIF_RETTYPE binary_to_term_int(Process* p, Uint32 flags, Eterm bin, Binar
if (ctx->aligned_alloc) {
ctx->reds -= bin_size / 8;
}
- if (binary2term_prepare(&ctx->b2ts, bytes, bin_size, ctx) < 0) {
+ if (binary2term_prepare(&ctx->b2ts, bytes, bin_size, &ctx, p) < 0) {
ctx->state = B2TBadArg;
}
break;
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index fbcb0c31fc..538015b242 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -5767,16 +5767,20 @@ deliver_term_check_port(ErlDrvTermData port_id, Eterm *connected_p)
ErtsThrPrgrDelayHandle dhndl = erts_thr_progress_unmanaged_delay();
#endif
erts_aint32_t state;
+ int res = 1;
Port *prt = erts_port_lookup_raw((Eterm) port_id);
- if (!prt)
- return -1;
+ if (!prt) {
+ res = -1;
+ goto done;
+ }
state = erts_atomic32_read_nob(&prt->state);
if (state & (ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP
| ERTS_PORT_SFLG_CLOSING)) {
if (state & ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP)
- return -1;
+ res = -1;
else
- return 0;
+ res = 0;
+ goto done;
}
if (connected_p) {
#ifdef ERTS_SMP
@@ -5785,22 +5789,25 @@ deliver_term_check_port(ErlDrvTermData port_id, Eterm *connected_p)
#endif
*connected_p = ERTS_PORT_GET_CONNECTED(prt);
}
+
+done:
+
#ifdef ERTS_SMP
if (dhndl != ERTS_THR_PRGR_DHANDLE_MANAGED) {
+ ERTS_SMP_LC_ASSERT(!prt || !erts_lc_is_port_locked(prt));
erts_thr_progress_unmanaged_continue(dhndl);
ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);
- }
+ } else
#endif
- ERTS_SMP_LC_ASSERT(dhndl == ERTS_THR_PRGR_DHANDLE_MANAGED
- ? erts_lc_is_port_locked(prt)
- : !erts_lc_is_port_locked(prt));
- return 1;
+ ERTS_SMP_LC_ASSERT(res != 1 || erts_lc_is_port_locked(prt));
+
+ return res;
}
int erl_drv_output_term(ErlDrvTermData port_id, ErlDrvTermData* data, int len)
{
/* May be called from arbitrary thread */
- Eterm connected;
+ Eterm connected = NIL; /* Shut up faulty warning... */
int res = deliver_term_check_port(port_id, &connected);
if (res <= 0)
return res;
diff --git a/erts/emulator/sys/unix/erl_unix_sys.h b/erts/emulator/sys/unix/erl_unix_sys.h
index 8d4e98bf3a..b55180c509 100644
--- a/erts/emulator/sys/unix/erl_unix_sys.h
+++ b/erts/emulator/sys/unix/erl_unix_sys.h
@@ -311,6 +311,7 @@ extern SIGFUNC sys_signal(int, SIGFUNC);
extern void sys_sigrelease(int);
extern void sys_sigblock(int);
extern void sys_stop_cat(void);
+extern void sys_init_suspend_handler(void);
/*
* Handling of floating point exceptions.
diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c
index d94b37430e..cbd47db37f 100644
--- a/erts/emulator/sys/unix/sys.c
+++ b/erts/emulator/sys/unix/sys.c
@@ -226,8 +226,10 @@ static erts_smp_atomic_t sys_misc_mem_sz;
static void smp_sig_notify(char c);
static int sig_notify_fds[2] = {-1, -1};
+#if !defined(ETHR_UNUSABLE_SIGUSRX) && defined(ERTS_THR_HAVE_SIG_FUNCS)
static int sig_suspend_fds[2] = {-1, -1};
#define ERTS_SYS_SUSPEND_SIGNAL SIGUSR2
+#endif
#endif
@@ -872,7 +874,7 @@ sigusr1_exit(void)
#else
-#ifdef ERTS_SMP
+#ifdef ERTS_SYS_SUSPEND_SIGNAL
void
sys_thr_suspend(erts_tid_t tid) {
erts_thr_kill(tid, ERTS_SYS_SUSPEND_SIGNAL);
@@ -900,7 +902,7 @@ static RETSIGTYPE user_signal1(int signum)
#endif
}
-#ifdef ERTS_SMP
+#ifdef ERTS_SYS_SUSPEND_SIGNAL
#if (defined(SIG_SIGSET) || defined(SIG_SIGNAL))
static RETSIGTYPE suspend_signal(void)
#else
@@ -913,7 +915,7 @@ static RETSIGTYPE suspend_signal(int signum)
res = read(sig_suspend_fds[0], buf, sizeof(int));
} while (res < 0 && errno == EINTR);
}
-#endif /* #ifdef ERTS_SMP */
+#endif /* #ifdef ERTS_SYS_SUSPEND_SIGNAL */
#endif /* #ifndef ETHR_UNUSABLE_SIGUSRX */
@@ -966,13 +968,17 @@ void init_break_handler(void)
sys_signal(SIGINT, request_break);
#ifndef ETHR_UNUSABLE_SIGUSRX
sys_signal(SIGUSR1, user_signal1);
-#ifdef ERTS_SMP
- sys_signal(ERTS_SYS_SUSPEND_SIGNAL, suspend_signal);
-#endif /* #ifdef ERTS_SMP */
#endif /* #ifndef ETHR_UNUSABLE_SIGUSRX */
sys_signal(SIGQUIT, do_quit);
}
+void sys_init_suspend_handler(void)
+{
+#ifdef ERTS_SYS_SUSPEND_SIGNAL
+ sys_signal(ERTS_SYS_SUSPEND_SIGNAL, suspend_signal);
+#endif
+}
+
int sys_max_files(void)
{
return(max_files);
@@ -990,7 +996,7 @@ static void block_signals(void)
#endif /* #ifndef ETHR_UNUSABLE_SIGUSRX */
#endif /* #ifndef ERTS_SMP */
-#if defined(ERTS_SMP) && !defined(ETHR_UNUSABLE_SIGUSRX)
+#ifdef ERTS_SYS_SUSPEND_SIGNAL
sys_sigblock(ERTS_SYS_SUSPEND_SIGNAL);
#endif
@@ -1009,7 +1015,7 @@ static void unblock_signals(void)
#endif /* #ifndef ETHR_UNUSABLE_SIGUSRX */
#endif /* #ifndef ERTS_SMP */
-#if defined(ERTS_SMP) && !defined(ETHR_UNUSABLE_SIGUSRX)
+#ifdef ERTS_SYS_SUSPEND_SIGNAL
sys_sigrelease(ERTS_SYS_SUSPEND_SIGNAL);
#endif
@@ -3248,12 +3254,14 @@ init_smp_sig_notify(void)
static void
init_smp_sig_suspend(void) {
+#ifdef ERTS_SYS_SUSPEND_SIGNAL
if (pipe(sig_suspend_fds) < 0) {
erts_exit(ERTS_ABORT_EXIT,
"Failed to create sig_suspend pipe: %s (%d)\n",
erl_errno_id(errno),
errno);
}
+#endif
}
#ifdef __DARWIN__