aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r--erts/emulator/beam/erl_monitor_link.c49
-rw-r--r--erts/emulator/beam/erl_monitor_link.h17
-rw-r--r--erts/emulator/beam/erl_node_tables.c153
-rw-r--r--erts/emulator/beam/erl_process.c76
-rw-r--r--erts/emulator/beam/erl_process.h7
5 files changed, 233 insertions, 69 deletions
diff --git a/erts/emulator/beam/erl_monitor_link.c b/erts/emulator/beam/erl_monitor_link.c
index 1c6b4afaa3..43028be39d 100644
--- a/erts/emulator/beam/erl_monitor_link.c
+++ b/erts/emulator/beam/erl_monitor_link.c
@@ -671,6 +671,24 @@ erts_monitor_tree_foreach(ErtsMonitor *root,
arg);
}
+void
+erts_debug_monitor_tree_destroying_foreach(ErtsMonitor *root,
+ ErtsMonitorFunc func,
+ void *arg,
+ void *vysp)
+{
+ void *tmp_vysp = erts_alloc(ERTS_ALC_T_ML_YIELD_STATE,
+ sizeof(ErtsMonLnkYieldState));
+ Sint reds;
+ sys_memcpy(tmp_vysp, tmp_vysp, sizeof(ErtsMonLnkYieldState));
+ do {
+ reds = ml_rbt_foreach_yielding((ErtsMonLnkNode *) root,
+ (ErtsMonLnkNodeFunc) func,
+ arg, &tmp_vysp, (Sint) INT_MAX);
+ } while (reds <= 0);
+ ERTS_ML_ASSERT(!tmp_vysp);
+}
+
int
erts_monitor_tree_foreach_yielding(ErtsMonitor *root,
ErtsMonitorFunc func,
@@ -716,6 +734,19 @@ erts_monitor_list_foreach(ErtsMonitor *list,
arg, &ystate, (Sint) INT_MAX));
}
+void
+erts_debug_monitor_list_destroying_foreach(ErtsMonitor *list,
+ ErtsMonitorFunc func,
+ void *arg,
+ void *vysp)
+{
+ void *tmp_vysp = vysp;
+ while (!ml_dl_list_foreach_yielding((ErtsMonLnkNode *) list,
+ (int (*)(ErtsMonLnkNode *, void *, Sint)) func,
+ arg, &tmp_vysp, (Sint) INT_MAX));
+ ERTS_ML_ASSERT(!tmp_vysp);
+}
+
int
erts_monitor_list_foreach_yielding(ErtsMonitor *list,
ErtsMonitorFunc func,
@@ -1080,6 +1111,24 @@ erts_link_tree_foreach(ErtsLink *root,
}
+void
+erts_debug_link_tree_destroying_foreach(ErtsLink *root,
+ ErtsLinkFunc func,
+ void *arg,
+ void *vysp)
+{
+ void *tmp_vysp = erts_alloc(ERTS_ALC_T_ML_YIELD_STATE,
+ sizeof(ErtsMonLnkYieldState));
+ Sint reds;
+ sys_memcpy(tmp_vysp, vysp, sizeof(ErtsMonLnkYieldState));
+ do {
+ reds = ml_rbt_foreach_yielding((ErtsMonLnkNode *) root,
+ (ErtsMonLnkNodeFunc) func,
+ arg, &tmp_vysp, (Sint) INT_MAX);
+ } while (reds <= 0);
+ ERTS_ML_ASSERT(!tmp_vysp);
+}
+
int
erts_link_tree_foreach_yielding(ErtsLink *root,
ErtsLinkFunc func,
diff --git a/erts/emulator/beam/erl_monitor_link.h b/erts/emulator/beam/erl_monitor_link.h
index eff861fce8..86be400c09 100644
--- a/erts/emulator/beam/erl_monitor_link.h
+++ b/erts/emulator/beam/erl_monitor_link.h
@@ -1509,6 +1509,17 @@ ERTS_GLB_INLINE ErtsMonitorSuspend *erts_monitor_suspend(ErtsMonitor *mon)
#endif
+void
+erts_debug_monitor_tree_destroying_foreach(ErtsMonitor *root,
+ ErtsMonitorFunc func,
+ void *arg,
+ void *vysp);
+void
+erts_debug_monitor_list_destroying_foreach(ErtsMonitor *list,
+ ErtsMonitorFunc func,
+ void *arg,
+ void *vysp);
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* Link Operations *
\* */
@@ -2365,4 +2376,10 @@ erts_link_dist_delete(ErtsLink *lnk)
#endif /* ERTS_GLB_INLINE_INCL_FUNC_DEF */
+void
+erts_debug_link_tree_destroying_foreach(ErtsLink *root,
+ ErtsLinkFunc func,
+ void *arg,
+ void *vysp);
+
#endif /* ERL_MONITOR_LINK_H__ */
diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c
index bdf30ef496..50e9812534 100644
--- a/erts/emulator/beam/erl_node_tables.c
+++ b/erts/emulator/beam/erl_node_tables.c
@@ -1200,7 +1200,7 @@ static Eterm AM_persistent_term;
static void setup_reference_table(void);
static Eterm reference_table_term(Uint **hpp, ErlOffHeap *ohp, Uint *szp);
static void delete_reference_table(void);
-static void cleanup_system(void);
+static void clear_system(void);
#undef ERTS_MAX__
#define ERTS_MAX__(A, B) ((A) > (B) ? (A) : (B))
@@ -1323,7 +1323,7 @@ erts_get_node_and_dist_references(struct process *proc)
delete_reference_table();
#endif
- cleanup_system();
+ clear_system();
erts_thr_progress_unblock();
erts_proc_lock(proc, ERTS_PROC_LOCK_MAIN);
@@ -1594,18 +1594,6 @@ static int clear_visited_monitor(ErtsMonitor *mon, void *p, Sint reds)
}
static void
-insert_p_monitors(ErtsPTabElementCommon *p)
-{
- Eterm id = p->id;
- erts_monitor_tree_foreach(p->u.alive.monitors,
- insert_monitor,
- (void *) &id);
- erts_monitor_list_foreach(p->u.alive.lt_monitors,
- insert_monitor,
- (void *) &id);
-}
-
-static void
insert_dist_monitors(DistEntry *dep)
{
if (dep->mld) {
@@ -1635,17 +1623,6 @@ insert_dist_sequences(DistEntry *dep)
}
static void
-clear_visited_p_monitors(ErtsPTabElementCommon *p)
-{
- erts_monitor_tree_foreach(p->u.alive.monitors,
- clear_visited_monitor,
- NULL);
- erts_monitor_list_foreach(p->u.alive.lt_monitors,
- clear_visited_monitor,
- NULL);
-}
-
-static void
clear_visited_dist_monitors(DistEntry *dep)
{
if (dep->mld) {
@@ -1689,13 +1666,6 @@ static int clear_visited_link(ErtsLink *lnk, void *p, Sint reds)
}
static void
-insert_p_links(ErtsPTabElementCommon *p)
-{
- Eterm id = p->id;
- erts_link_tree_foreach(p->u.alive.links, insert_link, (void *) &id);
-}
-
-static void
insert_dist_links(DistEntry *dep)
{
if (dep->mld)
@@ -1705,14 +1675,6 @@ insert_dist_links(DistEntry *dep)
}
static void
-clear_visited_p_links(ErtsPTabElementCommon *p)
-{
- erts_link_tree_foreach(p->u.alive.links,
- clear_visited_link,
- NULL);
-}
-
-static void
clear_visited_dist_links(DistEntry *dep)
{
if (dep->mld)
@@ -1907,15 +1869,11 @@ insert_process(Process *proc)
insert_sig_ext,
(void *) proc);
- /* If the process is FREE, the proc->common field has been
- re-used by the ptab delete, so we cannot trust it. */
- if (!(erts_atomic32_read_nob(&proc->state) & ERTS_PSFLG_FREE)) {
- /* Insert links */
- insert_p_links(&proc->common);
-
- /* Insert monitors */
- insert_p_monitors(&proc->common);
- }
+ /* Insert monitors and links... */
+ erts_debug_proc_monitor_link_foreach(proc,
+ insert_monitor,
+ insert_link,
+ (void *) &proc->common.id);
{
DistEntry *dep = ERTS_PROC_GET_DIST_ENTRY(proc);
@@ -1928,6 +1886,12 @@ insert_process(Process *proc)
}
static void
+insert_process2(Process *proc, void *arg)
+{
+ insert_process(proc);
+}
+
+static void
insert_dist_suspended_procs(DistEntry *dep)
{
ErtsProcList *plist = erts_proclist_peek_first(dep->suspended);
@@ -1938,6 +1902,19 @@ insert_dist_suspended_procs(DistEntry *dep)
}
}
+static void clear_process(Process *proc);
+
+static void
+clear_dist_suspended_procs(DistEntry *dep)
+{
+ ErtsProcList *plist = erts_proclist_peek_first(dep->suspended);
+ while (plist) {
+ if (is_not_immed(plist->u.pid))
+ clear_process(plist->u.p);
+ plist = erts_proclist_peek_next(dep->suspended, plist);
+ }
+}
+
static void
insert_persistent_term(ErlOffHeap *ohp, void *arg)
{
@@ -2030,7 +2007,8 @@ setup_reference_table(void)
if (proc)
insert_process(proc);
}
-
+ erts_debug_free_process_foreach(insert_process2, NULL);
+
erts_debug_foreach_sys_msg_in_q(insert_sys_msg);
/* Insert all ports */
@@ -2048,10 +2026,18 @@ setup_reference_table(void)
if (state & ERTS_PORT_SFLGS_DEAD)
continue;
- /* Insert links */
- insert_p_links(&prt->common);
- /* Insert monitors */
- insert_p_monitors(&prt->common);
+ /* Insert links */
+ erts_link_tree_foreach(ERTS_P_LINKS(prt),
+ insert_link,
+ (void *) &prt->common.id);
+ /* Insert monitors */
+ erts_monitor_tree_foreach(ERTS_P_MONITORS(prt),
+ insert_monitor,
+ (void *) &prt->common.id);
+ /* Insert local target monitors */
+ erts_monitor_list_foreach(ERTS_P_LT_MONITORS(prt),
+ insert_monitor,
+ (void *) &prt->common.id);
/* Insert port data */
ohp = erts_port_data_offheap(prt);
if (ohp)
@@ -2431,28 +2417,43 @@ delete_reference_table(void)
}
}
+static void clear_process(Process *proc)
+{
+ erts_proc_sig_debug_foreach_sig(proc,
+ noop_sig_msg,
+ noop_sig_offheap,
+ clear_visited_monitor,
+ clear_visited_link,
+ noop_sig_ext,
+ (void *) proc);
+
+
+ /* Clear monitors and links... */
+ erts_debug_proc_monitor_link_foreach(proc,
+ clear_visited_monitor,
+ clear_visited_link,
+ (void *) &proc->common.id);
+}
+
+static void clear_process2(Process *proc, void *arg)
+{
+ clear_process(proc);
+}
+
static void
-cleanup_system(void)
+clear_system(void)
{
DistEntry *dep;
int i, max;
- /* Cleanup... */
+ /* Clear... */
max = erts_ptab_max(&erts_proc);
for (i = 0; i < max; i++) {
Process *proc = erts_pix2proc(i);
- if (proc) {
- clear_visited_p_links(&proc->common);
- clear_visited_p_monitors(&proc->common);
- erts_proc_sig_debug_foreach_sig(proc,
- noop_sig_msg,
- noop_sig_offheap,
- clear_visited_monitor,
- clear_visited_link,
- noop_sig_ext,
- (void *) proc);
- }
+ if (proc)
+ clear_process(proc);
}
+ erts_debug_free_process_foreach(clear_process2, NULL);
max = erts_ptab_max(&erts_port);
for (i = 0; i < max; i++) {
@@ -2467,28 +2468,42 @@ cleanup_system(void)
if (state & ERTS_PORT_SFLGS_DEAD)
continue;
- clear_visited_p_links(&prt->common);
- clear_visited_p_monitors(&prt->common);
+ /* Clear links */
+ erts_link_tree_foreach(ERTS_P_LINKS(prt),
+ clear_visited_link,
+ (void *) &prt->common.id);
+ /* Clear monitors */
+ erts_monitor_tree_foreach(ERTS_P_MONITORS(prt),
+ clear_visited_monitor,
+ (void *) &prt->common.id);
+ /* Clear local target monitors */
+ erts_monitor_list_foreach(ERTS_P_LT_MONITORS(prt),
+ clear_visited_monitor,
+ (void *) &prt->common.id);
}
for(dep = erts_visible_dist_entries; dep; dep = dep->next) {
clear_visited_dist_links(dep);
clear_visited_dist_monitors(dep);
+ clear_dist_suspended_procs(dep);
}
for(dep = erts_hidden_dist_entries; dep; dep = dep->next) {
clear_visited_dist_links(dep);
clear_visited_dist_monitors(dep);
+ clear_dist_suspended_procs(dep);
}
for(dep = erts_pending_dist_entries; dep; dep = dep->next) {
clear_visited_dist_links(dep);
clear_visited_dist_monitors(dep);
+ clear_dist_suspended_procs(dep);
}
for(dep = erts_not_connected_dist_entries; dep; dep = dep->next) {
clear_visited_dist_links(dep);
clear_visited_dist_monitors(dep);
+ clear_dist_suspended_procs(dep);
}
}
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index 1f6adb98ef..994876e796 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -13495,3 +13495,79 @@ erts_debug_later_op_foreach(void (*callback)(void*),
}
}
}
+
+void
+erts_debug_free_process_foreach(void (*func)(Process *, void *), void *arg)
+{
+ ErtsRunQueue *rq;
+ int ix, prio;
+ for (ix = 0; ix < erts_no_run_queues; ix++) {
+ rq = ERTS_RUNQ_IX(ix);
+ for (prio = PRIORITY_MAX; prio < PRIORITY_LOW; prio++) {
+ Process *p = rq->procs.prio[prio].first;
+ for (; p; p = p->next) {
+ if (ERTS_PSFLG_FREE & erts_atomic32_read_nob(&p->state))
+ (*func)(p, arg);
+ }
+ }
+ }
+}
+
+void
+erts_debug_proc_monitor_link_foreach(Process *proc,
+ int (*monitor_func)(ErtsMonitor *, void *, Sint ),
+ int (*link_func)(ErtsLink *, void *, Sint ),
+ void *arg)
+{
+ if (!(erts_atomic32_read_nob(&proc->state) & ERTS_PSFLG_FREE)) {
+ /* For all links */
+ erts_link_tree_foreach(ERTS_P_LINKS(proc),
+ link_func,
+ arg);
+ /* For all monitors */
+ erts_monitor_tree_foreach(ERTS_P_MONITORS(proc),
+ monitor_func,
+ arg);
+ /* For all local target monitors */
+ erts_monitor_list_foreach(ERTS_P_LT_MONITORS(proc),
+ monitor_func,
+ arg);
+ }
+ else {
+ struct continue_exit_state *ce_state = proc->u.terminate;
+
+ /* For all links */
+ if (ce_state->phase == ERTS_CONTINUE_EXIT_LINKS)
+ erts_debug_link_tree_destroying_foreach(ce_state->links,
+ link_func,
+ arg,
+ ce_state->yield_state);
+ else
+ erts_link_tree_foreach(ce_state->links,
+ link_func,
+ arg);
+
+ /* For all monitors */
+ if (ce_state->phase == ERTS_CONTINUE_EXIT_MONITORS)
+ erts_debug_monitor_tree_destroying_foreach(ce_state->monitors,
+ monitor_func,
+ arg,
+ ce_state->yield_state);
+ else
+ erts_monitor_tree_foreach(ce_state->monitors,
+ monitor_func,
+ arg);
+
+ /* For all local target monitors */
+ if (ce_state->phase == ERTS_CONTINUE_EXIT_LT_MONITORS)
+ erts_debug_monitor_list_destroying_foreach(ce_state->lt_monitors,
+ monitor_func,
+ arg,
+ ce_state->yield_state);
+ else
+ erts_monitor_list_foreach(ce_state->lt_monitors,
+ monitor_func,
+ arg);
+
+ }
+}
diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h
index cdad72443f..f67f567705 100644
--- a/erts/emulator/beam/erl_process.h
+++ b/erts/emulator/beam/erl_process.h
@@ -701,6 +701,13 @@ void
erts_debug_later_op_foreach(void (*callback)(void*),
void (*func)(void *, ErtsThrPrgrVal, void *),
void *arg);
+void
+erts_debug_free_process_foreach(void (*func)(Process *, void *), void *arg);
+void
+erts_debug_proc_monitor_link_foreach(Process *proc,
+ int (*monitor_func)(ErtsMonitor *, void *, Sint ),
+ int (*link_func)(ErtsLink *, void *, Sint ),
+ void *arg);
#ifdef ERTS_INCLUDE_SCHEDULER_INTERNALS