aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r--erts/emulator/beam/erl_db.c32
-rw-r--r--erts/emulator/beam/erl_db.h10
-rw-r--r--erts/emulator/beam/erl_db_util.h2
-rw-r--r--erts/emulator/beam/erl_message.c2
-rw-r--r--erts/emulator/beam/erl_message.h26
-rw-r--r--erts/emulator/beam/erl_node_tables.c2
-rw-r--r--erts/emulator/beam/erl_process.c170
-rw-r--r--erts/emulator/beam/erl_process.h42
-rw-r--r--erts/emulator/beam/erl_thr_progress.h10
9 files changed, 187 insertions, 109 deletions
diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c
index 5bd8163968..4c30905495 100644
--- a/erts/emulator/beam/erl_db.c
+++ b/erts/emulator/beam/erl_db.c
@@ -224,8 +224,9 @@ Export ets_select_continue_exp;
static Export ets_delete_continue_exp;
static void
-free_dbtable(DbTable* tb)
+free_dbtable(void *vtb)
{
+ DbTable *tb = (DbTable *) vtb;
#ifdef HARDDEBUG
if (erts_smp_atomic_read_nob(&tb->common.memory_size) != sizeof(DbTable)) {
erts_fprintf(stderr, "ets: free_dbtable memory remain=%ld fix=%x\n",
@@ -251,20 +252,8 @@ free_dbtable(DbTable* tb)
ASSERT(is_immed(tb->common.heir_data));
erts_db_free(ERTS_ALC_T_DB_TABLE, tb, (void *) tb, sizeof(DbTable));
ERTS_ETS_MISC_MEM_ADD(-sizeof(DbTable));
- ERTS_SMP_MEMORY_BARRIER;
}
-#ifdef ERTS_SMP
-static void
-chk_free_dbtable(void *vtb)
-{
- DbTable * tb = (DbTable *) vtb;
- ERTS_THR_MEMORY_BARRIER;
- if (erts_refc_dectest(&tb->common.ref, 0) == 0)
- free_dbtable(tb);
-}
-#endif
-
static void schedule_free_dbtable(DbTable* tb)
{
/*
@@ -275,15 +264,10 @@ static void schedule_free_dbtable(DbTable* tb)
* need to unlock the table lock after this
* function has returned).
*/
-#ifdef ERTS_SMP
- int scheds = erts_get_max_no_executing_schedulers();
- ASSERT(scheds >= 1);
ASSERT(erts_refc_read(&tb->common.ref, 0) == 0);
- erts_refc_init(&tb->common.ref, scheds);
- erts_schedule_multi_misc_aux_work(0, scheds, chk_free_dbtable, tb);
-#else
- free_dbtable(tb);
-#endif
+ erts_schedule_thr_prgr_later_op(free_dbtable,
+ (void *) tb,
+ &tb->release.data);
}
static ERTS_INLINE void db_init_lock(DbTable* tb, int use_frequent_read_lock,
@@ -542,10 +526,6 @@ static int remove_named_tab(DbTable *tb, int have_lock)
&rwlock);
#ifdef ERTS_SMP
if (!have_lock && erts_smp_rwmtx_tryrwlock(rwlock) == EBUSY) {
- /*
- * We keep our increased refc over this op in order to
- * prevent the table from disapearing.
- */
db_unlock(tb, LCK_WRITE);
erts_smp_rwmtx_rwlock(rwlock);
db_lock(tb, LCK_WRITE);
@@ -1481,7 +1461,7 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2)
"** Too many db tables **\n");
free_heir_data(tb);
tb->common.meth->db_free_table(tb);
- free_dbtable(tb);
+ free_dbtable((void *) tb);
BIF_ERROR(BIF_P, SYSTEM_LIMIT);
}
diff --git a/erts/emulator/beam/erl_db.h b/erts/emulator/beam/erl_db.h
index 2e5deaf338..e9a661efbc 100644
--- a/erts/emulator/beam/erl_db.h
+++ b/erts/emulator/beam/erl_db.h
@@ -27,6 +27,10 @@
#define __DB_H__
#include "sys.h"
+#undef ERL_THR_PROGRESS_TSD_TYPE_ONLY
+#define ERL_THR_PROGRESS_TSD_TYPE_ONLY
+#include "erl_thr_progress.h"
+#undef ERL_THR_PROGRESS_TSD_TYPE_ONLY
#include "bif.h"
#include "erl_db_util.h" /* Flags */
@@ -36,6 +40,11 @@
Uint erts_get_ets_misc_mem_size(void);
+typedef struct {
+ DbTableCommon common;
+ ErtsThrPrgrLaterOp data;
+} DbTableRelease;
+
/*
* So, the structure for a database table, NB this is only
* interesting in db.c.
@@ -44,6 +53,7 @@ union db_table {
DbTableCommon common; /* Any type of db table */
DbTableHash hash; /* Linear hash array specific data */
DbTableTree tree; /* AVL tree specific data */
+ DbTableRelease release;
/*TT*/
};
diff --git a/erts/emulator/beam/erl_db_util.h b/erts/emulator/beam/erl_db_util.h
index ff5982640d..dcecc4251a 100644
--- a/erts/emulator/beam/erl_db_util.h
+++ b/erts/emulator/beam/erl_db_util.h
@@ -209,7 +209,7 @@ typedef struct db_fixation {
*/
typedef struct db_table_common {
- erts_refc_t ref; /* fixation counter and delete counter */
+ erts_refc_t ref; /* fixation counter */
#ifdef ERTS_SMP
erts_smp_rwmtx_t rwlock; /* rw lock on table */
erts_smp_mtx_t fixlock; /* Protects fixations,megasec,sec,microsec */
diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c
index 531144bc4f..e397f075d1 100644
--- a/erts/emulator/beam/erl_message.c
+++ b/erts/emulator/beam/erl_message.c
@@ -495,7 +495,7 @@ queue_message(Process *c_p,
#ifndef ERTS_SMP
res = receiver->msg.len;
#else
- res = receiver->msg_inq.len;
+ res = receiver->u.alive.msg_inq.len;
if (*receiver_locks & ERTS_PROC_LOCK_MAIN) {
/*
* We move 'in queue' to 'private queue' and place
diff --git a/erts/emulator/beam/erl_message.h b/erts/emulator/beam/erl_message.h
index bb4dbf0ef3..2ae94965b1 100644
--- a/erts/emulator/beam/erl_message.h
+++ b/erts/emulator/beam/erl_message.h
@@ -125,23 +125,23 @@ typedef struct {
#ifdef ERTS_SMP
/* Move in message queue to end of private message queue */
-#define ERTS_SMP_MSGQ_MV_INQ2PRIVQ(P) \
-do { \
- if ((P)->msg_inq.first) { \
- *(P)->msg.last = (P)->msg_inq.first; \
- (P)->msg.last = (P)->msg_inq.last; \
- (P)->msg.len += (P)->msg_inq.len; \
- (P)->msg_inq.first = NULL; \
- (P)->msg_inq.last = &(P)->msg_inq.first; \
- (P)->msg_inq.len = 0; \
- } \
+#define ERTS_SMP_MSGQ_MV_INQ2PRIVQ(P) \
+do { \
+ if ((P)->u.alive.msg_inq.first) { \
+ *(P)->msg.last = (P)->u.alive.msg_inq.first; \
+ (P)->msg.last = (P)->u.alive.msg_inq.last; \
+ (P)->msg.len += (P)->u.alive.msg_inq.len; \
+ (P)->u.alive.msg_inq.first = NULL; \
+ (P)->u.alive.msg_inq.last = &(P)->u.alive.msg_inq.first; \
+ (P)->u.alive.msg_inq.len = 0; \
+ } \
} while (0)
/* Add message last in message queue */
#define LINK_MESSAGE(p, mp) do { \
- *(p)->msg_inq.last = (mp); \
- (p)->msg_inq.last = &(mp)->next; \
- (p)->msg_inq.len++; \
+ *(p)->u.alive.msg_inq.last = (mp); \
+ (p)->u.alive.msg_inq.last = &(mp)->next; \
+ (p)->u.alive.msg_inq.len++; \
} while(0)
#else
diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c
index 649be3f454..606a0accf4 100644
--- a/erts/emulator/beam/erl_node_tables.c
+++ b/erts/emulator/beam/erl_node_tables.c
@@ -1332,7 +1332,7 @@ setup_reference_table(void)
proc->id);
}
#ifdef ERTS_SMP
- for (msg = proc->msg_inq.first; msg; msg = msg->next) {
+ for (msg = proc->u.alive.msg_inq.first; msg; msg = msg->next) {
ErlHeapFragment *heap_frag = NULL;
if (msg->data.attached) {
if (is_value(ERL_MESSAGE_TERM(msg)))
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index 8153cdce1c..c58bf40435 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -522,6 +522,7 @@ dbg_chk_aux_work_val(erts_aint32_t value)
valid |= ERTS_SSI_AUX_WORK_MISC_THR_PRGR;
valid |= ERTS_SSI_AUX_WORK_DD;
valid |= ERTS_SSI_AUX_WORK_DD_THR_PRGR;
+ valid |= ERTS_SSI_AUX_WORK_THR_PRGR_LATER_OP;
#endif
#if HAVE_ERTS_MSEG
valid |= ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK;
@@ -1653,6 +1654,74 @@ handle_delayed_dealloc_thr_prgr(ErtsAuxWorkData *awdp, erts_aint32_t aux_work)
return aux_work & ~ERTS_SSI_AUX_WORK_DD_THR_PRGR;
}
+/*
+ * Handle scheduled thread progress later operations.
+ */
+#define ERTS_MAX_THR_PRGR_LATER_OPS 50
+
+static ERTS_INLINE erts_aint32_t
+handle_thr_prgr_later_op(ErtsAuxWorkData *awdp, erts_aint32_t aux_work)
+{
+ int lops;
+ ErtsThrPrgrVal current = haw_thr_prgr_current(awdp);
+
+ for (lops = 0; lops < ERTS_MAX_THR_PRGR_LATER_OPS; lops++) {
+ ErtsThrPrgrLaterOp *lop = awdp->later_op.first;
+ if (!erts_thr_progress_has_reached_this(current, lop->later))
+ return aux_work & ~ERTS_SSI_AUX_WORK_THR_PRGR_LATER_OP;
+ awdp->later_op.first = lop->next;
+ lop->func(lop->data);
+ if (!awdp->later_op.first) {
+ awdp->later_op.last = NULL;
+ unset_aux_work_flags(awdp->ssi,
+ ERTS_SSI_AUX_WORK_THR_PRGR_LATER_OP);
+ return aux_work & ~ERTS_SSI_AUX_WORK_THR_PRGR_LATER_OP;
+ }
+ }
+
+ return aux_work;
+}
+
+#endif /* ERTS_SMP */
+
+void
+erts_schedule_thr_prgr_later_op(void (*later_func)(void *),
+ void *later_data,
+ ErtsThrPrgrLaterOp *lop)
+{
+#ifndef ERTS_SMP
+ later_func(later_data);
+#else
+ ErtsSchedulerData *esdp;
+ ErtsAuxWorkData *awdp;
+ int request_wakeup = 1;
+
+ esdp = erts_get_scheduler_data();
+ ASSERT(esdp);
+ awdp = &esdp->aux_work_data;
+
+ lop->func = later_func;
+ lop->data = later_data;
+ lop->later = erts_thr_progress_later(esdp);
+ lop->next = NULL;
+ if (!awdp->later_op.last)
+ awdp->later_op.first = lop;
+ else {
+ ErtsThrPrgrLaterOp *last = awdp->later_op.last;
+ last->next = lop;
+ if (erts_thr_progress_equal(last->later, lop->later))
+ request_wakeup = 0;
+ }
+ awdp->later_op.last = lop;
+ set_aux_work_flags_wakeup_nob(awdp->ssi,
+ ERTS_SSI_AUX_WORK_THR_PRGR_LATER_OP);
+ if (request_wakeup)
+ erts_thr_progress_wakeup(esdp, lop->later);
+#endif
+}
+
+#ifdef ERTS_SMP
+
static erts_atomic32_t completed_dealloc_count;
static void
@@ -1878,6 +1947,11 @@ handle_aux_work(ErtsAuxWorkData *awdp, erts_aint32_t orig_aux_work, int waiting)
| ERTS_SSI_AUX_WORK_FIX_ALLOC_DEALLOC),
handle_fix_alloc);
+#ifdef ERTS_SMP
+ HANDLE_AUX_WORK(ERTS_SSI_AUX_WORK_THR_PRGR_LATER_OP,
+ handle_thr_prgr_later_op);
+#endif
+
#if ERTS_USE_ASYNC_READY_Q
HANDLE_AUX_WORK(ERTS_SSI_AUX_WORK_ASYNC_READY,
handle_async_ready);
@@ -4596,6 +4670,8 @@ init_aux_work_data(ErtsAuxWorkData *awdp, ErtsSchedulerData *esdp, char *dawwp)
awdp->dd.thr_prgr = ERTS_THR_PRGR_VAL_WAITING;
awdp->dd.completed_callback = NULL;
awdp->dd.completed_arg = NULL;
+ awdp->later_op.first = NULL;
+ awdp->later_op.last = NULL;
#endif
#ifdef ERTS_USE_ASYNC_READY_Q
#ifdef ERTS_SMP
@@ -7781,9 +7857,9 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
p->reds = 0;
#ifdef ERTS_SMP
- p->u.ptimer = NULL;
+ p->u.alive.ptimer = NULL;
#else
- sys_memset(&p->u.tm, 0, sizeof(ErlTimer));
+ sys_memset(&p->u.alive.tm, 0, sizeof(ErlTimer));
#endif
p->reg = NULL;
@@ -7811,9 +7887,9 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
p->msg.save = &p->msg.first;
p->msg.len = 0;
#ifdef ERTS_SMP
- p->msg_inq.first = NULL;
- p->msg_inq.last = &p->msg_inq.first;
- p->msg_inq.len = 0;
+ p->u.alive.msg_inq.first = NULL;
+ p->u.alive.msg_inq.last = &p->u.alive.msg_inq.first;
+ p->u.alive.msg_inq.len = 0;
#endif
p->bif_timers = NULL;
p->mbuf = NULL;
@@ -7901,8 +7977,8 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
p->scheduler_data = NULL;
p->suspendee = NIL;
p->pending_suspenders = NULL;
- p->pending_exit.reason = THE_NON_VALUE;
- p->pending_exit.bp = NULL;
+ p->u.alive.pending_exit.reason = THE_NON_VALUE;
+ p->u.alive.pending_exit.bp = NULL;
#endif
#if !defined(NO_FPE_SIGNALS) || defined(HIPE)
@@ -7970,9 +8046,9 @@ void erts_init_empty_process(Process *p)
p->bin_old_vheap = 0;
p->bin_vheap_mature = 0;
#ifdef ERTS_SMP
- p->u.ptimer = NULL;
+ p->u.alive.ptimer = NULL;
#else
- memset(&(p->u.tm), 0, sizeof(ErlTimer));
+ memset(&(p->u.alive.tm), 0, sizeof(ErlTimer));
#endif
p->next = NULL;
p->off_heap.first = NULL;
@@ -8040,13 +8116,13 @@ void erts_init_empty_process(Process *p)
#ifdef ERTS_SMP
p->scheduler_data = NULL;
- p->msg_inq.first = NULL;
- p->msg_inq.last = &p->msg_inq.first;
- p->msg_inq.len = 0;
+ p->u.alive.msg_inq.first = NULL;
+ p->u.alive.msg_inq.last = &p->u.alive.msg_inq.first;
+ p->u.alive.msg_inq.len = 0;
p->suspendee = NIL;
p->pending_suspenders = NULL;
- p->pending_exit.reason = THE_NON_VALUE;
- p->pending_exit.bp = NULL;
+ p->u.alive.pending_exit.reason = THE_NON_VALUE;
+ p->u.alive.pending_exit.bp = NULL;
erts_proc_lock_init(p);
erts_smp_proc_unlock(p, ERTS_PROC_LOCKS_ALL);
RUNQ_SET_RQ(&p->run_queue, ERTS_RUNQ_IX(0));
@@ -8096,12 +8172,12 @@ erts_debug_verify_clean_empty_process(Process* p)
ASSERT(p->parent == NIL);
#ifdef ERTS_SMP
- ASSERT(p->msg_inq.first == NULL);
- ASSERT(p->msg_inq.len == 0);
+ ASSERT(p->u.alive.msg_inq.first == NULL);
+ ASSERT(p->u.alive.msg_inq.len == 0);
ASSERT(p->suspendee == NIL);
ASSERT(p->pending_suspenders == NULL);
- ASSERT(p->pending_exit.reason == THE_NON_VALUE);
- ASSERT(p->pending_exit.bp == NULL);
+ ASSERT(p->u.alive.pending_exit.reason == THE_NON_VALUE);
+ ASSERT(p->u.alive.pending_exit.bp == NULL);
#endif
/* Thing that erts_cleanup_empty_process() cleans up */
@@ -8282,7 +8358,7 @@ void
erts_handle_pending_exit(Process *c_p, ErtsProcLocks locks)
{
ErtsProcLocks xlocks;
- ASSERT(is_value(c_p->pending_exit.reason));
+ ASSERT(is_value(c_p->u.alive.pending_exit.reason));
ERTS_SMP_LC_ASSERT(erts_proc_lc_my_proc_locks(c_p) == locks);
ERTS_SMP_LC_ASSERT(locks & ERTS_PROC_LOCK_MAIN);
ERTS_SMP_LC_ASSERT(!((ERTS_PSFLG_EXITING|ERTS_PSFLG_FREE)
@@ -8301,10 +8377,10 @@ erts_handle_pending_exit(Process *c_p, ErtsProcLocks locks)
set_proc_exiting(c_p,
erts_smp_atomic32_read_acqb(&c_p->state),
- c_p->pending_exit.reason,
- c_p->pending_exit.bp);
- c_p->pending_exit.reason = THE_NON_VALUE;
- c_p->pending_exit.bp = NULL;
+ c_p->u.alive.pending_exit.reason,
+ c_p->u.alive.pending_exit.bp);
+ c_p->u.alive.pending_exit.reason = THE_NON_VALUE;
+ c_p->u.alive.pending_exit.bp = NULL;
if (xlocks)
erts_smp_proc_unlock(c_p, xlocks);
@@ -8525,7 +8601,7 @@ send_exit_signal(Process *c_p, /* current process if and only
else if (reason != am_normal || (flags & ERTS_XSIG_FLG_NO_IGN_NORMAL)) {
#ifdef ERTS_SMP
if (!(state & (ERTS_PSFLG_EXITING|ERTS_PSFLG_PENDING_EXIT))) {
- ASSERT(!rp->pending_exit.bp);
+ ASSERT(!rp->u.alive.pending_exit.bp);
if (rp == c_p && (*rp_locks & ERTS_PROC_LOCK_MAIN)) {
/* Ensure that all locks on c_p are locked before
@@ -8575,7 +8651,7 @@ send_exit_signal(Process *c_p, /* current process if and only
set_pending_exit:
if (is_immed(rsn)) {
- rp->pending_exit.reason = rsn;
+ rp->u.alive.pending_exit.reason = rsn;
}
else {
Eterm *hp;
@@ -8583,11 +8659,11 @@ send_exit_signal(Process *c_p, /* current process if and only
ErlHeapFragment *bp = new_message_buffer(sz);
hp = &bp->mem[0];
- rp->pending_exit.reason = copy_struct(rsn,
- sz,
- &hp,
- &bp->off_heap);
- rp->pending_exit.bp = bp;
+ rp->u.alive.pending_exit.reason = copy_struct(rsn,
+ sz,
+ &hp,
+ &bp->off_heap);
+ rp->u.alive.pending_exit.bp = bp;
}
erts_smp_atomic32_read_bor_relb(&rp->state,
ERTS_PSFLG_PENDING_EXIT);
@@ -8959,10 +9035,10 @@ erts_do_exit_process(Process* p, Eterm reason)
state = set_proc_exiting_state(p, erts_smp_atomic32_read_nob(&p->state));
if (state & ERTS_PSFLG_PENDING_EXIT) {
/* Process exited before pending exit was received... */
- p->pending_exit.reason = THE_NON_VALUE;
- if (p->pending_exit.bp) {
- free_message_buffer(p->pending_exit.bp);
- p->pending_exit.bp = NULL;
+ p->u.alive.pending_exit.reason = THE_NON_VALUE;
+ if (p->u.alive.pending_exit.bp) {
+ free_message_buffer(p->u.alive.pending_exit.bp);
+ p->u.alive.pending_exit.bp = NULL;
}
}
@@ -9209,21 +9285,9 @@ erts_continue_exit_process(Process *p)
delete_process(p);
#ifdef ERTS_SMP
- /*
- * Each scheduler will decrease refc by one via misc aux work;
- * we have one refc for reference from process table which we
- * now want to remove, i.e. we increase refc with schedulers-1.
- *
- * Process struct wont be deallocated until (earliest) when
- * all schedulers have decreased refc via misc aux work...
- */
- if (erts_no_schedulers != 1)
- erts_smp_proc_add_refc(p, (Sint32) erts_no_schedulers-1);
- erts_schedule_multi_misc_aux_work(0,
- erts_no_schedulers,
- proc_dec_refc,
- (void *) p);
-
+ erts_schedule_thr_prgr_later_op(proc_dec_refc,
+ (void *) p,
+ &p->u.release_data);
erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);
ERTS_SMP_CHK_HAVE_ONLY_MAIN_PROC_LOCK(p);
#endif
@@ -9275,9 +9339,9 @@ cancel_timer(Process* p)
ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(p));
p->flags &= ~(F_INSLPQUEUE|F_TIMO);
#ifdef ERTS_SMP
- erts_cancel_smp_ptimer(p->u.ptimer);
+ erts_cancel_smp_ptimer(p->u.alive.ptimer);
#else
- erts_cancel_timer(&p->u.tm);
+ erts_cancel_timer(&p->u.alive.tm);
#endif
}
@@ -9298,12 +9362,12 @@ set_timer(Process* p, Uint timeout)
p->flags &= ~F_TIMO;
#ifdef ERTS_SMP
- erts_create_smp_ptimer(&p->u.ptimer,
+ erts_create_smp_ptimer(&p->u.alive.ptimer,
p->id,
(ErlTimeoutProc) timeout_proc,
timeout);
#else
- erts_set_timer(&p->u.tm,
+ erts_set_timer(&p->u.alive.tm,
(ErlTimeoutProc) timeout_proc,
NULL,
(void*) p,
diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h
index b8b137f413..1436e246d6 100644
--- a/erts/emulator/beam/erl_process.h
+++ b/erts/emulator/beam/erl_process.h
@@ -275,16 +275,17 @@ typedef enum {
#define ERTS_SSI_AUX_WORK_DD_THR_PRGR (((erts_aint32_t) 1) << 2)
#define ERTS_SSI_AUX_WORK_FIX_ALLOC_DEALLOC (((erts_aint32_t) 1) << 3)
#define ERTS_SSI_AUX_WORK_FIX_ALLOC_LOWER_LIM (((erts_aint32_t) 1) << 4)
-#define ERTS_SSI_AUX_WORK_ASYNC_READY (((erts_aint32_t) 1) << 5)
-#define ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN (((erts_aint32_t) 1) << 6)
-#define ERTS_SSI_AUX_WORK_MISC_THR_PRGR (((erts_aint32_t) 1) << 7)
-#define ERTS_SSI_AUX_WORK_MISC (((erts_aint32_t) 1) << 8)
-#define ERTS_SSI_AUX_WORK_CHECK_CHILDREN (((erts_aint32_t) 1) << 9)
-#define ERTS_SSI_AUX_WORK_SET_TMO (((erts_aint32_t) 1) << 10)
-#define ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK (((erts_aint32_t) 1) << 11)
-#define ERTS_SSI_AUX_WORK_CODE_IX_ACTIVATION (((erts_aint32_t) 1) << 12)
-#define ERTS_SSI_AUX_WORK_REAP_PORTS (((erts_aint32_t) 1) << 13)
-#define ERTS_SSI_AUX_WORK_FINISH_BP (((erts_aint32_t) 1) << 14)
+#define ERTS_SSI_AUX_WORK_THR_PRGR_LATER_OP (((erts_aint32_t) 1) << 5)
+#define ERTS_SSI_AUX_WORK_ASYNC_READY (((erts_aint32_t) 1) << 6)
+#define ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN (((erts_aint32_t) 1) << 7)
+#define ERTS_SSI_AUX_WORK_MISC_THR_PRGR (((erts_aint32_t) 1) << 8)
+#define ERTS_SSI_AUX_WORK_MISC (((erts_aint32_t) 1) << 9)
+#define ERTS_SSI_AUX_WORK_CHECK_CHILDREN (((erts_aint32_t) 1) << 10)
+#define ERTS_SSI_AUX_WORK_SET_TMO (((erts_aint32_t) 1) << 11)
+#define ERTS_SSI_AUX_WORK_MSEG_CACHE_CHECK (((erts_aint32_t) 1) << 12)
+#define ERTS_SSI_AUX_WORK_CODE_IX_ACTIVATION (((erts_aint32_t) 1) << 13)
+#define ERTS_SSI_AUX_WORK_REAP_PORTS (((erts_aint32_t) 1) << 14)
+#define ERTS_SSI_AUX_WORK_FINISH_BP (((erts_aint32_t) 1) << 15)
typedef struct ErtsSchedulerSleepInfo_ ErtsSchedulerSleepInfo;
@@ -463,6 +464,10 @@ typedef struct {
void (*completed_callback)(void *);
void (*completed_arg)(void *);
} dd;
+ struct {
+ ErtsThrPrgrLaterOp *first;
+ ErtsThrPrgrLaterOp *last;
+ } later_op;
#endif
#ifdef ERTS_USE_ASYNC_READY_Q
struct {
@@ -860,10 +865,17 @@ struct process {
Uint64 bin_old_vheap; /* Virtual old heap size for binaries */
union {
+ struct {
#ifdef ERTS_SMP
- ErtsSmpPTimer *ptimer;
+ ErtsSmpPTimer *ptimer;
+ ErlMessageInQueue msg_inq;
+ ErtsPendExit pending_exit;
#else
- ErlTimer tm; /* Timer entry */
+ ErlTimer tm; /* Timer entry */
+#endif
+ } alive; /* when process is alive */
+#ifdef ERTS_SMP
+ ErtsThrPrgrLaterOp release_data; /* when releasing process struct */
#endif
void *exit_data; /* Misc data referred during termination */
} u;
@@ -873,10 +885,8 @@ struct process {
#ifdef ERTS_SMP
erts_proc_lock_t lock;
ErtsSchedulerData *scheduler_data;
- ErlMessageInQueue msg_inq;
Eterm suspendee;
ErtsPendingSuspend *pending_suspenders;
- ErtsPendExit pending_exit;
erts_smp_atomic_t run_queue;
#ifdef HIPE
struct hipe_process_state_smp hipe_smp;
@@ -1175,6 +1185,10 @@ int erts_sched_set_wakeup_other_thresold(char *str);
int erts_sched_set_wakeup_other_type(char *str);
int erts_sched_set_busy_wait_threshold(char *str);
+void erts_schedule_thr_prgr_later_op(void (*)(void *),
+ void *,
+ ErtsThrPrgrLaterOp *);
+
#if defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK)
int erts_dbg_check_halloc_lock(Process *p);
#endif
diff --git a/erts/emulator/beam/erl_thr_progress.h b/erts/emulator/beam/erl_thr_progress.h
index 89486b065b..e72321cf48 100644
--- a/erts/emulator/beam/erl_thr_progress.h
+++ b/erts/emulator/beam/erl_thr_progress.h
@@ -78,6 +78,16 @@ void erts_thr_progress_fatal_error_block(SWord timeout,
#endif /* ERTS_SMP */
+typedef struct ErtsThrPrgrLaterOp_ ErtsThrPrgrLaterOp;
+struct ErtsThrPrgrLaterOp_ {
+#ifdef ERTS_SMP
+ ErtsThrPrgrVal later;
+#endif
+ void (*func)(void *);
+ void *data;
+ ErtsThrPrgrLaterOp *next;
+};
+
#endif
#if !defined(ERL_THR_PROGRESS_H__) && !defined(ERL_THR_PROGRESS_TSD_TYPE_ONLY)