From 337919abe6ed9a97e15d5f471ef8f79d44cb8363 Mon Sep 17 00:00:00 2001
From: Sverker Eriksson
Date: Mon, 26 Feb 2018 15:36:34 +0100
Subject: erts,kernel: Add erts_internal:get_dflags/0
for kernel to ask erts about distribution flags
and keep this info in one place.
---
erts/emulator/beam/atom.names | 1 +
erts/emulator/beam/bif.tab | 1 +
erts/emulator/beam/dist.c | 21 +++++++++++++++++++
erts/emulator/beam/dist.h | 37 +++++++++++++++++++++++++++------
erts/emulator/beam/erl_node_tables.c | 2 +-
erts/preloaded/ebin/erts_internal.beam | Bin 13964 -> 14100 bytes
erts/preloaded/src/erts_internal.erl | 5 +++++
7 files changed, 60 insertions(+), 7 deletions(-)
(limited to 'erts')
diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names
index 42a368cdd8..b40d9a325b 100644
--- a/erts/emulator/beam/atom.names
+++ b/erts/emulator/beam/atom.names
@@ -250,6 +250,7 @@ atom error_handler
atom error_logger
atom erts_code_purger
atom erts_debug
+atom erts_dflags
atom erts_internal
atom ets
atom ETS_TRANSFER='ETS-TRANSFER'
diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab
index 0d1166f6ed..be653ee2a0 100644
--- a/erts/emulator/beam/bif.tab
+++ b/erts/emulator/beam/bif.tab
@@ -690,6 +690,7 @@ bif erlang:iolist_to_iovec/1
# New in 21.0
#
+bif erts_internal:get_dflags/0
bif erts_internal:new_connection/1
bif erts_internal:abort_connection/2
bif erts_internal:map_next/3
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index 30390cdb5e..6f122273dc 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -641,6 +641,13 @@ trap_function(Eterm func, int arity)
return erts_export_put(am_erlang, func, arity);
}
+/*
+ * Sync with dist_util.erl:
+ *
+ * -record(erts_dflags, {default, mandatory, addable, rejectable}).
+ */
+static Eterm erts_dflags_record;
+
void init_dist(void)
{
init_nodes_monitors();
@@ -657,6 +664,15 @@ void init_dist(void)
dist_ctrl_put_data_trap = erts_export_put(am_erts_internal,
am_dist_ctrl_put_data,
2);
+ {
+ Eterm* hp = erts_alloc(ERTS_ALC_T_LITERAL, (1+5)*sizeof(Eterm));
+ erts_dflags_record = TUPLE5(hp, am_erts_dflags,
+ make_small(DFLAG_DIST_DEFAULT),
+ make_small(DFLAG_DIST_MANDATORY),
+ make_small(DFLAG_DIST_ADDABLE),
+ make_small(DFLAG_DIST_REJECTABLE));
+ erts_set_literal_tag(&erts_dflags_record, hp, (1+5));
+ }
}
#define ErtsDistOutputBuf2Binary(OB) \
@@ -3506,6 +3522,11 @@ BIF_RETTYPE setnode_3(BIF_ALIST_3)
goto done;
}
+BIF_RETTYPE erts_internal_get_dflags_0(BIF_ALIST_0)
+{
+ return erts_dflags_record;
+}
+
BIF_RETTYPE erts_internal_new_connection_1(BIF_ALIST_1)
{
DistEntry* dep;
diff --git a/erts/emulator/beam/dist.h b/erts/emulator/beam/dist.h
index ea4697815f..202457bb3b 100644
--- a/erts/emulator/beam/dist.h
+++ b/erts/emulator/beam/dist.h
@@ -40,26 +40,51 @@
#define DFLAG_UNICODE_IO 0x1000
#define DFLAG_DIST_HDR_ATOM_CACHE 0x2000
#define DFLAG_SMALL_ATOM_TAGS 0x4000
-#define DFLAG_INTERNAL_TAGS 0x8000
+#define DFLAG_INTERNAL_TAGS 0x8000 /* used by ETS 'compressed' option */
#define DFLAG_UTF8_ATOMS 0x10000
#define DFLAG_MAP_TAG 0x20000
#define DFLAG_BIG_CREATION 0x40000
#define DFLAG_SEND_SENDER 0x80000
-#define DFLAG_NO_MAGIC 0x100000
+#define DFLAG_NO_MAGIC 0x100000 /* internal for pending connection */
-/* Mandatory flags for distribution (sync with dist_util.erl) */
+/* Mandatory flags for distribution */
#define DFLAG_DIST_MANDATORY (DFLAG_EXTENDED_REFERENCES \
| DFLAG_EXTENDED_PIDS_PORTS \
| DFLAG_UTF8_ATOMS \
| DFLAG_NEW_FUN_TAGS)
-/* Additional optimistic flags when encoding toward pending connection */
-#define DFLAG_DIST_HOPEFULLY (DFLAG_NO_MAGIC \
- | DFLAG_EXPORT_PTR_TAG \
+/*
+ * Additional optimistic flags when encoding toward pending connection.
+ * If remote node does not supporting these (erl_interface)
+ * then we will need to transcode all messages enqueued before
+ * connection setup was finished.
+ */
+#define DFLAG_DIST_HOPEFULLY (DFLAG_EXPORT_PTR_TAG \
| DFLAG_BIT_BINARIES \
| DFLAG_DIST_MONITOR \
| DFLAG_DIST_MONITOR_NAME)
+/* Our preferred set of flags. Used for connection setup handshake */
+#define DFLAG_DIST_DEFAULT (DFLAG_DIST_MANDATORY | DFLAG_DIST_HOPEFULLY \
+ | DFLAG_FUN_TAGS \
+ | DFLAG_NEW_FLOATS \
+ | DFLAG_UNICODE_IO \
+ | DFLAG_DIST_HDR_ATOM_CACHE \
+ | DFLAG_SMALL_ATOM_TAGS \
+ | DFLAG_UTF8_ATOMS \
+ | DFLAG_MAP_TAG \
+ | DFLAG_BIG_CREATION \
+ | DFLAG_SEND_SENDER)
+
+/* Flags addable by local distr implementations */
+#define DFLAG_DIST_ADDABLE DFLAG_DIST_DEFAULT
+
+/* Flags rejectable by local distr implementation */
+#define DFLAG_DIST_REJECTABLE (DFLAG_DIST_HDR_ATOM_CACHE \
+ | DFLAG_HIDDEN_ATOM_CACHE \
+ | DFLAG_ATOM_CACHE)
+
+
/* All flags that should be enabled when term_to_binary/1 is used. */
#define TERM_TO_BINARY_DFLAGS (DFLAG_EXTENDED_REFERENCES \
| DFLAG_NEW_FUN_TAGS \
diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c
index eaf133f5c0..088b087ebb 100644
--- a/erts/emulator/beam/erl_node_tables.c
+++ b/erts/emulator/beam/erl_node_tables.c
@@ -628,7 +628,7 @@ erts_set_dist_entry_pending(DistEntry *dep)
erts_no_of_not_connected_dist_entries--;
dep->status = ERTS_DE_SFLG_PENDING;
- dep->flags = (DFLAG_DIST_MANDATORY | DFLAG_DIST_HOPEFULLY);
+ dep->flags = (DFLAG_DIST_MANDATORY | DFLAG_DIST_HOPEFULLY | DFLAG_NO_MAGIC);
dep->connection_id = (dep->connection_id + 1) & ERTS_DIST_CON_ID_MASK;
dep->prev = NULL;
diff --git a/erts/preloaded/ebin/erts_internal.beam b/erts/preloaded/ebin/erts_internal.beam
index 7d2edd9845..7206b0415d 100644
Binary files a/erts/preloaded/ebin/erts_internal.beam and b/erts/preloaded/ebin/erts_internal.beam differ
diff --git a/erts/preloaded/src/erts_internal.erl b/erts/preloaded/src/erts_internal.erl
index a083e9ac2f..291a8e8fa8 100644
--- a/erts/preloaded/src/erts_internal.erl
+++ b/erts/preloaded/src/erts_internal.erl
@@ -63,6 +63,7 @@
-export([dist_ctrl_put_data/2]).
+-export([get_dflags/0]).
-export([new_connection/1]).
-export([abort_connection/2]).
@@ -510,6 +511,10 @@ dist_ctrl_put_data(DHandle, IoList) ->
end.
+-spec erts_internal:get_dflags() -> {erts_dflags,integer(),integer(),integer(),integer()}.
+get_dflags() ->
+ erlang:nif_error(undefined).
+
-spec erts_internal:new_connection(Node) -> ConnId when
Node :: atom(),
ConnId :: {integer(), erlang:dist_handle()}.
--
cgit v1.2.3
From 7fb3ed7d2731050186eb5224fe8e6050e4909341 Mon Sep 17 00:00:00 2001
From: Sverker Eriksson
Date: Mon, 26 Feb 2018 20:40:51 +0100
Subject: erts,kernel: Add dist_util:strict_order_flags/0
to replace DFLAGS_STRICT_ORDER_DELIVERY
and remove that compile time dependency.
---
erts/doc/src/alt_dist.xml | 11 +++++------
erts/doc/src/erl_dist_protocol.xml | 7 +++----
erts/emulator/beam/dist.c | 12 +++++++-----
erts/emulator/beam/dist.h | 2 ++
erts/preloaded/ebin/erts_internal.beam | Bin 14100 -> 14104 bytes
erts/preloaded/src/erts_internal.erl | 3 ++-
6 files changed, 19 insertions(+), 16 deletions(-)
(limited to 'erts')
diff --git a/erts/doc/src/alt_dist.xml b/erts/doc/src/alt_dist.xml
index d3731a5391..92d40d8558 100644
--- a/erts/doc/src/alt_dist.xml
+++ b/erts/doc/src/alt_dist.xml
@@ -782,10 +782,9 @@
DFLAG_DIST_HDR_ATOM_CACHE
- Do not use atom cache over this connection.
- DFLAGS_STRICT_ORDER_DELIVERY
- - Do not use any features that require strict
- order delivery.
+ Use function dist_util:strict_order_flags/0 to get all flags
+ for features that require strict order delivery.
This flag field is optional.
@@ -819,9 +818,9 @@
The data delivery order can be relaxed by disabling
features that require strict ordering. This is done by
- passing the ?DFLAGS_STRICT_ORDER_DELIVERY
- distribution
- flags in the
+ passing the
+ distribution flags
+ returned by dist_util:strict_order_flags/0 in the
reject_flags
field of the #hs_data{}
record used when setting up the connection. When relaxed
diff --git a/erts/doc/src/erl_dist_protocol.xml b/erts/doc/src/erl_dist_protocol.xml
index a78b13aaa4..98a9a76b60 100644
--- a/erts/doc/src/erl_dist_protocol.xml
+++ b/erts/doc/src/erl_dist_protocol.xml
@@ -849,10 +849,9 @@ DiB == gen_digest(ChA, ICA)?
- There are also a collection of DFLAGs bitwise or:ed
- together in the DFLAGS_STRICT_ORDER_DELIVERY macro.
- These flags corresponds to features that require strict
- ordering of data over distribution channels.
+ There is also function dist_util:strict_order_flags/0
+ returning all flags (bitwise or:ed together) corresponding to features
+ that require strict ordering of data over distribution channels.
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index 6f122273dc..c08a8ec832 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -644,7 +644,8 @@ trap_function(Eterm func, int arity)
/*
* Sync with dist_util.erl:
*
- * -record(erts_dflags, {default, mandatory, addable, rejectable}).
+ * -record(erts_dflags,
+ * {default, mandatory, addable, rejectable, strict_order}).
*/
static Eterm erts_dflags_record;
@@ -665,13 +666,14 @@ void init_dist(void)
am_dist_ctrl_put_data,
2);
{
- Eterm* hp = erts_alloc(ERTS_ALC_T_LITERAL, (1+5)*sizeof(Eterm));
- erts_dflags_record = TUPLE5(hp, am_erts_dflags,
+ Eterm* hp = erts_alloc(ERTS_ALC_T_LITERAL, (1+6)*sizeof(Eterm));
+ erts_dflags_record = TUPLE6(hp, am_erts_dflags,
make_small(DFLAG_DIST_DEFAULT),
make_small(DFLAG_DIST_MANDATORY),
make_small(DFLAG_DIST_ADDABLE),
- make_small(DFLAG_DIST_REJECTABLE));
- erts_set_literal_tag(&erts_dflags_record, hp, (1+5));
+ make_small(DFLAG_DIST_REJECTABLE),
+ make_small(DFLAG_DIST_STRICT_ORDER));
+ erts_set_literal_tag(&erts_dflags_record, hp, (1+6));
}
}
diff --git a/erts/emulator/beam/dist.h b/erts/emulator/beam/dist.h
index 202457bb3b..e8dcdb669d 100644
--- a/erts/emulator/beam/dist.h
+++ b/erts/emulator/beam/dist.h
@@ -84,6 +84,8 @@
| DFLAG_HIDDEN_ATOM_CACHE \
| DFLAG_ATOM_CACHE)
+/* Flags for all features needing strict order delivery */
+#define DFLAG_DIST_STRICT_ORDER DFLAG_DIST_HDR_ATOM_CACHE
/* All flags that should be enabled when term_to_binary/1 is used. */
#define TERM_TO_BINARY_DFLAGS (DFLAG_EXTENDED_REFERENCES \
diff --git a/erts/preloaded/ebin/erts_internal.beam b/erts/preloaded/ebin/erts_internal.beam
index 7206b0415d..b79f734a6d 100644
Binary files a/erts/preloaded/ebin/erts_internal.beam and b/erts/preloaded/ebin/erts_internal.beam differ
diff --git a/erts/preloaded/src/erts_internal.erl b/erts/preloaded/src/erts_internal.erl
index 291a8e8fa8..a51c0c4c0e 100644
--- a/erts/preloaded/src/erts_internal.erl
+++ b/erts/preloaded/src/erts_internal.erl
@@ -511,7 +511,8 @@ dist_ctrl_put_data(DHandle, IoList) ->
end.
--spec erts_internal:get_dflags() -> {erts_dflags,integer(),integer(),integer(),integer()}.
+-spec erts_internal:get_dflags() -> {erts_dflags, integer(), integer(),
+ integer(), integer(), integer()}.
get_dflags() ->
erlang:nif_error(undefined).
--
cgit v1.2.3
From c10e3e1fc83cbccd1c8c3b377e2309ea8fa27572 Mon Sep 17 00:00:00 2001
From: Sverker Eriksson
Date: Thu, 1 Mar 2018 12:27:48 +0100
Subject: erts: Optimize dist transcoding toward erl_/jinterface
to only transcode if output buffer actually contains
unsupported BIT_BINARY_EXT or EXPORT_EXT.
---
erts/emulator/beam/dist.c | 2 ++
erts/emulator/beam/dist.h | 6 +++---
erts/emulator/beam/erl_node_tables.h | 1 +
erts/emulator/beam/external.c | 23 ++++++++++++++++-------
4 files changed, 22 insertions(+), 10 deletions(-)
(limited to 'erts')
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index c08a8ec832..132a0b9fba 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -2000,6 +2000,7 @@ erts_dsig_send(ErtsDSigData *dsdp, struct erts_dsig_send_context* ctx)
break;
}
ctx->u.ec.flags = ctx->flags;
+ ctx->u.ec.hopefull_flags = 0;
ctx->u.ec.level = 0;
ctx->u.ec.wstack.wstart = NULL;
ctx->obuf->msg_start = ctx->obuf->ext_endp;
@@ -2023,6 +2024,7 @@ erts_dsig_send(ErtsDSigData *dsdp, struct erts_dsig_send_context* ctx)
ctx->data_size = ctx->obuf->ext_endp - ctx->obuf->extp;
+ ctx->obuf->hopefull_flags = ctx->u.ec.hopefull_flags;
/*
* Signal encoded; now verify that the connection still exists,
* and if so enqueue the signal and schedule it for send.
diff --git a/erts/emulator/beam/dist.h b/erts/emulator/beam/dist.h
index e8dcdb669d..000c66a00f 100644
--- a/erts/emulator/beam/dist.h
+++ b/erts/emulator/beam/dist.h
@@ -55,9 +55,8 @@
/*
* Additional optimistic flags when encoding toward pending connection.
- * If remote node does not supporting these (erl_interface)
- * then we will need to transcode all messages enqueued before
- * connection setup was finished.
+ * If remote node (erl_interface) does not supporting these then we may need
+ * to transcode messages enqueued before connection setup was finished.
*/
#define DFLAG_DIST_HOPEFULLY (DFLAG_EXPORT_PTR_TAG \
| DFLAG_BIT_BINARIES \
@@ -355,6 +354,7 @@ typedef struct TTBSizeContext_ {
typedef struct TTBEncodeContext_ {
Uint flags;
+ Uint hopefull_flags;
int level;
byte* ep;
Eterm obj;
diff --git a/erts/emulator/beam/erl_node_tables.h b/erts/emulator/beam/erl_node_tables.h
index 8d29c83e15..5822f97f55 100644
--- a/erts/emulator/beam/erl_node_tables.h
+++ b/erts/emulator/beam/erl_node_tables.h
@@ -86,6 +86,7 @@ struct ErtsDistOutputBuf_ {
byte *alloc_endp;
#endif
ErtsDistOutputBuf *next;
+ Uint hopefull_flags;
byte *extp;
byte *ext_endp;
byte *msg_start;
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c
index b12a021e41..b358685cc0 100644
--- a/erts/emulator/beam/external.c
+++ b/erts/emulator/beam/external.c
@@ -2873,6 +2873,8 @@ enc_term_int(TTBEncodeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj, byte* ep,
ep[j] = 0; /* Zero unused bits at end of binary */
data_dst = ep;
ep += j + 1;
+ if (ctx)
+ ctx->hopefull_flags |= DFLAG_BIT_BINARIES;
} else {
/*
* Bit-level binary, but the receiver doesn't support it.
@@ -2908,6 +2910,8 @@ enc_term_int(TTBEncodeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj, byte* ep,
ep = enc_atom(acmp, exp->info.mfa.function, ep, dflags);
ep = enc_term(acmp, make_small(exp->info.mfa.arity),
ep, dflags, off_heap);
+ if (ctx)
+ ctx->hopefull_flags |= DFLAG_EXPORT_PTR_TAG;
} else {
/* Tag, arity */
*ep++ = SMALL_TUPLE_EXT;
@@ -4729,11 +4733,13 @@ Sint transcode_dist_obuf(ErtsDistOutputBuf* ob,
struct transcode_context* ctx = dep->transcode_ctx;
if (!ctx) { /* first call for 'ob' */
-
- if (~dflags & (DFLAG_BIT_BINARIES | DFLAG_EXPORT_PTR_TAG)) {
+ ASSERT(!(ob->hopefull_flags & ~(Uint)(DFLAG_BIT_BINARIES |
+ DFLAG_EXPORT_PTR_TAG)));
+ if (~dflags & ob->hopefull_flags) {
/*
- * Receiver does not support bitstrings and/or export funs.
- * We need to transcode control and message terms to use tuple fallbacks.
+ * Receiver does not support bitstrings and/or export funs
+ * and output buffer contains such message tags (hopefull_flags).
+ * Must transcode control and message terms to use tuple fallbacks.
*/
ctx = erts_alloc(ERTS_ALC_T_DIST_TRANSCODE, sizeof(struct transcode_context));
dep->transcode_ctx = ctx;
@@ -4760,7 +4766,7 @@ Sint transcode_dist_obuf(ErtsDistOutputBuf* ob,
ctx->state = TRANSCODE_ENC_CTL;
}
}
- else {
+ else if (!(dflags & DFLAG_DIST_HDR_ATOM_CACHE)) {
/*
* No need for full transcoding, but primitive receiver (erl_/jinterface)
* expects VERSION_MAGIC before both control and message terms.
@@ -4777,8 +4783,10 @@ Sint transcode_dist_obuf(ErtsDistOutputBuf* ob,
*--(ob->extp) = VERSION_MAGIC;
goto done;
}
+ else
+ goto done;
}
- else {
+ else { /* continue after yield */
ASSERT(ctx->dbg_ob == ob);
}
ctx->b2t.reds = reds * B2T_BYTES_PER_REDUCTION;
@@ -4831,6 +4839,7 @@ Sint transcode_dist_obuf(ErtsDistOutputBuf* ob,
ob->msg_start = ob->ext_endp;
ctx->ttb.wstack.wstart = NULL;
ctx->ttb.flags = dflags;
+ ctx->ttb.hopefull_flags = 0;
ctx->ttb.level = 0;
ctx->state = TRANSCODE_ENC_MSG;
@@ -4843,7 +4852,7 @@ Sint transcode_dist_obuf(ErtsDistOutputBuf* ob,
reds /= TERM_TO_BINARY_LOOP_FACTOR;
ASSERT(ob->ext_endp <= ob->alloc_endp);
-
+ ASSERT(!ctx->ttb.hopefull_flags);
}
transcode_free_ctx(dep);
--
cgit v1.2.3
From b31750711daa35011c62898d2eb424332e170bcc Mon Sep 17 00:00:00 2001
From: Sverker Eriksson
Date: Thu, 1 Mar 2018 16:36:17 +0100
Subject: erts: Refactor DistEntry.status flags into a state
Just to simplify and get 4 distinctive states
IDLE, PENDING, CONNECTED and EXITING.
The old possible flag combos were:
0
PENDING
CONNECTED
CONNECTED|EXITING
EXITING
The two EXITING states did not serve any purpose
other then as a slight optimization in monitor_node(_,false,_)
to shortcut EXITING when there can be no monitors.
---
erts/emulator/beam/dist.c | 66 ++++++++++++++++++++----------------
erts/emulator/beam/dist.h | 18 +++-------
erts/emulator/beam/erl_node_tables.c | 23 +++++++------
erts/emulator/beam/erl_node_tables.h | 11 +++---
erts/emulator/beam/external.c | 4 +--
5 files changed, 63 insertions(+), 59 deletions(-)
(limited to 'erts')
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index 132a0b9fba..f5491fd92a 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -588,13 +588,13 @@ int erts_do_net_exits(DistEntry *dep, Eterm reason)
erts_port_task_abort(&dep->dist_cmd);
}
- if (dep->status & ERTS_DE_SFLG_EXITING) {
+ if (dep->state == ERTS_DE_STATE_EXITING) {
#ifdef DEBUG
ASSERT(erts_atomic32_read_nob(&dep->qflgs) & ERTS_DE_QFLG_EXIT);
#endif
}
else {
- dep->status |= ERTS_DE_SFLG_EXITING;
+ dep->state = ERTS_DE_STATE_EXITING;
erts_mtx_lock(&dep->qlock);
ASSERT(!(erts_atomic32_read_nob(&dep->qflgs) & ERTS_DE_QFLG_EXIT));
erts_atomic32_read_bor_relb(&dep->qflgs, ERTS_DE_QFLG_EXIT);
@@ -785,7 +785,7 @@ static void clear_dist_entry(DistEntry *dep)
erts_atomic64_set_nob(&dep->out, 0);
obuf = clear_de_out_queues(dep);
- dep->status = 0;
+ dep->state = ERTS_DE_STATE_IDLE;
suspendees = get_suspended_on_de(dep, ERTS_DE_QFLGS_ALL);
erts_mtx_unlock(&dep->qlock);
@@ -2032,8 +2032,8 @@ erts_dsig_send(ErtsDSigData *dsdp, struct erts_dsig_send_context* ctx)
ctx->obuf->next = NULL;
erts_de_rlock(dep);
cid = dep->cid;
- if (!(dep->status & (ERTS_DE_SFLG_PENDING | ERTS_DE_SFLG_CONNECTED))
- || dep->status & ERTS_DE_SFLG_EXITING
+ if (dep->state == ERTS_DE_STATE_EXITING
+ || dep->state == ERTS_DE_STATE_IDLE
|| dep->connection_id != dsdp->connection_id) {
/* Not the same connection as when we started; drop message... */
erts_de_runlock(dep);
@@ -2108,7 +2108,7 @@ erts_dsig_send(ErtsDSigData *dsdp, struct erts_dsig_send_context* ctx)
}
erts_mtx_unlock(&dep->qlock);
- if (!(dep->status & ERTS_DE_SFLG_PENDING)) {
+ if (dep->state != ERTS_DE_STATE_PENDING) {
if (is_internal_port(dep->cid))
erts_schedule_dist_command(NULL, dep);
}
@@ -2290,7 +2290,7 @@ int
erts_dist_command(Port *prt, int initial_reds)
{
Sint reds = initial_reds - ERTS_PORT_REDS_DIST_CMD_START;
- Uint32 status;
+ enum dist_entry_state state;
Uint32 flags;
Sint qsize, obufsize = 0;
ErtsDistOutputQueue oq, foq;
@@ -2305,17 +2305,17 @@ erts_dist_command(Port *prt, int initial_reds)
erts_de_rlock(dep);
flags = dep->flags;
- status = dep->status;
+ state = dep->state;
send = dep->send;
erts_de_runlock(dep);
- if (status & ERTS_DE_SFLG_EXITING) {
+ if (state == ERTS_DE_STATE_EXITING) {
erts_deliver_port_exit(prt, prt->common.id, am_killed, 0, 1);
reds -= ERTS_PORT_REDS_DIST_CMD_EXIT;
return initial_reds - reds;
}
- ASSERT(!(status & ERTS_DE_SFLG_PENDING));
+ ASSERT(state != ERTS_DE_STATE_PENDING);
ASSERT(send);
@@ -2851,7 +2851,7 @@ dist_ctrl_get_data_1(BIF_ALIST_1)
erts_de_rlock(dep);
- if (dep->status & ERTS_DE_SFLG_EXITING)
+ if (dep->state == ERTS_DE_STATE_EXITING)
goto return_none;
ASSERT(dep->cid == BIF_P->common.id);
@@ -2954,9 +2954,9 @@ erts_dist_port_not_busy(Port *prt)
static void kill_connection(DistEntry *dep)
{
ERTS_LC_ASSERT(erts_lc_is_de_rwlocked(dep));
- ASSERT(dep->status == ERTS_DE_SFLG_CONNECTED);
+ ASSERT(dep->state == ERTS_DE_STATE_CONNECTED);
- dep->status |= ERTS_DE_SFLG_EXITING;
+ dep->state = ERTS_DE_STATE_EXITING;
erts_mtx_lock(&dep->qlock);
ASSERT(!(erts_atomic32_read_nob(&dep->qflgs) & ERTS_DE_QFLG_EXIT));
erts_atomic32_read_bor_nob(&dep->qflgs, ERTS_DE_QFLG_EXIT);
@@ -2973,7 +2973,7 @@ erts_kill_dist_connection(DistEntry *dep, Uint32 connection_id)
{
erts_de_rwlock(dep);
if (connection_id == dep->connection_id
- && dep->status == ERTS_DE_SFLG_CONNECTED) {
+ && dep->state == ERTS_DE_STATE_CONNECTED) {
kill_connection(dep);
}
@@ -3361,7 +3361,7 @@ BIF_RETTYPE setnode_3(BIF_ALIST_3)
goto badarg;
}
- if (dep->status & ERTS_DE_SFLG_EXITING) {
+ if (dep->state == ERTS_DE_STATE_EXITING) {
/* Suspend on dist entry waiting for the exit to finish */
ErtsProcList *plp = erts_proclist_create(BIF_P);
plp->next = NULL;
@@ -3371,8 +3371,8 @@ BIF_RETTYPE setnode_3(BIF_ALIST_3)
erts_mtx_unlock(&dep->qlock);
goto yield;
}
- if (dep->status != ERTS_DE_SFLG_PENDING) {
- if (dep->status == 0)
+ if (dep->state != ERTS_DE_STATE_PENDING) {
+ if (dep->state == ERTS_DE_STATE_IDLE)
erts_set_dist_entry_pending(dep);
else
goto badarg;
@@ -3410,7 +3410,7 @@ BIF_RETTYPE setnode_3(BIF_ALIST_3)
goto done; /* Already set */
}
- if (dep->status & ERTS_DE_SFLG_EXITING) {
+ if (dep->state == ERTS_DE_STATE_EXITING) {
/* Suspend on dist entry waiting for the exit to finish */
ErtsProcList *plp = erts_proclist_create(BIF_P);
plp->next = NULL;
@@ -3420,8 +3420,8 @@ BIF_RETTYPE setnode_3(BIF_ALIST_3)
erts_mtx_unlock(&dep->qlock);
goto yield;
}
- if (dep->status != ERTS_DE_SFLG_PENDING) {
- if (dep->status == 0)
+ if (dep->state != ERTS_DE_STATE_PENDING) {
+ if (dep->state == ERTS_DE_STATE_IDLE)
erts_set_dist_entry_pending(dep);
else
goto badarg;
@@ -3457,7 +3457,7 @@ BIF_RETTYPE setnode_3(BIF_ALIST_3)
#ifdef DEBUG
ASSERT(erts_atomic_read_nob(&dep->qsize) == 0
- || (dep->status & ERTS_DE_SFLG_PENDING));
+ || (dep->state == ERTS_DE_STATE_PENDING));
#endif
if (flags & DFLAG_DIST_HDR_ATOM_CACHE)
@@ -3550,15 +3550,20 @@ BIF_RETTYPE erts_internal_new_connection_1(BIF_ALIST_1)
erts_de_rwlock(dep);
- if (ERTS_DE_IS_CONNECTED(dep) || dep->status & ERTS_DE_SFLG_PENDING)
+ switch (dep->state) {
+ case ERTS_DE_STATE_PENDING:
+ case ERTS_DE_STATE_CONNECTED:
conn_id = dep->connection_id;
- else if (dep->status == 0) {
+ break;
+ case ERTS_DE_STATE_IDLE:
erts_set_dist_entry_pending(dep);
conn_id = dep->connection_id;
- }
- else {
- ASSERT(dep->status & ERTS_DE_SFLG_EXITING);
+ break;
+ case ERTS_DE_STATE_EXITING:
conn_id = (dep->connection_id + 1) & ERTS_DIST_CON_ID_MASK;
+ break;
+ default:
+ erts_exit(ERTS_ABORT_EXIT, "Invalid dep->state (%d)\n", dep->state);
}
erts_de_rwunlock(dep);
hp = HAlloc(BIF_P, 3 + ERTS_MAGIC_REF_THING_SIZE);
@@ -3573,10 +3578,10 @@ static Sint abort_connection(DistEntry* dep, Uint32 conn_id)
if (dep->connection_id != conn_id)
;
- else if (dep->status == ERTS_DE_SFLG_CONNECTED) {
+ else if (dep->state == ERTS_DE_STATE_CONNECTED) {
kill_connection(dep);
}
- else if (dep->status == ERTS_DE_SFLG_PENDING) {
+ else if (dep->state == ERTS_DE_STATE_PENDING) {
NetExitsContext nec = {dep};
ErtsLink *nlinks;
ErtsLink *node_links;
@@ -3656,7 +3661,7 @@ BIF_RETTYPE erts_internal_abort_connection_2(BIF_ALIST_2)
int erts_auto_connect(DistEntry* dep, Process *proc, ErtsProcLocks proc_locks)
{
erts_de_rwlock(dep);
- if (dep->status != 0) {
+ if (dep->state != ERTS_DE_STATE_IDLE) {
erts_de_rwunlock(dep);
}
else {
@@ -3932,7 +3937,8 @@ monitor_node(Process* p, Eterm Node, Eterm Bool, Eterm Options)
erts_proc_lock(p, ERTS_PROC_LOCK_LINK);
erts_de_rlock(dep);
- if (!(dep->status & (ERTS_DE_SFLG_PENDING | ERTS_DE_SFLG_CONNECTED))) {
+ if (dep->state == ERTS_DE_STATE_IDLE) {
+ ASSERT(!dep->node_links);
erts_proc_unlock(p, ERTS_PROC_LOCK_LINK);
erts_de_runlock(dep);
goto done;
diff --git a/erts/emulator/beam/dist.h b/erts/emulator/beam/dist.h
index 000c66a00f..b1b7ce9c78 100644
--- a/erts/emulator/beam/dist.h
+++ b/erts/emulator/beam/dist.h
@@ -137,14 +137,6 @@ typedef struct {
int no_suspend;
} ErtsDSigData;
-#define ERTS_DE_IS_NOT_CONNECTED(DEP) \
- (ERTS_LC_ASSERT(erts_lc_rwmtx_is_rlocked(&(DEP)->rwmtx) \
- || erts_lc_rwmtx_is_rwlocked(&(DEP)->rwmtx)), \
- (is_nil((DEP)->cid) || ((DEP)->status & ERTS_DE_SFLG_EXITING)))
-
-#define ERTS_DE_IS_CONNECTED(DEP) \
- (!ERTS_DE_IS_NOT_CONNECTED((DEP)))
-
#define ERTS_DE_BUSY_LIMIT (1024*1024)
extern int erts_dist_buf_busy_limit;
extern int erts_is_alive;
@@ -207,18 +199,18 @@ erts_dsig_prepare(ErtsDSigData *dsdp,
retry:
erts_de_rlock(dep);
- if (ERTS_DE_IS_CONNECTED(dep)) {
+ if (dep->state == ERTS_DE_STATE_CONNECTED) {
res = ERTS_DSIG_PREP_CONNECTED;
}
- else if (dep->status & ERTS_DE_SFLG_PENDING) {
+ else if (dep->state == ERTS_DE_STATE_PENDING) {
res = ERTS_DSIG_PREP_PENDING;
}
- else if (dep->status & ERTS_DE_SFLG_EXITING) {
+ else if (dep->state == ERTS_DE_STATE_EXITING) {
res = ERTS_DSIG_PREP_NOT_CONNECTED;
goto fail;
}
else if (connect) {
- ASSERT(dep->status == 0);
+ ASSERT(dep->state == ERTS_DE_STATE_IDLE);
erts_de_runlock(dep);
if (!erts_auto_connect(dep, proc, proc_locks)) {
return ERTS_DSIG_PREP_NOT_ALIVE;
@@ -226,7 +218,7 @@ retry:
goto retry;
}
else {
- ASSERT(dep->status == 0);
+ ASSERT(dep->state == ERTS_DE_STATE_IDLE);
res = ERTS_DSIG_PREP_NOT_CONNECTED;
goto fail;
}
diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c
index 088b087ebb..9871965ba6 100644
--- a/erts/emulator/beam/erl_node_tables.c
+++ b/erts/emulator/beam/erl_node_tables.c
@@ -170,7 +170,7 @@ dist_table_alloc(void *dep_tmpl)
dep->cid = NIL;
erts_atomic_init_nob(&dep->input_handler, (erts_aint_t) NIL);
dep->connection_id = 0;
- dep->status = 0;
+ dep->state = ERTS_DE_STATE_IDLE;
dep->flags = 0;
dep->version = 0;
@@ -223,7 +223,7 @@ dist_table_free(void *vdep)
DistEntry *dep = (DistEntry *) vdep;
ASSERT(de_refc_read(dep, -1) == -1);
- ASSERT(dep->status == 0);
+ ASSERT(dep->state == ERTS_DE_STATE_IDLE);
ASSERT(is_nil(dep->cid));
ASSERT(dep->nlinks == NULL);
ASSERT(dep->node_links == NULL);
@@ -556,14 +556,18 @@ erts_set_dist_entry_not_connected(DistEntry *dep)
ASSERT(dep != erts_this_dist_entry);
- if (dep->status & ERTS_DE_SFLG_PENDING) {
+ if (dep->state == ERTS_DE_STATE_PENDING) {
ASSERT(is_nil(dep->cid));
ASSERT(erts_no_of_pending_dist_entries > 0);
erts_no_of_pending_dist_entries--;
head = &erts_pending_dist_entries;
+
+ // Todo: Is this really ok? Must be not wait for links and monitors
+ // to be fired before we can allow another connection.
+ dep->state = ERTS_DE_STATE_IDLE;
}
else {
- ASSERT(dep->status != 0);
+ ASSERT(dep->state != ERTS_DE_STATE_IDLE);
ASSERT(is_internal_port(dep->cid) || is_internal_pid(dep->cid));
if (dep->flags & DFLAG_PUBLISHED) {
ASSERT(erts_no_of_visible_dist_entries > 0);
@@ -575,6 +579,7 @@ erts_set_dist_entry_not_connected(DistEntry *dep)
erts_no_of_hidden_dist_entries--;
head = &erts_hidden_dist_entries;
}
+ dep->state = ERTS_DE_STATE_EXITING;
}
if(dep->prev) {
@@ -588,7 +593,6 @@ erts_set_dist_entry_not_connected(DistEntry *dep)
if(dep->next)
dep->next->prev = dep->prev;
- dep->status &= ~(ERTS_DE_SFLG_PENDING | ERTS_DE_SFLG_CONNECTED);
dep->flags = 0;
dep->prev = NULL;
dep->cid = NIL;
@@ -610,7 +614,7 @@ erts_set_dist_entry_pending(DistEntry *dep)
erts_rwmtx_rwlock(&erts_dist_table_rwmtx);
ASSERT(dep != erts_this_dist_entry);
- ASSERT(dep->status == 0);
+ ASSERT(dep->state == ERTS_DE_STATE_IDLE);
ASSERT(is_nil(dep->cid));
if(dep->prev) {
@@ -627,7 +631,7 @@ erts_set_dist_entry_pending(DistEntry *dep)
erts_no_of_not_connected_dist_entries--;
- dep->status = ERTS_DE_SFLG_PENDING;
+ dep->state = ERTS_DE_STATE_PENDING;
dep->flags = (DFLAG_DIST_MANDATORY | DFLAG_DIST_HOPEFULLY | DFLAG_NO_MAGIC);
dep->connection_id = (dep->connection_id + 1) & ERTS_DIST_CON_ID_MASK;
@@ -652,7 +656,7 @@ erts_set_dist_entry_connected(DistEntry *dep, Eterm cid, Uint flags)
ASSERT(dep != erts_this_dist_entry);
ASSERT(is_nil(dep->cid));
- ASSERT(dep->status & ERTS_DE_SFLG_PENDING);
+ ASSERT(dep->state == ERTS_DE_STATE_PENDING);
ASSERT(is_internal_port(cid) || is_internal_pid(cid));
if(dep->prev) {
@@ -670,8 +674,7 @@ erts_set_dist_entry_connected(DistEntry *dep, Eterm cid, Uint flags)
ASSERT(erts_no_of_pending_dist_entries > 0);
erts_no_of_pending_dist_entries--;
- dep->status &= ~ERTS_DE_SFLG_PENDING;
- dep->status |= ERTS_DE_SFLG_CONNECTED;
+ dep->state = ERTS_DE_STATE_CONNECTED;
dep->flags = flags & ~DFLAG_NO_MAGIC;
dep->cid = cid;
erts_atomic_set_nob(&dep->input_handler,
diff --git a/erts/emulator/beam/erl_node_tables.h b/erts/emulator/beam/erl_node_tables.h
index 5822f97f55..58279017c8 100644
--- a/erts/emulator/beam/erl_node_tables.h
+++ b/erts/emulator/beam/erl_node_tables.h
@@ -57,9 +57,12 @@
#define ERST_INTERNAL_CHANNEL_NO 0
-#define ERTS_DE_SFLG_PENDING (((Uint32) 1) << 0)
-#define ERTS_DE_SFLG_CONNECTED (((Uint32) 1) << 1)
-#define ERTS_DE_SFLG_EXITING (((Uint32) 1) << 2)
+enum dist_entry_state {
+ ERTS_DE_STATE_IDLE,
+ ERTS_DE_STATE_PENDING,
+ ERTS_DE_STATE_CONNECTED,
+ ERTS_DE_STATE_EXITING
+};
#define ERTS_DE_QFLG_BUSY (((erts_aint32_t) 1) << 0)
#define ERTS_DE_QFLG_EXIT (((erts_aint32_t) 1) << 1)
@@ -122,7 +125,7 @@ typedef struct dist_entry_ {
Eterm cid; /* connection handler (pid or port),
NIL == free */
Uint32 connection_id; /* Connection id incremented on connect */
- Uint32 status; /* Slot status, like exiting reserved etc */
+ enum dist_entry_state state;
Uint32 flags; /* Distribution flags, like hidden,
atom cache etc. */
unsigned long version; /* Protocol version */
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c
index b358685cc0..314005e18d 100644
--- a/erts/emulator/beam/external.c
+++ b/erts/emulator/beam/external.c
@@ -711,8 +711,8 @@ erts_prepare_dist_ext(ErtsDistExternal *edep,
erts_de_rlock(dep);
- if (dep->status != ERTS_DE_SFLG_CONNECTED &&
- dep->status != ERTS_DE_SFLG_PENDING) {
+ if (dep->state != ERTS_DE_STATE_CONNECTED &&
+ dep->state != ERTS_DE_STATE_PENDING) {
erts_de_runlock(dep);
return ERTS_PREP_DIST_EXT_CLOSED;
}
--
cgit v1.2.3
From 96aba63465135d5e2537b42e5167b2863957915c Mon Sep 17 00:00:00 2001
From: Sverker Eriksson
Date: Thu, 1 Mar 2018 17:56:01 +0100
Subject: erts: Postpone idle DistEntry until abort is completed
---
erts/emulator/beam/dist.c | 11 +++++++++++
erts/emulator/beam/erl_node_tables.c | 6 +-----
2 files changed, 12 insertions(+), 5 deletions(-)
(limited to 'erts')
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index f5491fd92a..cd799e04b8 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -3630,6 +3630,17 @@ static Sint abort_connection(DistEntry* dep, Uint32 conn_id)
delete_cache(cache);
free_de_out_queues(dep, obuf);
+
+ /*
+ * We wait to make DistEntry idle and accept new connection attempts
+ * until all is cleared and deallocated. This to get some back pressure
+ * against repeated failing connection attempts saturating all CPUs
+ * with cleanup jobs.
+ */
+ erts_de_rwlock(dep);
+ ASSERT(dep->state == ERTS_DE_STATE_EXITING);
+ dep->state = ERTS_DE_STATE_IDLE;
+ erts_de_rwunlock(dep);
return reds;
}
erts_de_rwunlock(dep);
diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c
index 9871965ba6..e8901a652f 100644
--- a/erts/emulator/beam/erl_node_tables.c
+++ b/erts/emulator/beam/erl_node_tables.c
@@ -561,10 +561,6 @@ erts_set_dist_entry_not_connected(DistEntry *dep)
ASSERT(erts_no_of_pending_dist_entries > 0);
erts_no_of_pending_dist_entries--;
head = &erts_pending_dist_entries;
-
- // Todo: Is this really ok? Must be not wait for links and monitors
- // to be fired before we can allow another connection.
- dep->state = ERTS_DE_STATE_IDLE;
}
else {
ASSERT(dep->state != ERTS_DE_STATE_IDLE);
@@ -579,7 +575,6 @@ erts_set_dist_entry_not_connected(DistEntry *dep)
erts_no_of_hidden_dist_entries--;
head = &erts_hidden_dist_entries;
}
- dep->state = ERTS_DE_STATE_EXITING;
}
if(dep->prev) {
@@ -593,6 +588,7 @@ erts_set_dist_entry_not_connected(DistEntry *dep)
if(dep->next)
dep->next->prev = dep->prev;
+ dep->state = ERTS_DE_STATE_EXITING;
dep->flags = 0;
dep->prev = NULL;
dep->cid = NIL;
--
cgit v1.2.3
From b0860754c392a591389f5f35ee5458758f6db10f Mon Sep 17 00:00:00 2001
From: Sverker Eriksson
Date: Fri, 2 Mar 2018 18:49:29 +0100
Subject: erts: Improve send/2 docs
with link to ! operator
and clarify ugly badarg for unregistered atom argument.
---
erts/doc/src/erlang.xml | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
(limited to 'erts')
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index 771897ba94..ff0480291b 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -5700,11 +5700,17 @@ true
Sends a message and returns Msg. This
- is the same as Dest ! Msg.
+ is the same as using the
+ send operator:
+ Dest ! Msg.
Dest can be a remote or local process identifier,
a (local) port, a locally registered name, or a tuple
{RegName, Node}
- for a registered name at another node.
+ for a registered name at another node.
+ The function fails with a badarg run-time error if
+ Dest is an atom name, but this name is not
+ registered. This is the only case when send fails for an
+ unreachable destination Dest (of correct type).
--
cgit v1.2.3