void erts_thr_progress_active(ErtsSchedulerData *esdp, int on) { ErtsThrPrgrData *tpd = thr_prgr_data(esdp); #ifdef ERTS_ENABLE_LOCK_CHECK erts_lc_check_exact(NULL, 0); #endif ERTS_THR_PROGRESS_STATE_DEBUG_SET_ACTIVE(tpd->id, on); if (on) { ASSERT(!tpd->active); tpd->active = 1; erts_atomic32_inc_nob(&intrnl->misc.data.lflgs); } else { ASSERT(tpd->active); tpd->active = 0; erts_atomic32_dec_nob(&intrnl->misc.data.lflgs); if (update(tpd)) leader_update(tpd); } #ifdef DEBUG { erts_aint32_t n = erts_atomic32_read_nob(&intrnl->misc.data.lflgs); n &= ERTS_THR_PRGR_LFLG_ACTIVE_MASK; ASSERT(tpd->active <= n && n <= intrnl->managed.no); } #endif }
void erts_thr_progress_unblock(void) { erts_tse_t *event; int id, break_id, sz, wakeup; ErtsThrPrgrData *tpd = thr_prgr_data(NULL); ASSERT(tpd->is_blocking); if (--tpd->is_blocking) return; sz = intrnl->managed.no; wakeup = 1; if (!tpd->is_managed) id = break_id = tpd->id < 0 ? 0 : tpd->id % sz; else { break_id = tpd->id; id = break_id + 1; if (id >= sz) id = 0; if (id == break_id) wakeup = 0; erts_atomic32_inc_nob(&intrnl->misc.data.block_count); } event = ((erts_tse_t *) erts_atomic_read_nob(&intrnl->misc.data.blocker_event)); ASSERT(event); erts_atomic_set_nob(&intrnl->misc.data.blocker_event, ERTS_AINT_NULL); erts_atomic32_read_bor_relb(&intrnl->misc.data.block_count, ERTS_THR_PRGR_BC_FLG_NOT_BLOCKING); #if ERTS_THR_PRGR_PRINT_BLOCKERS erts_fprintf(stderr, "unblock(%d)\n", tpd->id); #endif erts_atomic32_read_band_mb(&intrnl->misc.data.lflgs, ~ERTS_THR_PRGR_LFLG_BLOCK); if (wakeup) { do { ErtsThrPrgrVal tmp; tmp = read_nob(&intrnl->thr[id].data.current); if (tmp != ERTS_THR_PRGR_VAL_WAITING) wakeup_managed(id); if (++id >= sz) id = 0; } while (id != break_id); } return_tmp_thr_prgr_data(tpd); erts_tse_return(event); }
void erts_thr_progress_register_managed_thread(ErtsSchedulerData *esdp, ErtsThrPrgrCallbacks *callbacks, int pref_wakeup) { ErtsThrPrgrData *tpd = perhaps_thr_prgr_data(NULL); int is_blocking = 0, managed; if (tpd) { if (!tpd->is_temporary) erl_exit(ERTS_ABORT_EXIT, "%s:%d:%s(): Double register of thread\n", __FILE__, __LINE__, __func__); is_blocking = tpd->is_blocking; return_tmp_thr_prgr_data(tpd); } if (esdp) tpd = &esdp->thr_progress_data; else tpd = erts_alloc(ERTS_ALC_T_THR_PRGR_DATA, sizeof(ErtsThrPrgrData)); if (pref_wakeup && !erts_atomic32_xchg_nob(&intrnl->misc.data.pref_wakeup_used, 1)) tpd->id = 0; else if (esdp) tpd->id = (int) esdp->no; else tpd->id = erts_atomic32_inc_read_nob(&intrnl->misc.data.managed_id); ASSERT(tpd->id >= 0); if (tpd->id >= intrnl->managed.no) erl_exit(ERTS_ABORT_EXIT, "%s:%d:%s(): Too many managed registered threads\n", __FILE__, __LINE__, __func__); tpd->is_managed = 1; tpd->is_blocking = is_blocking; tpd->is_temporary = 0; #ifdef ERTS_ENABLE_LOCK_CHECK tpd->is_delaying = 1; #endif init_wakeup_request_array(&tpd->wakeup_request[0]); ERTS_THR_PROGRESS_STATE_DEBUG_INIT(tpd->id); tpd->leader = 0; tpd->active = 1; tpd->confirmed = 0; tpd->leader_state.current = ERTS_THR_PRGR_VAL_WAITING; erts_tsd_set(erts_thr_prgr_data_key__, (void *) tpd); erts_atomic32_inc_nob(&intrnl->misc.data.lflgs); ASSERT(callbacks->wakeup); ASSERT(callbacks->prepare_wait); ASSERT(callbacks->wait); ASSERT(callbacks->finalize_wait); intrnl->managed.callbacks[tpd->id] = *callbacks; callbacks->prepare_wait(callbacks->arg); managed = erts_atomic32_inc_read_relb(&intrnl->misc.data.managed_count); if (managed != intrnl->managed.no) { /* Wait until all managed threads have registered... */ do { callbacks->wait(callbacks->arg); callbacks->prepare_wait(callbacks->arg); managed = erts_atomic32_read_acqb(&intrnl->misc.data.managed_count); } while (managed != intrnl->managed.no); } else { int id; /* All managed threads have registered; lets go... */ for (id = 0; id < managed; id++) if (id != tpd->id) wakeup_managed(id); } callbacks->finalize_wait(callbacks->arg); }
void erts_ddll_increment_port_count(DE_Handle *dh) { assert_drv_list_locked(); erts_atomic32_inc_nob(&dh->port_count); }