aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/emulator/beam/bif.c36
-rw-r--r--erts/emulator/beam/dist.c27
-rw-r--r--erts/emulator/beam/dist.h2
3 files changed, 50 insertions, 15 deletions
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index a71907505c..eb44d5632a 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -1302,9 +1302,17 @@ static BIF_RETTYPE send_exit_signal_bif(Process *c_p, Eterm id, Eterm reason, in
ERTS_BIF_PREP_RET(ret_val, am_true); /* Old incarnation of this node... */
else {
int code;
- ErtsDSigData dsd;
+ ErtsSendContext ctx;
- code = erts_dsig_prepare(&dsd, dep, c_p, ERTS_PROC_LOCK_MAIN,
+ ctx.suspend = !0;
+ ctx.connect = !0;
+ ctx.deref_dep = 0;
+ ctx.return_term = am_true;
+ ctx.dss.reds = (Sint) (ERTS_BIF_REDS_LEFT(c_p) * TERM_TO_BINARY_LOOP_FACTOR);
+ ctx.dss.phase = ERTS_DSIG_SEND_PHASE_INIT;
+ ctx.dss.from = c_p->common.id;
+
+ code = erts_dsig_prepare(&ctx.dsd, dep, c_p, ERTS_PROC_LOCK_MAIN,
ERTS_DSP_NO_LOCK, 0, 1);
switch (code) {
case ERTS_DSIG_PREP_NOT_ALIVE:
@@ -1313,11 +1321,29 @@ static BIF_RETTYPE send_exit_signal_bif(Process *c_p, Eterm id, Eterm reason, in
break;
case ERTS_DSIG_PREP_PENDING:
case ERTS_DSIG_PREP_CONNECTED:
- code = erts_dsig_send_exit2(&dsd, c_p->common.id, id, reason);
- if (code == ERTS_DSIG_SEND_YIELD)
+ code = erts_dsig_send_exit2(&ctx, c_p->common.id, id, reason);
+ switch (code) {
+ case ERTS_DSIG_SEND_YIELD:
ERTS_BIF_PREP_YIELD_RETURN(ret_val, c_p, am_true);
- else
+ break;
+ case ERTS_DSIG_SEND_CONTINUE:
+ BUMP_ALL_REDS(c_p);
+ erts_set_gc_state(c_p, 0);
+ ERTS_BIF_PREP_TRAP1(ret_val, &dsend_continue_trap_export, c_p,
+ erts_dsend_export_trap_context(c_p, &ctx));
+ break;
+ case ERTS_DSIG_SEND_OK:
ERTS_BIF_PREP_RET(ret_val, am_true);
+ break;
+ case ERTS_DSIG_SEND_TOO_LRG:
+ erts_set_gc_state(c_p, 1);
+ ERTS_BIF_PREP_ERROR(ret_val, c_p, SYSTEM_LIMIT);
+ break;
+ default:
+ ASSERT(! "Invalid dsig send exit2 result");
+ ERTS_BIF_PREP_ERROR(ret_val, c_p, EXC_INTERNAL_ERROR);
+ break;
+ }
break;
default:
ASSERT(! "Invalid dsig prepare result");
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index 78674848a1..749760a1b3 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -178,6 +178,7 @@ static Export *dist_ctrl_put_data_trap;
/* forward declarations */
static int dsig_send_exit(ErtsDSigData* dsdp, Eterm ctl, Eterm msg, Eterm from, int force_busy);
+static int dsig_send_exit_ctx(ErtsSendContext *ctx, Eterm ctl, Eterm msg);
static int dsig_send_ctl(ErtsDSigData* dsdp, Eterm ctl, int force_busy);
static void send_nodes_mon_msgs(Process *, Eterm, Eterm, Eterm, Eterm);
static void init_nodes_monitors(void);
@@ -1276,25 +1277,22 @@ erts_dsig_send_exit(ErtsDSigData *dsdp, Eterm from, Eterm local, Eterm remote, E
}
int
-erts_dsig_send_exit2(ErtsDSigData *dsdp, Eterm local, Eterm remote, Eterm reason)
+erts_dsig_send_exit2(ErtsSendContext *ctx, Eterm local, Eterm remote, Eterm reason)
{
- DeclareTmpHeapNoproc(ctl_heap,5);
int res;
Eterm ctl, msg;
- UseTmpHeapNoproc(5);
- if (dsdp->dep->flags & DFLAG_EXIT_PAYLOAD) {
- ctl = TUPLE3(&ctl_heap[0],
+ if (ctx->dsd.dep->flags & DFLAG_EXIT_PAYLOAD) {
+ ctl = TUPLE3(&ctx->ctl_heap[0],
make_small(DOP_PAYLOAD_EXIT2), local, remote);
msg = reason;
} else {
- ctl = TUPLE4(&ctl_heap[0],
+ ctl = TUPLE4(&ctx->ctl_heap[0],
make_small(DOP_EXIT2), local, remote, reason);
msg = THE_NON_VALUE;
}
- res = dsig_send_exit(dsdp, ctl, msg, local, 0);
- UnUseTmpHeapNoproc(5);
+ res = dsig_send_exit_ctx(ctx, ctl, msg);
return res;
}
@@ -2162,7 +2160,7 @@ static int dsig_send_exit(ErtsDSigData* dsdp, Eterm ctl, Eterm msg, Eterm from,
ctx.msg = msg;
ctx.from = from;
ctx.force_busy = force_busy;
- ctx.force_encode = 1;
+ ctx.force_encode = force_busy;
ctx.phase = ERTS_DSIG_SEND_PHASE_INIT;
ctx.reds = 1; /* provoke assert below (no reduction count with force_encode) */
ret = erts_dsig_send(dsdp, &ctx);
@@ -2170,6 +2168,17 @@ static int dsig_send_exit(ErtsDSigData* dsdp, Eterm ctl, Eterm msg, Eterm from,
return ret;
}
+static int dsig_send_exit_ctx(ErtsSendContext *ctx, Eterm ctl, Eterm msg)
+{
+ int ret;
+ ctx->dss.ctl = ctl;
+ ctx->dss.msg = msg;
+ ctx->dss.force_busy = 0;
+ ctx->dss.force_encode = 0;
+ ret = erts_dsig_send(&ctx->dsd, &ctx->dss);
+ return ret;
+}
+
static int dsig_send_ctl(ErtsDSigData* dsdp, Eterm ctl, int force_busy)
{
struct erts_dsig_send_context ctx;
diff --git a/erts/emulator/beam/dist.h b/erts/emulator/beam/dist.h
index 034b75df38..8ea214a0f2 100644
--- a/erts/emulator/beam/dist.h
+++ b/erts/emulator/beam/dist.h
@@ -415,7 +415,7 @@ extern int erts_dsig_send_unlink(ErtsDSigData *, Eterm, Eterm);
extern int erts_dsig_send_reg_msg(Eterm, Eterm, ErtsSendContext*);
extern int erts_dsig_send_group_leader(ErtsDSigData *, Eterm, Eterm);
extern int erts_dsig_send_exit(ErtsDSigData *, Eterm, Eterm, Eterm, Eterm);
-extern int erts_dsig_send_exit2(ErtsDSigData *, Eterm, Eterm, Eterm);
+extern int erts_dsig_send_exit2(ErtsSendContext *, Eterm, Eterm, Eterm);
extern int erts_dsig_send_demonitor(ErtsDSigData *, Eterm, Eterm, Eterm, int);
extern int erts_dsig_send_monitor(ErtsDSigData *, Eterm, Eterm, Eterm);
extern int erts_dsig_send_m_exit(ErtsDSigData *, Eterm, Eterm, Eterm, Eterm, Eterm);