void Delay_usec(uint32 usec) { int was_error; #if defined(USE_NANOSLEEP) struct timespec elapsed, tv; #elif defined(USE_COND_TIMEDWAIT) // Use a local mutex and cv, so threads remain independent pthread_cond_t delay_cond = PTHREAD_COND_INITIALIZER; pthread_mutex_t delay_mutex = PTHREAD_MUTEX_INITIALIZER; struct timespec elapsed; uint64 future; #else struct timeval tv; #ifndef SELECT_SETS_REMAINING uint64 then, now, elapsed; #endif #endif // Set the timeout interval - Linux only needs to do this once #if defined(SELECT_SETS_REMAINING) tv.tv_sec = 0; tv.tv_usec = usec; #elif defined(USE_NANOSLEEP) elapsed.tv_sec = 0; elapsed.tv_nsec = usec * 1000; #elif defined(USE_COND_TIMEDWAIT) future = GetTicks_usec() + usec; elapsed.tv_sec = future / 1000000; elapsed.tv_nsec = (future % 1000000) * 1000; #else then = GetTicks_usec(); #endif do { errno = 0; #if defined(USE_NANOSLEEP) tv.tv_sec = elapsed.tv_sec; tv.tv_nsec = elapsed.tv_nsec; was_error = nanosleep(&tv, &elapsed); #elif defined(USE_COND_TIMEDWAIT) was_error = pthread_mutex_lock(&delay_mutex); was_error = pthread_cond_timedwait(&delay_cond, &delay_mutex, &elapsed); was_error = pthread_mutex_unlock(&delay_mutex); #else #ifndef SELECT_SETS_REMAINING // Calculate the time interval left (in case of interrupt) now = GetTicks_usec(); elapsed = now - then; then = now; if (elapsed >= usec) break; usec -= elapsed; tv.tv_sec = 0; tv.tv_usec = usec; #endif was_error = select(0, NULL, NULL, NULL, &tv); #endif } while (was_error && (errno == EINTR)); }
static DWORD WINAPI tick_func(void *arg) { int tick_counter = 0; uint64 start = GetTicks_usec(); int64 ticks = 0; uint64 next = GetTicks_usec(); while (!tick_thread_cancel) { // Wait next += 16625; int64 delay = next - GetTicks_usec(); if (delay > 0) Delay_usec(delay); else if (delay < -16625) next = GetTicks_usec(); ticks++; // Pseudo Mac 1Hz interrupt, update local time if (++tick_counter > 60) { tick_counter = 0; WriteMacInt32(0x20c, TimerDateTime()); } // Trigger 60Hz interrupt if (ReadMacInt32(XLM_IRQ_NEST) == 0) { SetInterruptFlag(INTFLAG_VIA); TriggerInterrupt(); } } uint64 end = GetTicks_usec(); D(bug("%lu ticks in %lu usec = %f ticks/sec\n", (unsigned long)ticks, (unsigned long)(end - start), ticks * 1000000.0 / (end - start))); return 0; }
void Delay_usec(uint32 usec) { #ifdef __unix__ int was_error; #ifndef __linux__ /* Non-Linux implementations need to calculate time left */ uint64 then, now, elapsed; #endif struct timeval tv; /* Set the timeout interval - Linux only needs to do this once */ #ifdef __linux__ tv.tv_sec = 0; tv.tv_usec = usec; #else then = GetTicks_usec(); #endif do { errno = 0; #ifndef __linux__ /* Calculate the time interval left (in case of interrupt) */ now = GetTicks_usec(); elapsed = (now-then); then = now; if ( elapsed >= usec ) { break; } usec -= elapsed; tv.tv_sec = 0; tv.tv_usec = usec; #endif was_error = select(0, NULL, NULL, NULL, &tv); } while (was_error && (errno == EINTR)); #else SDL_Delay(usec / 1000); #endif }