int micro_delay(u32_t micros) { u64_t start, delta, delta_end; Hz = sys_hz(); /* Start of delay. */ read_frclock_64(&start); assert(_minix_kerninfo->minix_arm_frclock_hz); delta_end = (_minix_kerninfo->minix_arm_frclock_hz * micros) / MICROHZ; /* If we have to wait for at least one HZ tick, use the regular * tickdelay first. Round downwards on purpose, so the average * half-tick we wait short (depending on where in the current tick * we call tickdelay). We can correct for both overhead of tickdelay * itself and the short wait in the busywait later. */ if (micros >= MICROSPERTICK(Hz)) tickdelay(micros*Hz/MICROHZ); /* Wait (the rest) of the delay time using busywait. */ do { read_frclock_64(&delta); } while (delta_frclock_64(start, delta) < delta_end); return 0; }
int spin_check(spin_t *s) { /* Check whether a timeout has taken place. Return TRUE if the caller * should continue spinning, and FALSE if a timeout has occurred. The * implementation assumes that it is okay to spin a little bit too long * (up to a full clock tick extra). */ u64_t cur_tsc, tsc_delta; clock_t now, micro_delta; switch (s->s_state) { case STATE_INIT: s->s_state = STATE_BASE_TS; break; case STATE_BASE_TS: s->s_state = STATE_TS; read_frclock_64(&s->s_base_tsc); break; case STATE_TS: read_frclock_64(&cur_tsc); tsc_delta = delta_frclock_64(s->s_base_tsc, cur_tsc); micro_delta = frclock_64_to_micros(tsc_delta); if (micro_delta >= s->s_usecs) { s->s_timeout = TRUE; return FALSE; } if (micro_delta >= TSC_SPIN) { s->s_usecs -= micro_delta; s->s_base_uptime = getticks(); s->s_state = STATE_UPTIME; } break; case STATE_UPTIME: now = getticks(); /* We assume that sys_hz() caches its return value. */ micro_delta = ((now - s->s_base_uptime) * 1000 / sys_hz()) * 1000; if (micro_delta >= s->s_usecs) { s->s_timeout = TRUE; return FALSE; } break; default: panic("spin_check: invalid state %d", s->s_state); } return TRUE; }
static int keep_displaying_restarted() { u64_t delta; u32_t micro_delta; read_frclock_64(&has_restarted_t2); delta = delta_frclock_64(has_restarted_t1, has_restarted_t2); micro_delta = frclock_64_to_micros(delta); #define DISPLAY_1SEC 1000000 /* 1 second in microseconds */ if (micro_delta < DISPLAY_1SEC) { return 1; } has_restarted = 0; return 0; }