291 |
|
static uint8 last_xpram[XPRAM_SIZE]; // Buffer for monitoring XPRAM changes |
292 |
|
|
293 |
|
static bool nvram_thread_active = false; // Flag: NVRAM watchdog installed |
294 |
+ |
static volatile bool nvram_thread_cancel; // Flag: Cancel NVRAM thread |
295 |
|
static pthread_t nvram_thread; // NVRAM watchdog |
296 |
|
static bool tick_thread_active = false; // Flag: MacOS thread installed |
297 |
+ |
static volatile bool tick_thread_cancel; // Flag: Cancel 60Hz thread |
298 |
|
static pthread_t tick_thread; // 60Hz thread |
299 |
|
static pthread_t emul_thread; // MacOS thread |
300 |
|
|
902 |
|
D(bug("Low Memory initialized\n")); |
903 |
|
|
904 |
|
// Start 60Hz thread |
905 |
+ |
tick_thread_cancel = false; |
906 |
|
tick_thread_active = (pthread_create(&tick_thread, NULL, tick_func, NULL) == 0); |
907 |
|
D(bug("Tick thread installed (%ld)\n", tick_thread)); |
908 |
|
|
909 |
|
// Start NVRAM watchdog thread |
910 |
|
memcpy(last_xpram, XPRAM, XPRAM_SIZE); |
911 |
+ |
nvram_thread_cancel = false; |
912 |
|
nvram_thread_active = (pthread_create(&nvram_thread, NULL, nvram_func, NULL) == 0); |
913 |
|
D(bug("NVRAM thread installed (%ld)\n", nvram_thread)); |
914 |
|
|
1007 |
|
|
1008 |
|
// Stop 60Hz thread |
1009 |
|
if (tick_thread_active) { |
1010 |
+ |
tick_thread_cancel = true; |
1011 |
|
pthread_cancel(tick_thread); |
1012 |
|
pthread_join(tick_thread, NULL); |
1013 |
|
} |
1014 |
|
|
1015 |
|
// Stop NVRAM watchdog thread |
1016 |
|
if (nvram_thread_active) { |
1017 |
+ |
nvram_thread_cancel = true; |
1018 |
|
pthread_cancel(nvram_thread); |
1019 |
|
pthread_join(nvram_thread, NULL); |
1020 |
|
} |
1284 |
|
* NVRAM watchdog thread (saves NVRAM every minute) |
1285 |
|
*/ |
1286 |
|
|
1287 |
< |
static void *nvram_func(void *arg) |
1287 |
> |
static void nvram_watchdog(void) |
1288 |
|
{ |
1289 |
< |
struct timespec req = {60, 0}; // 1 minute |
1289 |
> |
if (memcmp(last_xpram, XPRAM, XPRAM_SIZE)) { |
1290 |
> |
memcpy(last_xpram, XPRAM, XPRAM_SIZE); |
1291 |
> |
SaveXPRAM(); |
1292 |
> |
} |
1293 |
> |
} |
1294 |
|
|
1295 |
< |
for (;;) { |
1296 |
< |
pthread_testcancel(); |
1297 |
< |
nanosleep(&req, NULL); |
1298 |
< |
pthread_testcancel(); |
1299 |
< |
if (memcmp(last_xpram, XPRAM, XPRAM_SIZE)) { |
1300 |
< |
memcpy(last_xpram, XPRAM, XPRAM_SIZE); |
1291 |
< |
SaveXPRAM(); |
1292 |
< |
} |
1295 |
> |
static void *nvram_func(void *arg) |
1296 |
> |
{ |
1297 |
> |
while (!nvram_thread_cancel) { |
1298 |
> |
for (int i=0; i<60 && !nvram_thread_cancel; i++) |
1299 |
> |
Delay_usec(999999); // Only wait 1 second so we quit promptly when nvram_thread_cancel becomes true |
1300 |
> |
nvram_watchdog(); |
1301 |
|
} |
1302 |
|
return NULL; |
1303 |
|
} |
1310 |
|
static void *tick_func(void *arg) |
1311 |
|
{ |
1312 |
|
int tick_counter = 0; |
1313 |
< |
struct timespec req = {0, 16625000}; |
1313 |
> |
uint64 start = GetTicks_usec(); |
1314 |
> |
int64 ticks = 0; |
1315 |
> |
uint64 next = GetTicks_usec(); |
1316 |
|
|
1317 |
< |
for (;;) { |
1317 |
> |
while (!tick_thread_cancel) { |
1318 |
|
|
1319 |
|
// Wait |
1320 |
< |
nanosleep(&req, NULL); |
1320 |
> |
next += 16625; |
1321 |
> |
int64 delay = next - GetTicks_usec(); |
1322 |
> |
if (delay > 0) |
1323 |
> |
Delay_usec(delay); |
1324 |
> |
else if (delay < -16625) |
1325 |
> |
next = GetTicks_usec(); |
1326 |
> |
ticks++; |
1327 |
|
|
1328 |
|
#if !EMULATED_PPC |
1329 |
|
// Did we crash? |
1381 |
|
TriggerInterrupt(); |
1382 |
|
} |
1383 |
|
} |
1384 |
+ |
|
1385 |
+ |
uint64 end = GetTicks_usec(); |
1386 |
+ |
D(bug("%Ld ticks in %Ld usec = %f ticks/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start))); |
1387 |
|
return NULL; |
1388 |
|
} |
1389 |
|
|