|
|
1.1 ! root 1: #include "config.h" ! 2: ! 3: #if HAVE_NANOSLEEP ! 4: #ifdef __MINGW32__ ! 5: #include <unistd.h> ! 6: #else ! 7: #include <sys/time.h> ! 8: #endif ! 9: #endif ! 10: #include <errno.h> ! 11: ! 12: #include "host.h" ! 13: #include "configuration.h" ! 14: #include "main.h" ! 15: ! 16: /* NeXTdimension blank handling, see nd_sdl.c */ ! 17: void nd_display_blank(int num); ! 18: void nd_video_blank(int num); ! 19: ! 20: #define NUM_BLANKS 3 ! 21: static const char* BLANKS[] = { ! 22: "main","nd_main","nd_video" ! 23: }; ! 24: ! 25: static volatile Uint32 blank[NUM_BLANKS]; ! 26: static Uint32 vblCounter[NUM_BLANKS]; ! 27: static Uint64 perfCounterStart; ! 28: static Sint64 cycleCounterStart; ! 29: static double cycleSecsStart; ! 30: static bool isRealtime; ! 31: static bool oldIsRealtime; ! 32: static double cycleDivisor; ! 33: static lock_t timeLock; ! 34: static Uint32 ticksStart; ! 35: static bool enableRealtime; ! 36: static Uint64 hardClockExpected; ! 37: static Uint64 hardClockActual; ! 38: static time_t unixTimeStart; ! 39: static double unixTimeOffset = 0; ! 40: static double perfFrequency; ! 41: static double realTimeOffset; ! 42: static Uint64 pauseTimeStamp; ! 43: static bool osDarkmatter; ! 44: ! 45: void host_reset() { ! 46: perfCounterStart = SDL_GetPerformanceCounter(); ! 47: pauseTimeStamp = perfCounterStart; ! 48: perfFrequency = SDL_GetPerformanceFrequency(); ! 49: ticksStart = SDL_GetTicks(); ! 50: unixTimeStart = time(NULL); ! 51: cycleCounterStart = 0; ! 52: cycleSecsStart = 0; ! 53: isRealtime = false; ! 54: oldIsRealtime = false; ! 55: hardClockExpected = 0; ! 56: hardClockActual = 0; ! 57: enableRealtime = ConfigureParams.System.bRealtime; ! 58: realTimeOffset = 0; ! 59: osDarkmatter = false; ! 60: ! 61: for(int i = NUM_BLANKS; --i >= 0;) { ! 62: vblCounter[i] = 0; ! 63: blank[i] = 0; ! 64: } ! 65: ! 66: cycleDivisor = ConfigureParams.System.nCpuFreq * 1000 * 1000; ! 67: ! 68: SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH); ! 69: } ! 70: ! 71: void host_blank(int slot, int src, bool state) { ! 72: int bit = 1 << slot; ! 73: if(state) { ! 74: blank[src] |= bit; ! 75: vblCounter[src]++; ! 76: } ! 77: else ! 78: blank[src] &= ~bit; ! 79: switch (src) { ! 80: case ND_DISPLAY: nd_display_blank(slot); break; ! 81: case ND_VIDEO: nd_video_blank(slot); break; ! 82: } ! 83: } ! 84: ! 85: bool host_blank_state(int slot, int src) { ! 86: int bit = 1 << slot; ! 87: return blank[src] & bit; ! 88: } ! 89: ! 90: void host_hardclock(int expected, int actual) { ! 91: if(abs(actual-expected) > 1000) ! 92: fprintf(stderr, "[Hardclock] expected:%dus actual:%dus\n", expected, actual); ! 93: else { ! 94: hardClockExpected += expected; ! 95: hardClockActual += actual; ! 96: } ! 97: } ! 98: ! 99: extern Sint64 nCyclesMainCounter; ! 100: ! 101: void host_realtime(bool state) { ! 102: isRealtime = state; ! 103: } ! 104: ! 105: double host_time_sec() { ! 106: double rt; ! 107: double vt; ! 108: host_time(&rt, &vt); ! 109: return vt; ! 110: } ! 111: ! 112: void host_time(double* realTime, double* hostTime) { ! 113: host_lock(&timeLock); ! 114: ! 115: *realTime = (SDL_GetPerformanceCounter() - perfCounterStart); ! 116: *realTime /= perfFrequency; ! 117: ! 118: if(oldIsRealtime) { ! 119: *hostTime = *realTime; ! 120: } else { ! 121: *hostTime = nCyclesMainCounter - cycleCounterStart; ! 122: *hostTime /= cycleDivisor; ! 123: *hostTime += cycleSecsStart; ! 124: } ! 125: bool state = (isRealtime || osDarkmatter) && enableRealtime; ! 126: if(oldIsRealtime != state) { ! 127: if(oldIsRealtime) { ! 128: // switching from real-time to cycle-time ! 129: cycleSecsStart = *realTime; ! 130: cycleCounterStart = nCyclesMainCounter; ! 131: } else { ! 132: // switching from cycle-time to real-time ! 133: realTimeOffset = *hostTime - *realTime; ! 134: if(realTimeOffset > 0) { ! 135: // if hostTime is in the future, wait until realTime is there as well ! 136: if(realTimeOffset > 0.01) ! 137: host_sleep_sec(realTimeOffset); ! 138: else ! 139: while(*realTime < *hostTime) { ! 140: *realTime = (SDL_GetPerformanceCounter() - perfCounterStart); ! 141: *realTime /= perfFrequency; ! 142: } ! 143: } ! 144: } ! 145: oldIsRealtime = state; ! 146: } ! 147: ! 148: realTimeOffset = *hostTime - *realTime; ! 149: ! 150: host_unlock(&timeLock); ! 151: } ! 152: ! 153: // Return current time as micro seconds ! 154: Uint64 host_time_us() { ! 155: return host_time_sec() * 1000.0 * 1000.0; ! 156: } ! 157: ! 158: // Return current time as milliseconds ! 159: Uint32 host_time_ms() { ! 160: return host_time_us() / 1000LL; ! 161: } ! 162: ! 163: time_t host_unix_time() { ! 164: return unixTimeStart + unixTimeOffset + host_time_sec(); ! 165: } ! 166: ! 167: void host_set_unix_time(time_t now) { ! 168: unixTimeOffset += difftime(now, host_unix_time()); ! 169: } ! 170: ! 171: double host_real_time_offset() { ! 172: host_lock(&timeLock); ! 173: double result = realTimeOffset; ! 174: host_unlock(&timeLock); ! 175: return result; ! 176: } ! 177: ! 178: void host_pause_time(bool pausing) { ! 179: if(pausing) { ! 180: pauseTimeStamp = SDL_GetPerformanceCounter(); ! 181: } else { ! 182: perfCounterStart += SDL_GetPerformanceCounter() - pauseTimeStamp; ! 183: } ! 184: } ! 185: ! 186: /*-----------------------------------------------------------------------*/ ! 187: /** ! 188: * Sleep for a given number of micro seconds. We burn cycles by running ! 189: * the event loop. ! 190: */ ! 191: void host_sleep_us(Uint64 us) { ! 192: #if HAVE_NANOSLEEP ! 193: struct timespec ts; ! 194: int ret; ! 195: ts.tv_sec = us / 1000000; ! 196: ts.tv_nsec = (us % 1000000) * 1000; /* micro sec -> nano sec */ ! 197: /* wait until all the delay is elapsed, including possible interruptions by signals */ ! 198: do { ! 199: errno = 0; ! 200: ret = nanosleep(&ts, &ts); ! 201: } while ( ret && ( errno == EINTR ) ); /* keep on sleeping if we were interrupted */ ! 202: #else ! 203: Uint64 timeout = host_time_us() + us; ! 204: host_sleep_ms(( (Uint32)(ticks_micro / 1000) ) ; /* micro sec -> milli sec */ ! 205: while(host_time_us() < timeout) {} ! 206: #endif ! 207: } ! 208: ! 209: void host_sleep_ms(Uint32 ms) { ! 210: Uint64 sleep = ms; ! 211: sleep *= 1000; ! 212: host_sleep_us(sleep); ! 213: } ! 214: ! 215: void host_sleep_sec(double sec) { ! 216: sec *= 1000 * 1000; ! 217: host_sleep_us((Uint64)sec); ! 218: } ! 219: ! 220: void host_lock(lock_t* lock) { ! 221: SDL_AtomicLock(lock); ! 222: } ! 223: ! 224: int host_trylock(lock_t* lock) { ! 225: return SDL_AtomicTryLock(lock); ! 226: } ! 227: ! 228: void host_unlock(lock_t* lock) { ! 229: SDL_AtomicUnlock(lock); ! 230: } ! 231: ! 232: thread_t* host_thread_create(thread_func_t func, void* data) { ! 233: return SDL_CreateThread(func, "Thread", data); ! 234: } ! 235: ! 236: int host_thread_wait(thread_t* thread) { ! 237: int status; ! 238: SDL_WaitThread(thread, &status); ! 239: return status; ! 240: } ! 241: ! 242: int host_num_cpus() { ! 243: return SDL_GetCPUCount(); ! 244: } ! 245: ! 246: void host_darkmatter(bool state) { ! 247: osDarkmatter = state; ! 248: } ! 249: ! 250: static double lastVT; ! 251: static char report[512]; ! 252: ! 253: const char* host_report(double realTime, double hostTime) { ! 254: double dVT = hostTime - lastVT; ! 255: ! 256: double hardClock = hardClockExpected; ! 257: hardClock /= hardClockActual == 0 ? 1 : hardClockActual; ! 258: ! 259: char* r = report; ! 260: r += sprintf(r, "[%s] hostTime:%.1f hardClock:%.3fMHz", enableRealtime ? "Max.speed" : "CycleTime", hostTime, hardClock); ! 261: ! 262: for(int i = NUM_BLANKS; --i >= 0;) { ! 263: r += sprintf(r, " %s:%.1fHz", BLANKS[i], (double)vblCounter[i]/dVT); ! 264: vblCounter[i] = 0; ! 265: } ! 266: ! 267: lastVT = hostTime; ! 268: ! 269: return report; ! 270: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.