void erts_thr_progress_fatal_error_wait(SWord timeout) { erts_aint32_t bc; SWord time_left = timeout; ErtsMonotonicTime timeout_time; ErtsSchedulerData *esdp = erts_get_scheduler_data(); /* * Counting poll intervals may give us a too long timeout * if cpu is busy. We use timeout time to try to prevent * this. In case we havn't got time correction this may * however fail too... */ timeout_time = erts_get_monotonic_time(esdp); timeout_time += ERTS_MSEC_TO_MONOTONIC((ErtsMonotonicTime) timeout); while (1) { if (erts_milli_sleep(ERTS_THR_PRGR_FTL_ERR_BLCK_POLL_INTERVAL) == 0) time_left -= ERTS_THR_PRGR_FTL_ERR_BLCK_POLL_INTERVAL; bc = erts_atomic32_read_acqb(&intrnl->misc.data.block_count); if (bc == 0) break; /* Succefully blocked all managed threads */ if (time_left <= 0) break; /* Timeout */ if (timeout_time <= erts_get_monotonic_time(esdp)) break; /* Timeout */ } }
void erts_p_slpq(void) { erts_printf("Not yet implemented...\n"); #if 0 ErtsMonotonicTime current_time = erts_get_monotonic_time(NULL); int i; ErtsTWheelTimer* p; /* print the whole wheel, starting at the current position */ erts_printf("\ncurrent time = %bps tiw_pos = %d tiw_nto %d\n", current_time, tiw->pos, tiw->nto); i = tiw->pos; if (tiw->w[i] != NULL) { erts_printf("%d:\n", i); for(p = tiw->w[i]; p != NULL; p = p->next) { erts_printf(" (timeout time %bps, slot %d)\n", ERTS_CLKTCKS_TO_MONOTONIC(p->timeout_pos), p->slot); } } for(i = ((i+1) & (ERTS_TIW_SIZE-1)); i != (tiw->pos & (ERTS_TIW_SIZE-1)); i = ((i+1) & (ERTS_TIW_SIZE-1))) { if (tiw->w[i] != NULL) { erts_printf("%d:\n", i); for(p = tiw->w[i]; p != NULL; p = p->next) { erts_printf(" (timeout time %bps, slot %d)\n", ERTS_CLKTCKS_TO_MONOTONIC(p->timeout_pos), p->slot); } } } #endif }
ErtsTimerWheel * erts_create_timer_wheel(ErtsSchedulerData *esdp) { ErtsMonotonicTime mtime; int i; ErtsTimerWheel *tiw; tiw = erts_alloc_permanent_cache_aligned(ERTS_ALC_T_TIMER_WHEEL, sizeof(ErtsTimerWheel)); for(i = 0; i < ERTS_TIW_SIZE; i++) tiw->w[i] = NULL; mtime = erts_get_monotonic_time(esdp); tiw->pos = ERTS_MONOTONIC_TO_CLKTCKS(mtime); tiw->nto = 0; tiw->at_once.head = NULL; tiw->at_once.tail = NULL; tiw->at_once.nto = 0; tiw->yield_slot = ERTS_TWHEEL_SLOT_INACTIVE; tiw->true_next_timeout_time = 0; tiw->next_timeout_time = mtime + ERTS_MONOTONIC_DAY; tiw->sentinel.next = &tiw->sentinel; tiw->sentinel.prev = &tiw->sentinel; tiw->sentinel.u.func.timeout = NULL; tiw->sentinel.u.func.cancel = NULL; tiw->sentinel.u.func.arg = NULL; return tiw; }
static int ms_wait(Process *c_p, Eterm etimeout, int busy) { ErtsSchedulerData *esdp = erts_proc_sched_data(c_p); ErtsMonotonicTime time, timeout_time; Sint64 ms; if (!term_to_Sint64(etimeout, &ms)) return 0; time = erts_get_monotonic_time(esdp); if (ms < 0) timeout_time = time; else timeout_time = time + ERTS_MSEC_TO_MONOTONIC(ms); while (time < timeout_time) { if (busy) erts_thr_yield(); else { ErtsMonotonicTime timeout = timeout_time - time; #ifdef __WIN32__ Sleep((DWORD) ERTS_MONOTONIC_TO_MSEC(timeout)); #else { ErtsMonotonicTime to = ERTS_MONOTONIC_TO_USEC(timeout); struct timeval tv; tv.tv_sec = (long) to / (1000*1000); tv.tv_usec = (long) to % (1000*1000); select(0, NULL, NULL, NULL, &tv); } #endif } time = erts_get_monotonic_time(esdp); } return 1; }
static ERTS_INLINE ErtsMonotonicTime get_mtime(Process *c_p) { return erts_get_monotonic_time(erts_proc_sched_data(c_p)); }
static ERTS_INLINE ErtsMonotonicTime find_next_timeout(ErtsSchedulerData *esdp, ErtsTimerWheel *tiw, int search_all, ErtsMonotonicTime curr_time, /* When !search_all */ ErtsMonotonicTime max_search_time) /* When !search_all */ { int start_ix, tiw_pos_ix; ErtsTWheelTimer *p; int true_min_timeout = 0; ErtsMonotonicTime min_timeout, min_timeout_pos, slot_timeout_pos; if (tiw->nto == 0) { /* no timeouts in wheel */ if (!search_all) min_timeout_pos = tiw->pos; else { curr_time = erts_get_monotonic_time(esdp); tiw->pos = min_timeout_pos = ERTS_MONOTONIC_TO_CLKTCKS(curr_time); } min_timeout_pos += ERTS_MONOTONIC_TO_CLKTCKS(ERTS_MONOTONIC_DAY); goto found_next; } slot_timeout_pos = min_timeout_pos = tiw->pos; if (search_all) min_timeout_pos += ERTS_MONOTONIC_TO_CLKTCKS(ERTS_MONOTONIC_DAY); else min_timeout_pos = ERTS_MONOTONIC_TO_CLKTCKS(curr_time + max_search_time); start_ix = tiw_pos_ix = (int) (tiw->pos & (ERTS_TIW_SIZE-1)); do { if (++slot_timeout_pos >= min_timeout_pos) break; p = tiw->w[tiw_pos_ix]; if (p) { ErtsTWheelTimer *end = p; do { ErtsMonotonicTime timeout_pos; timeout_pos = p->timeout_pos; if (min_timeout_pos > timeout_pos) { true_min_timeout = 1; min_timeout_pos = timeout_pos; if (min_timeout_pos <= slot_timeout_pos) goto found_next; } p = p->next; } while (p != end); } tiw_pos_ix++; if (tiw_pos_ix == ERTS_TIW_SIZE) tiw_pos_ix = 0; } while (start_ix != tiw_pos_ix); found_next: min_timeout = ERTS_CLKTCKS_TO_MONOTONIC(min_timeout_pos); tiw->next_timeout_time = min_timeout; tiw->true_next_timeout_time = true_min_timeout; return min_timeout; }