aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/dist.h
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/beam/dist.h')
-rw-r--r--erts/emulator/beam/dist.h290
1 files changed, 290 insertions, 0 deletions
diff --git a/erts/emulator/beam/dist.h b/erts/emulator/beam/dist.h
new file mode 100644
index 0000000000..ea1abcaeed
--- /dev/null
+++ b/erts/emulator/beam/dist.h
@@ -0,0 +1,290 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1996-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#ifndef __DIST_H__
+#define __DIST_H__
+
+#include "erl_process.h"
+#include "erl_node_tables.h"
+
+#define DFLAG_PUBLISHED 0x01
+#define DFLAG_ATOM_CACHE 0x02
+#define DFLAG_EXTENDED_REFERENCES 0x04
+#define DFLAG_DIST_MONITOR 0x08
+#define DFLAG_FUN_TAGS 0x10
+#define DFLAG_DIST_MONITOR_NAME 0x20
+#define DFLAG_HIDDEN_ATOM_CACHE 0x40
+#define DFLAG_NEW_FUN_TAGS 0x80
+#define DFLAG_EXTENDED_PIDS_PORTS 0x100
+#define DFLAG_EXPORT_PTR_TAG 0x200
+#define DFLAG_BIT_BINARIES 0x400
+#define DFLAG_NEW_FLOATS 0x800
+#define DFLAG_UNICODE_IO 0x1000
+#define DFLAG_DIST_HDR_ATOM_CACHE 0x2000
+#define DFLAG_SMALL_ATOM_TAGS 0x4000
+
+/* 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 \
+ | DFLAG_EXTENDED_PIDS_PORTS \
+ | DFLAG_EXPORT_PTR_TAG \
+ | DFLAG_BIT_BINARIES)
+
+/* opcodes used in distribution messages */
+#define DOP_LINK 1
+#define DOP_SEND 2
+#define DOP_EXIT 3
+#define DOP_UNLINK 4
+#define DOP_NODE_LINK 5
+#define DOP_REG_SEND 6
+#define DOP_GROUP_LEADER 7
+#define DOP_EXIT2 8
+
+#define DOP_SEND_TT 12
+#define DOP_EXIT_TT 13
+#define DOP_REG_SEND_TT 16
+#define DOP_EXIT2_TT 18
+
+#define DOP_MONITOR_P 19
+#define DOP_DEMONITOR_P 20
+#define DOP_MONITOR_P_EXIT 21
+
+/* distribution trap functions */
+extern Export* dsend2_trap;
+extern Export* dsend3_trap;
+/*extern Export* dsend_nosuspend_trap;*/
+extern Export* dlink_trap;
+extern Export* dunlink_trap;
+extern Export* dmonitor_node_trap;
+extern Export* dgroup_leader_trap;
+extern Export* dexit_trap;
+extern Export* dmonitor_p_trap;
+
+typedef enum {
+ ERTS_DSP_NO_LOCK,
+ ERTS_DSP_RLOCK,
+ ERTS_DSP_RWLOCK
+} ErtsDSigPrepLock;
+
+
+typedef struct {
+ Process *proc;
+ DistEntry *dep;
+ Eterm cid;
+ Eterm connection_id;
+ int no_suspend;
+} ErtsDSigData;
+
+#define ERTS_DE_IS_NOT_CONNECTED(DEP) \
+ (ERTS_SMP_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)))
+
+
+extern int erts_is_alive;
+
+/*
+ * erts_dsig_prepare() prepares a send of a distributed signal.
+ * One of the values defined below are returned. If the returned
+ * value is another than ERTS_DSIG_PREP_CONNECTED, the
+ * distributed signal cannot be sent before apropriate actions
+ * have been taken. Apropriate actions would typically be setting
+ * up the connection.
+ */
+
+/* Connected; signal can be sent. */
+#define ERTS_DSIG_PREP_CONNECTED 0
+/* Not connected; connection needs to be set up. */
+#define ERTS_DSIG_PREP_NOT_CONNECTED 1
+/* Caller would be suspended on send operation. */
+#define ERTS_DSIG_PREP_WOULD_SUSPEND 2
+/* System not alive (distributed) */
+#define ERTS_DSIG_PREP_NOT_ALIVE 3
+
+ERTS_GLB_INLINE int erts_dsig_prepare(ErtsDSigData *,
+ DistEntry *,
+ Process *,
+ ErtsDSigPrepLock,
+ int);
+
+ERTS_GLB_INLINE
+void erts_schedule_dist_command(Port *, DistEntry *);
+
+#if ERTS_GLB_INLINE_INCL_FUNC_DEF
+
+ERTS_GLB_INLINE int
+erts_dsig_prepare(ErtsDSigData *dsdp,
+ DistEntry *dep,
+ Process *proc,
+ ErtsDSigPrepLock dspl,
+ int no_suspend)
+{
+ int failure;
+ if (!erts_is_alive)
+ return ERTS_DSIG_PREP_NOT_ALIVE;
+ if (!dep)
+ return ERTS_DSIG_PREP_NOT_CONNECTED;
+ if (dspl == ERTS_DSP_RWLOCK)
+ erts_smp_de_rwlock(dep);
+ else
+ erts_smp_de_rlock(dep);
+ if (ERTS_DE_IS_NOT_CONNECTED(dep)) {
+ failure = ERTS_DSIG_PREP_NOT_CONNECTED;
+ goto fail;
+ }
+ if (no_suspend) {
+ failure = ERTS_DSIG_PREP_CONNECTED;
+ erts_smp_spin_lock(&dep->qlock);
+ if (dep->qflgs & ERTS_DE_QFLG_BUSY)
+ failure = ERTS_DSIG_PREP_WOULD_SUSPEND;
+ erts_smp_spin_unlock(&dep->qlock);
+ if (failure == ERTS_DSIG_PREP_WOULD_SUSPEND)
+ goto fail;
+ }
+ dsdp->proc = proc;
+ dsdp->dep = dep;
+ dsdp->cid = dep->cid;
+ dsdp->connection_id = dep->connection_id;
+ dsdp->no_suspend = no_suspend;
+ if (dspl == ERTS_DSP_NO_LOCK)
+ erts_smp_de_runlock(dep);
+ return ERTS_DSIG_PREP_CONNECTED;
+
+ fail:
+ if (dspl == ERTS_DSP_RWLOCK)
+ erts_smp_de_rwunlock(dep);
+ else
+ erts_smp_de_runlock(dep);
+ return failure;
+
+}
+
+ERTS_GLB_INLINE
+void erts_schedule_dist_command(Port *prt, DistEntry *dist_entry)
+{
+ DistEntry *dep;
+ Eterm id;
+
+ if (prt) {
+ ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt));
+ ASSERT((erts_port_status_get(prt) & ERTS_PORT_SFLGS_DEAD) == 0);
+ ASSERT(prt->dist_entry);
+
+ dep = prt->dist_entry;
+ id = prt->id;
+ }
+ else {
+ ASSERT(dist_entry);
+ ERTS_SMP_LC_ASSERT(erts_lc_rwmtx_is_rlocked(&dist_entry->rwmtx)
+ || erts_lc_rwmtx_is_rwlocked(&dist_entry->rwmtx));
+ ASSERT(is_internal_port(dist_entry->cid));
+
+ dep = dist_entry;
+ id = dep->cid;
+ }
+
+ if (!erts_smp_atomic_xchg(&dep->dist_cmd_scheduled, 1)) {
+ (void) erts_port_task_schedule(id,
+ &dep->dist_cmd,
+ ERTS_PORT_TASK_DIST_CMD,
+ (ErlDrvEvent) -1,
+ NULL);
+ }
+}
+
+#endif
+
+typedef struct {
+ ErtsLink *d_lnk;
+ ErtsLink *d_sub_lnk;
+} ErtsDistLinkData;
+
+ERTS_GLB_INLINE void erts_remove_dist_link(ErtsDistLinkData *,
+ Eterm,
+ Eterm,
+ DistEntry *);
+ERTS_GLB_INLINE int erts_was_dist_link_removed(ErtsDistLinkData *);
+ERTS_GLB_INLINE void erts_destroy_dist_link(ErtsDistLinkData *);
+
+#if ERTS_GLB_INLINE_INCL_FUNC_DEF
+
+ERTS_GLB_INLINE void
+erts_remove_dist_link(ErtsDistLinkData *dldp,
+ Eterm lid,
+ Eterm rid,
+ DistEntry *dep)
+{
+ erts_smp_de_links_lock(dep);
+ dldp->d_lnk = erts_lookup_link(dep->nlinks, lid);
+ if (!dldp->d_lnk)
+ dldp->d_sub_lnk = NULL;
+ else {
+ dldp->d_sub_lnk = erts_remove_link(&ERTS_LINK_ROOT(dldp->d_lnk), rid);
+ dldp->d_lnk = (ERTS_LINK_ROOT(dldp->d_lnk)
+ ? NULL
+ : erts_remove_link(&dep->nlinks, lid));
+ }
+ erts_smp_de_links_unlock(dep);
+}
+
+ERTS_GLB_INLINE int
+erts_was_dist_link_removed(ErtsDistLinkData *dldp)
+{
+ return dldp->d_sub_lnk != NULL;
+}
+
+ERTS_GLB_INLINE void
+erts_destroy_dist_link(ErtsDistLinkData *dldp)
+{
+ if (dldp->d_lnk)
+ erts_destroy_link(dldp->d_lnk);
+ if (dldp->d_sub_lnk)
+ erts_destroy_link(dldp->d_sub_lnk);
+}
+
+#endif
+
+/*
+ * erts_dsig_send_* return values.
+ */
+#define ERTS_DSIG_SEND_OK 0
+#define ERTS_DSIG_SEND_YIELD 1
+
+extern int erts_dsig_send_link(ErtsDSigData *, Eterm, Eterm);
+extern int erts_dsig_send_msg(ErtsDSigData *, Eterm, Eterm);
+extern int erts_dsig_send_exit_tt(ErtsDSigData *, Eterm, Eterm, Eterm, Eterm);
+extern int erts_dsig_send_unlink(ErtsDSigData *, Eterm, Eterm);
+extern int erts_dsig_send_reg_msg(ErtsDSigData *, Eterm, Eterm);
+extern int erts_dsig_send_group_leader(ErtsDSigData *, Eterm, Eterm);
+extern int erts_dsig_send_exit(ErtsDSigData *, Eterm, Eterm, Eterm);
+extern int erts_dsig_send_exit2(ErtsDSigData *, 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);
+
+extern int erts_dist_command(Port *prt, int reds);
+extern void erts_dist_port_not_busy(Port *prt);
+extern void erts_kill_dist_connection(DistEntry *dep, Uint32);
+
+extern Uint erts_dist_cache_size(void);
+
+#endif