mirror of
https://github.com/kanjitalk755/macemu.git
synced 2025-01-26 16:31:11 +00:00
Implement better Windows suspend/resume routines so that we don't oversleep.
i.e. really wake up the thread on next TriggerInterrupt().
This commit is contained in:
parent
2e6ae14c4c
commit
5fed65456b
@ -77,8 +77,9 @@ bool ThirtyThreeBitAddressing = false;
|
||||
|
||||
|
||||
// Global variables
|
||||
static uint8 last_xpram[XPRAM_SIZE]; // Buffer for monitoring XPRAM changes
|
||||
HANDLE emul_thread = NULL; // Handle of MacOS emulation thread (main thread)
|
||||
|
||||
static uint8 last_xpram[XPRAM_SIZE]; // Buffer for monitoring XPRAM changes
|
||||
static bool xpram_thread_active = false; // Flag: XPRAM watchdog installed
|
||||
static volatile bool xpram_thread_cancel = false; // Flag: Cancel XPRAM thread
|
||||
static SDL_Thread *xpram_thread = NULL; // XPRAM watchdog
|
||||
@ -421,6 +422,9 @@ int main(int argc, char **argv)
|
||||
QuitEmulator();
|
||||
D(bug("Initialization complete\n"));
|
||||
|
||||
// Get handle of main thread
|
||||
emul_thread = GetCurrentThread();
|
||||
|
||||
// SDL threads available, start 60Hz thread
|
||||
tick_thread_active = ((tick_thread = SDL_CreateThread(tick_func, NULL)) != NULL);
|
||||
if (!tick_thread_active) {
|
||||
|
@ -36,6 +36,9 @@
|
||||
#define USECS2TICKS(USECS) (((uint64)(USECS) * frequency) / 1000000)
|
||||
#define TICKS2USECS(TICKS) (((uint64)(TICKS) * 1000000) / frequency)
|
||||
|
||||
// From main_windows.cpp
|
||||
extern HANDLE emul_thread;
|
||||
|
||||
// Global variables
|
||||
static uint32 frequency; // CPU frequency in Hz (< 4 GHz)
|
||||
static tm_time_t mac_boot_ticks;
|
||||
@ -201,8 +204,54 @@ void Delay_usec(uint32 usec)
|
||||
* Suspend emulator thread, virtual CPU in idle mode
|
||||
*/
|
||||
|
||||
struct idle_sentinel {
|
||||
idle_sentinel();
|
||||
~idle_sentinel();
|
||||
};
|
||||
static idle_sentinel idle_sentinel;
|
||||
|
||||
static int idle_sem_ok = -1;
|
||||
static HANDLE idle_sem = NULL;
|
||||
|
||||
static HANDLE idle_lock = NULL;
|
||||
#define LOCK_IDLE WaitForSingleObject(idle_lock, INFINITE)
|
||||
#define UNLOCK_IDLE ReleaseMutex(idle_lock)
|
||||
|
||||
idle_sentinel::idle_sentinel()
|
||||
{
|
||||
LOCK_IDLE;
|
||||
idle_sem_ok = 1;
|
||||
if ((idle_sem = CreateSemaphore(0, 0, 1, NULL)) == NULL)
|
||||
idle_sem_ok = 0;
|
||||
if ((idle_lock = CreateMutex(NULL, FALSE, NULL)) == NULL)
|
||||
idle_sem_ok = 0;
|
||||
UNLOCK_IDLE;
|
||||
}
|
||||
|
||||
idle_sentinel::~idle_sentinel()
|
||||
{
|
||||
if (idle_lock) {
|
||||
ReleaseMutex(idle_lock);
|
||||
CloseHandle(idle_lock);
|
||||
}
|
||||
if (idle_sem) {
|
||||
ReleaseSemaphore(idle_sem, 1, NULL);
|
||||
CloseHandle(idle_sem);
|
||||
}
|
||||
}
|
||||
|
||||
void idle_wait(void)
|
||||
{
|
||||
LOCK_IDLE;
|
||||
if (idle_sem_ok > 0) {
|
||||
idle_sem_ok++;
|
||||
UNLOCK_IDLE;
|
||||
WaitForSingleObject(idle_sem, INFINITE);
|
||||
return;
|
||||
}
|
||||
UNLOCK_IDLE;
|
||||
|
||||
// Fallback: sleep 10 ms (this should not happen though)
|
||||
Delay_usec(10000);
|
||||
}
|
||||
|
||||
@ -213,4 +262,12 @@ void idle_wait(void)
|
||||
|
||||
void idle_resume(void)
|
||||
{
|
||||
LOCK_IDLE;
|
||||
if (idle_sem_ok > 1) {
|
||||
idle_sem_ok--;
|
||||
UNLOCK_IDLE;
|
||||
ReleaseSemaphore(idle_sem, 1, NULL);
|
||||
return;
|
||||
}
|
||||
UNLOCK_IDLE;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user