void task_sleep (task_ticks_t ticks) { #ifdef PTHDEBUG2 printf ("task_sleep(%d)\n", ticks); #endif pth_nap (pth_time (0, ticks * PTH_USECS_PER_TICK)); }
void SDL_Delay (Uint32 ms) { #ifdef ENABLE_PTH pth_time_t tv; tv.tv_sec = ms/1000; tv.tv_usec = (ms%1000)*1000; pth_nap(tv); #else int was_error; #ifdef USE_NANOSLEEP struct timespec elapsed, tv; #else struct timeval tv; #ifndef SELECT_SETS_REMAINING Uint32 then, now, elapsed; #endif #endif /* Set the timeout interval - Linux only needs to do this once */ #ifdef SELECT_SETS_REMAINING tv.tv_sec = ms/1000; tv.tv_usec = (ms%1000)*1000; #elif defined(USE_NANOSLEEP) elapsed.tv_sec = ms/1000; elapsed.tv_nsec = (ms%1000)*1000000; #else then = SDL_GetTicks(); #endif do { errno = 0; #if _POSIX_THREAD_SYSCALL_SOFT pthread_yield_np(); #endif #ifdef USE_NANOSLEEP tv.tv_sec = elapsed.tv_sec; tv.tv_nsec = elapsed.tv_nsec; was_error = nanosleep(&tv, &elapsed); #else #ifndef SELECT_SETS_REMAINING /* Calculate the time interval left (in case of interrupt) */ now = SDL_GetTicks(); elapsed = (now-then); then = now; if ( elapsed >= ms ) { break; } ms -= elapsed; tv.tv_sec = ms/1000; tv.tv_usec = (ms%1000)*1000; #endif was_error = select(0, NULL, NULL, NULL, &tv); #endif /* USE_NANOSLEEP */ } while ( was_error && (errno == EINTR) ); #endif /* ENABLE_PTH */ }
void SDL_Delay (Uint32 ms) { #if SDL_THREAD_PTH pth_time_t tv; tv.tv_sec = ms/1000; tv.tv_usec = (ms%1000)*1000; pth_nap(tv); #else int was_error; #if HAVE_NANOSLEEP struct timespec elapsed, tv; #else struct timeval tv; Uint32 then, now, elapsed; #endif /* Set the timeout interval */ #if HAVE_NANOSLEEP elapsed.tv_sec = ms/1000; elapsed.tv_nsec = (ms%1000)*1000000; #else then = SDL_GetTicks(); #endif do { errno = 0; #if HAVE_NANOSLEEP tv.tv_sec = elapsed.tv_sec; tv.tv_nsec = elapsed.tv_nsec; was_error = nanosleep(&tv, &elapsed); #else /* Calculate the time interval left (in case of interrupt) */ now = SDL_GetTicks(); elapsed = (now-then); then = now; if ( elapsed >= ms ) { break; } ms -= elapsed; tv.tv_sec = ms/1000; tv.tv_usec = (ms%1000)*1000; was_error = select(0, NULL, NULL, NULL, &tv); #endif /* HAVE_NANOSLEEP */ } while ( was_error && (errno == EINTR) ); #endif /* SDL_THREAD_PTH */ }
/** * Implement a realtime loop on a non-realtime OS. * * This function never returns. It is called from a separate thread context to * simulate what would be done at interrupt time on a realtime OS. Instead, * it sleeps for short durations, and on wakeup invokes the target's realtime * functions multiple times, depending on how long the sleep lasted. */ void realtime_loop (void) { struct timeval prev_time, curr_time; int usecs_elapsed = 0; #ifdef CONFIG_DEBUG_LATENCY int latency; #endif gettimeofday (&prev_time, NULL); for (;;) { /* Delay a small amount on most iterations of the loop. If we do not ever sleep, then this task will consume all of the CPU. Our goal is to sleep for 1ms (1000 usecs) evenly on every iteration. However we adjust this value in two ways: First, we always try to sleep slightly less than that, since this function will consume some CPU time. The rough estimate for this is 100 usecs. Second, handle actual delays that are fractional. For example, if we actually sleep for 2.9ms, we will only simulate two interrupts, and 900 usec is ignored. So for the next iteration, don't sleep for that extra 900 usec. Because of the adjustments, usecs_asked can go negative; if it does, we won't sleep at all. */ int usecs_asked = 1000 - usecs_elapsed - 100; if (usecs_asked > 0) { #if defined(CONFIG_PTH) pth_nap (pth_time (0, usecs_asked)); #elif defined(CONFIG_PTHREADS) usleep (usecs_asked); #else #error "No thread library supported for realtime yet" #endif } /* Now see how long we actually slept. This takes into account the actual sleep time, which is typically longer on a multitasking OS, and also the length of time that the previous iteration took. Even if we did not sleep at all above, usecs_elapsed will be positive here. */ gettimeofday (&curr_time, NULL); usecs_elapsed = curr_time.tv_usec - prev_time.tv_usec; if (usecs_elapsed < 0) usecs_elapsed += 1000000; #ifdef CONFIG_DEBUG_LATENCY /* This is for debugging only to see how good your native OS is. Print a message when the latency is more than 0.5ms than we requested . */ latency = usecs_elapsed - usecs_asked; if (latency > 200) print_log ("latency %d usec\n", latency); #endif prev_time = curr_time; /* Invoke realtime tick at least once every time through the loop. So if we slept < 1ms (either the OS lied to us, or we didn't sleep at all), we'll make forward progress. */ realtime_counter++; realtime_tick (); usecs_elapsed -= usecs_asked; if (usecs_elapsed > 20000) { } /* If any remaining millseconds occurred during the wait, handle them */ while (usecs_elapsed >= 1000) { realtime_counter++; realtime_tick (); usecs_elapsed -= 1000; } /* Whatever was left over will be subtracted from the next delay, so that we stay on schedule */ } }