From 84adefa331c4159d432d22840663c38f155cd4c1 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Fri, 20 Nov 2009 14:54:40 +0000 Subject: The R13B03 release. --- erts/emulator/beam/erl_node_tables.h | 261 +++++++++++++++++++++++++++++++++++ 1 file changed, 261 insertions(+) create mode 100644 erts/emulator/beam/erl_node_tables.h (limited to 'erts/emulator/beam/erl_node_tables.h') diff --git a/erts/emulator/beam/erl_node_tables.h b/erts/emulator/beam/erl_node_tables.h new file mode 100644 index 0000000000..c48dac6219 --- /dev/null +++ b/erts/emulator/beam/erl_node_tables.h @@ -0,0 +1,261 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2001-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 ERL_NODE_TABLES_H__ +#define ERL_NODE_TABLES_H__ + +/* + * The "node_tables module" contain two (hash) tables: the node_table + * and the dist_table. + * + * The elements of the node_table represents a specific incarnation of + * an Erlang node and has {Nodename, Creation} pairs as keys. Elements + * in the node_table are referred to from node containers (see + * node_container_utils.h). + * + * The elements of the dist_table represents a (potential) connection + * to an Erlang node and has Nodename as key. Elements in the + * dist_table are either referred to from elements in the node_table + * or from the process or port structure of the entity controlling + * the connection. + * + * Both tables are garbage collected by reference counting. + */ + +#include "sys.h" +#include "hash.h" +#include "erl_process.h" +#include "erl_monitors.h" +#include "erl_smp.h" +#define ERTS_PORT_TASK_ONLY_BASIC_TYPES__ +#include "erl_port_task.h" +#undef ERTS_PORT_TASK_ONLY_BASIC_TYPES__ + +#define ERST_INTERNAL_CHANNEL_NO 0 + +#define ERTS_DE_SFLG_CONNECTED (((Uint32) 1) << 0) +#define ERTS_DE_SFLG_EXITING (((Uint32) 1) << 1) + +#define ERTS_DE_SFLGS_ALL (ERTS_DE_SFLG_CONNECTED \ + | ERTS_DE_SFLG_EXITING) + +#define ERTS_DE_QFLG_BUSY (((Uint32) 1) << 0) +#define ERTS_DE_QFLG_EXIT (((Uint32) 1) << 1) + +#define ERTS_DE_QFLGS_ALL (ERTS_DE_QFLG_BUSY \ + | ERTS_DE_QFLG_EXIT) + +#ifdef ARCH_64 +#define ERTS_DIST_OUTPUT_BUF_DBG_PATTERN ((Uint) 0xf713f713f713f713UL) +#else +#define ERTS_DIST_OUTPUT_BUF_DBG_PATTERN ((Uint) 0xf713f713) +#endif + +typedef struct ErtsDistOutputBuf_ ErtsDistOutputBuf; +struct ErtsDistOutputBuf_ { +#ifdef DEBUG + Uint dbg_pattern; +#endif + ErtsDistOutputBuf *next; + byte *extp; + byte *ext_endp; + byte data[1]; +}; + +typedef struct { + ErtsDistOutputBuf *first; + ErtsDistOutputBuf *last; +} ErtsDistOutputQueue; + +struct ErtsProcList_; +typedef struct { + struct ErtsProcList_ *first; + struct ErtsProcList_ *last; +} ErtsDistSuspended; + +/* + * Lock order: + * 1. dist_entry->rwmtx + * 2. erts_node_table_rwmtx + * 3. erts_dist_table_rwmtx + * + * Lock mutexes with lower numbers before mutexes with higher numbers and + * unlock mutexes with higher numbers before mutexes with higher numbers. + */ + +struct erl_link; +struct port; + +typedef struct dist_entry_ { + HashBucket hash_bucket; /* Hash bucket */ + struct dist_entry_ *next; /* Next entry in dist_table (not sorted) */ + struct dist_entry_ *prev; /* Previous entry in dist_table (not sorted) */ + erts_refc_t refc; /* Reference count */ + + erts_smp_rwmtx_t rwmtx; /* Protects all fields below until lck_mtx. */ + Eterm sysname; /* name@host atom for efficiency */ + Uint32 creation; /* creation of connected node */ + 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 */ + Uint32 flags; /* Distribution flags, like hidden, + atom cache etc. */ + unsigned long version; /* Protocol version */ + + + erts_smp_mtx_t lnk_mtx; /* Protects node_links, nlinks, and + monitors. */ + ErtsLink *node_links; /* In a dist entry, node links are kept + in a separate tree, while they are + colocted with the ordinary link tree + for processes. It's not due to confusion, + it's because the link tree for the dist + entry is in two levels, see erl_monitors.h + */ + ErtsLink *nlinks; /* Link tree with subtrees */ + ErtsMonitor *monitors; /* Monitor tree */ + + erts_smp_spinlock_t qlock; /* Protects qflgs and out_queue */ + Uint32 qflgs; + Sint qsize; + ErtsDistOutputQueue out_queue; + ErtsDistSuspended suspended; + + ErtsDistOutputQueue finalized_out_queue; + erts_smp_atomic_t dist_cmd_scheduled; + ErtsPortTaskHandle dist_cmd; + + Uint (*send)(struct port *prt, ErtsDistOutputBuf *obuf); + + struct cache* cache; /* The atom cache */ +} DistEntry; + +typedef struct erl_node_ { + HashBucket hash_bucket; /* Hash bucket */ + erts_refc_t refc; /* Reference count */ + Eterm sysname; /* name@host atom for efficiency */ + Uint32 creation; /* Creation */ + DistEntry *dist_entry; /* Corresponding dist entry */ +} ErlNode; + + +extern Hash erts_dist_table; +extern Hash erts_node_table; +extern erts_smp_rwmtx_t erts_dist_table_rwmtx; +extern erts_smp_rwmtx_t erts_node_table_rwmtx; + +extern DistEntry *erts_hidden_dist_entries; +extern DistEntry *erts_visible_dist_entries; +extern DistEntry *erts_not_connected_dist_entries; +extern Sint erts_no_of_hidden_dist_entries; +extern Sint erts_no_of_visible_dist_entries; +extern Sint erts_no_of_not_connected_dist_entries; + +extern DistEntry *erts_this_dist_entry; +extern ErlNode *erts_this_node; + +DistEntry *erts_channel_no_to_dist_entry(Uint); +DistEntry *erts_sysname_to_connected_dist_entry(Eterm); +DistEntry *erts_find_or_insert_dist_entry(Eterm); +DistEntry *erts_find_dist_entry(Eterm); +void erts_delete_dist_entry(DistEntry *); +Uint erts_dist_table_size(void); +void erts_dist_table_info(int, void *); +void erts_set_dist_entry_not_connected(DistEntry *); +void erts_set_dist_entry_connected(DistEntry *, Eterm, Uint); +ErlNode *erts_find_or_insert_node(Eterm, Uint); +void erts_delete_node(ErlNode *); +void erts_set_this_node(Eterm, Uint); +Uint erts_node_table_size(void); +void erts_init_node_tables(void); +void erts_node_table_info(int, void *); +void erts_print_node_info(int, void *, Eterm, int*, int*); +Eterm erts_get_node_and_dist_references(struct process *); +#if defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK) +int erts_lc_is_de_rwlocked(DistEntry *); +int erts_lc_is_de_rlocked(DistEntry *); +#endif + +ERTS_GLB_INLINE void erts_deref_dist_entry(DistEntry *dep); +ERTS_GLB_INLINE void erts_deref_node_entry(ErlNode *np); +ERTS_GLB_INLINE void erts_smp_de_rlock(DistEntry *dep); +ERTS_GLB_INLINE void erts_smp_de_runlock(DistEntry *dep); +ERTS_GLB_INLINE void erts_smp_de_rwlock(DistEntry *dep); +ERTS_GLB_INLINE void erts_smp_de_rwunlock(DistEntry *dep); +ERTS_GLB_INLINE void erts_smp_de_links_lock(DistEntry *dep); +ERTS_GLB_INLINE void erts_smp_de_links_unlock(DistEntry *dep); + +#if ERTS_GLB_INLINE_INCL_FUNC_DEF + +ERTS_GLB_INLINE void +erts_deref_dist_entry(DistEntry *dep) +{ + ASSERT(dep); + if (erts_refc_dectest(&dep->refc, 0) == 0) + erts_delete_dist_entry(dep); +} + +ERTS_GLB_INLINE void +erts_deref_node_entry(ErlNode *np) +{ + ASSERT(np); + if (erts_refc_dectest(&np->refc, 0) == 0) + erts_delete_node(np); +} + +ERTS_GLB_INLINE void +erts_smp_de_rlock(DistEntry *dep) +{ + erts_smp_rwmtx_rlock(&dep->rwmtx); +} + +ERTS_GLB_INLINE void +erts_smp_de_runlock(DistEntry *dep) +{ + erts_smp_rwmtx_runlock(&dep->rwmtx); +} + +ERTS_GLB_INLINE void +erts_smp_de_rwlock(DistEntry *dep) +{ + erts_smp_rwmtx_rwlock(&dep->rwmtx); +} + +ERTS_GLB_INLINE void +erts_smp_de_rwunlock(DistEntry *dep) +{ + erts_smp_rwmtx_rwunlock(&dep->rwmtx); +} + +ERTS_GLB_INLINE void +erts_smp_de_links_lock(DistEntry *dep) +{ + erts_smp_mtx_lock(&dep->lnk_mtx); +} + +ERTS_GLB_INLINE void +erts_smp_de_links_unlock(DistEntry *dep) +{ + erts_smp_mtx_unlock(&dep->lnk_mtx); +} + +#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */ + + +#endif -- cgit v1.2.3