1 |
|
/* |
2 |
|
* timer_windows.cpp - Time Manager emulation, Windows specific stuff |
3 |
|
* |
4 |
< |
* Basilisk II (C) 1997-2004 Christian Bauer |
4 |
> |
* Basilisk II (C) 1997-2005 Christian Bauer |
5 |
|
* |
6 |
|
* This program is free software; you can redistribute it and/or modify |
7 |
|
* it under the terms of the GNU General Public License as published by |
34 |
|
// Helper time functions |
35 |
|
#define MSECS2TICKS(MSECS) (((uint64)(MSECS) * frequency) / 1000) |
36 |
|
#define USECS2TICKS(USECS) (((uint64)(USECS) * frequency) / 1000000) |
37 |
– |
#define TICKS2MSECS(TICKS) (((uint64)(TICKS) * 1000) / frequency) |
37 |
|
#define TICKS2USECS(TICKS) (((uint64)(TICKS) * 1000000) / frequency) |
38 |
|
|
39 |
+ |
// From main_windows.cpp |
40 |
+ |
extern HANDLE emul_thread; |
41 |
+ |
|
42 |
|
// Global variables |
43 |
|
static uint32 frequency; // CPU frequency in Hz (< 4 GHz) |
44 |
|
static tm_time_t mac_boot_ticks; |
50 |
|
* Initialize native Windows timers |
51 |
|
*/ |
52 |
|
|
53 |
< |
void SysTimerInit(void) |
53 |
> |
void timer_init(void) |
54 |
|
{ |
55 |
|
D(bug("SysTimerInit\n")); |
56 |
|
|
167 |
|
if (hosttime < 0) |
168 |
|
return 0; |
169 |
|
else { |
170 |
< |
uint64 t = TICKS2MSECS(hosttime); |
170 |
> |
uint64 t = TICKS2USECS(hosttime); |
171 |
|
if (t > 0x7fffffff) |
172 |
|
return t / 1000; // Time in milliseconds |
173 |
|
else |
198 |
|
// millisecond resolution anyway |
199 |
|
Sleep(usec / 1000); |
200 |
|
} |
201 |
+ |
|
202 |
+ |
|
203 |
+ |
/* |
204 |
+ |
* Suspend emulator thread, virtual CPU in idle mode |
205 |
+ |
*/ |
206 |
+ |
|
207 |
+ |
struct idle_sentinel { |
208 |
+ |
idle_sentinel(); |
209 |
+ |
~idle_sentinel(); |
210 |
+ |
}; |
211 |
+ |
static idle_sentinel idle_sentinel; |
212 |
+ |
|
213 |
+ |
static int idle_sem_ok = -1; |
214 |
+ |
static HANDLE idle_sem = NULL; |
215 |
+ |
|
216 |
+ |
static HANDLE idle_lock = NULL; |
217 |
+ |
#define LOCK_IDLE WaitForSingleObject(idle_lock, INFINITE) |
218 |
+ |
#define UNLOCK_IDLE ReleaseMutex(idle_lock) |
219 |
+ |
|
220 |
+ |
idle_sentinel::idle_sentinel() |
221 |
+ |
{ |
222 |
+ |
LOCK_IDLE; |
223 |
+ |
idle_sem_ok = 1; |
224 |
+ |
if ((idle_sem = CreateSemaphore(0, 0, 1, NULL)) == NULL) |
225 |
+ |
idle_sem_ok = 0; |
226 |
+ |
if ((idle_lock = CreateMutex(NULL, FALSE, NULL)) == NULL) |
227 |
+ |
idle_sem_ok = 0; |
228 |
+ |
UNLOCK_IDLE; |
229 |
+ |
} |
230 |
+ |
|
231 |
+ |
idle_sentinel::~idle_sentinel() |
232 |
+ |
{ |
233 |
+ |
if (idle_lock) { |
234 |
+ |
ReleaseMutex(idle_lock); |
235 |
+ |
CloseHandle(idle_lock); |
236 |
+ |
} |
237 |
+ |
if (idle_sem) { |
238 |
+ |
ReleaseSemaphore(idle_sem, 1, NULL); |
239 |
+ |
CloseHandle(idle_sem); |
240 |
+ |
} |
241 |
+ |
} |
242 |
+ |
|
243 |
+ |
void idle_wait(void) |
244 |
+ |
{ |
245 |
+ |
LOCK_IDLE; |
246 |
+ |
if (idle_sem_ok > 0) { |
247 |
+ |
idle_sem_ok++; |
248 |
+ |
UNLOCK_IDLE; |
249 |
+ |
WaitForSingleObject(idle_sem, INFINITE); |
250 |
+ |
return; |
251 |
+ |
} |
252 |
+ |
UNLOCK_IDLE; |
253 |
+ |
|
254 |
+ |
// Fallback: sleep 10 ms (this should not happen though) |
255 |
+ |
Delay_usec(10000); |
256 |
+ |
} |
257 |
+ |
|
258 |
+ |
|
259 |
+ |
/* |
260 |
+ |
* Resume execution of emulator thread, events just arrived |
261 |
+ |
*/ |
262 |
+ |
|
263 |
+ |
void idle_resume(void) |
264 |
+ |
{ |
265 |
+ |
LOCK_IDLE; |
266 |
+ |
if (idle_sem_ok > 1) { |
267 |
+ |
idle_sem_ok--; |
268 |
+ |
UNLOCK_IDLE; |
269 |
+ |
ReleaseSemaphore(idle_sem, 1, NULL); |
270 |
+ |
return; |
271 |
+ |
} |
272 |
+ |
UNLOCK_IDLE; |
273 |
+ |
} |