aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/erl_process.c
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2012-02-15 15:12:18 +0100
committerSverker Eriksson <[email protected]>2012-02-21 15:32:07 +0100
commitdc2b0ecba50cbe6b2f2321b1f24579a0353ced18 (patch)
tree0ad297a07792533c1d2820c5ca69a886f3239e03 /erts/emulator/beam/erl_process.c
parentc4a8cc5914157c70ced742d957ec0e8d9c618164 (diff)
downloadotp-dc2b0ecba50cbe6b2f2321b1f24579a0353ced18.tar.gz
otp-dc2b0ecba50cbe6b2f2321b1f24579a0353ced18.tar.bz2
otp-dc2b0ecba50cbe6b2f2321b1f24579a0353ced18.zip
erts: Activate staged code in a thread safe way
Activation of staged code is scheduled for a later moment when all schedulers have done a full memory barrier. This allow them to read active code index while executing without any memory barriers at all.
Diffstat (limited to 'erts/emulator/beam/erl_process.c')
-rw-r--r--erts/emulator/beam/erl_process.c53
1 files changed, 51 insertions, 2 deletions
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index 44a99e1f84..aaee951107 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -366,6 +366,9 @@ dbg_chk_aux_work_val(erts_aint32_t value)
#ifdef ERTS_SMP_SCHEDULERS_NEED_TO_CHECK_CHILDREN
valid |= ERTS_SSI_AUX_WORK_CHECK_CHILDREN;
#endif
+#ifdef ERTS_SMP
+ valid |= ERTS_SSI_AUX_WORK_CODE_IX_ACTIVATION;
+#endif
if (~valid & value)
erl_exit(ERTS_ABORT_EXIT,
@@ -861,7 +864,7 @@ set_aux_work_flags_wakeup_nob(ErtsSchedulerSleepInfo *ssi,
}
}
-#if 0 /* Currently not used */
+#ifdef ERTS_SMP
static ERTS_INLINE void
set_aux_work_flags_wakeup_relb(ErtsSchedulerSleepInfo *ssi,
@@ -882,7 +885,7 @@ set_aux_work_flags_wakeup_relb(ErtsSchedulerSleepInfo *ssi,
}
}
-#endif
+#endif /* ERTS_SMP */
static ERTS_INLINE erts_aint32_t
set_aux_work_flags(ErtsSchedulerSleepInfo *ssi, erts_aint32_t flgs)
@@ -1145,7 +1148,49 @@ handle_async_ready_clean(ErtsAuxWorkData *awdp,
}
}
+#endif /* ERTS_USE_ASYNC_READY_Q */
+
+#ifdef ERTS_SMP
+void
+erts_notify_code_ix_activation(Process* p, ErtsThrPrgrVal later)
+{
+ ErtsAuxWorkData* awdp = &p->scheduler_data->aux_work_data;
+ ASSERT(awdp->code_ix_activation.code_stager == NULL);
+ awdp->code_ix_activation.code_stager = p;
+ awdp->code_ix_activation.thr_prgr = later;
+ erts_smp_proc_inc_refc(p);
+ set_aux_work_flags_wakeup_relb(p->scheduler_data->ssi,
+ ERTS_SSI_AUX_WORK_CODE_IX_ACTIVATION);
+}
+
+static erts_aint32_t
+handle_code_ix_activation(ErtsAuxWorkData *awdp, erts_aint32_t aux_work)
+{
+ Process* p;
+ if (!erts_thr_progress_has_reached(awdp->code_ix_activation.thr_prgr)) {
+ return aux_work & ~ERTS_SSI_AUX_WORK_CODE_IX_ACTIVATION;
+ }
+ unset_aux_work_flags(awdp->ssi, ERTS_SSI_AUX_WORK_CODE_IX_ACTIVATION);
+ p = awdp->code_ix_activation.code_stager;
+ ASSERT(p);
+#ifdef DEBUG
+ awdp->code_ix_activation.code_stager = NULL;
#endif
+ erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS);
+ if (!ERTS_PROC_IS_EXITING(p)) {
+ erts_activate_staging_code_ix();
+ erts_resume(p, ERTS_PROC_LOCK_STATUS);
+ erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
+ }
+ else {
+ erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS);
+ erts_abort_staging_code_ix();
+ }
+ erts_unlock_code_ix();
+ erts_smp_proc_dec_refc(p);
+ return aux_work & ~ERTS_SSI_AUX_WORK_CODE_IX_ACTIVATION;
+}
+#endif /* ERTS_SMP */
static ERTS_INLINE erts_aint32_t
handle_fix_alloc(ErtsAuxWorkData *awdp, erts_aint32_t aux_work)
@@ -1451,6 +1496,10 @@ handle_aux_work(ErtsAuxWorkData *awdp, erts_aint32_t orig_aux_work)
handle_mseg_cache_check);
#endif
+#ifdef ERTS_SMP
+ HANDLE_AUX_WORK(ERTS_SSI_AUX_WORK_CODE_IX_ACTIVATION,
+ handle_code_ix_activation);
+#endif
ERTS_DBG_CHK_AUX_WORK_VAL(aux_work);
return aux_work;