diff options
Diffstat (limited to 'erts')
-rw-r--r-- | erts/emulator/beam/bif.c | 36 | ||||
-rw-r--r-- | erts/emulator/beam/dist.c | 27 | ||||
-rw-r--r-- | erts/emulator/beam/dist.h | 2 |
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); |