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