Merge branch 'mingw' of git://qemu.weilnetz.de/qemu
* 'mingw' of git://qemu.weilnetz.de/qemu: qemu-timer: move timeBeginPeriod/timeEndPeriod to os-win32 Release SMP restriction on Windows Ensure good ordering of memory instruction in cpu_exec Check effective suspension of TCG thread
This commit is contained in:
commit
75312e745a
@ -215,6 +215,14 @@ int cpu_exec(CPUArchState *env)
|
||||
|
||||
cpu_single_env = env;
|
||||
|
||||
/* As long as cpu_single_env is null, up to the assignment just above,
|
||||
* requests by other threads to exit the execution loop are expected to
|
||||
* be issued using the exit_request global. We must make sure that our
|
||||
* evaluation of the global value is performed past the cpu_single_env
|
||||
* value transition point, which requires a memory barrier as well as
|
||||
* an instruction scheduling constraint on modern architectures. */
|
||||
smp_mb();
|
||||
|
||||
if (unlikely(exit_request)) {
|
||||
cpu->exit_request = 1;
|
||||
}
|
||||
|
24
cpus.c
24
cpus.c
@ -862,9 +862,29 @@ static void qemu_cpu_kick_thread(CPUState *cpu)
|
||||
}
|
||||
#else /* _WIN32 */
|
||||
if (!qemu_cpu_is_self(cpu)) {
|
||||
SuspendThread(cpu->hThread);
|
||||
CONTEXT tcgContext;
|
||||
|
||||
if (SuspendThread(cpu->hThread) == (DWORD)-1) {
|
||||
fprintf(stderr, "qemu:%s: GetLastError:%d\n", __func__,
|
||||
GetLastError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* On multi-core systems, we are not sure that the thread is actually
|
||||
* suspended until we can get the context.
|
||||
*/
|
||||
tcgContext.ContextFlags = CONTEXT_CONTROL;
|
||||
while (GetThreadContext(cpu->hThread, &tcgContext) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cpu_signal(0);
|
||||
ResumeThread(cpu->hThread);
|
||||
|
||||
if (ResumeThread(cpu->hThread) == (DWORD)-1) {
|
||||
fprintf(stderr, "qemu:%s: GetLastError:%d\n", __func__,
|
||||
GetLastError());
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
29
os-win32.c
29
os-win32.c
@ -23,6 +23,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
@ -67,27 +68,19 @@ static BOOL WINAPI qemu_ctrl_handler(DWORD type)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static TIMECAPS mm_tc;
|
||||
|
||||
static void os_undo_timer_resolution(void)
|
||||
{
|
||||
timeEndPeriod(mm_tc.wPeriodMin);
|
||||
}
|
||||
|
||||
void os_setup_early_signal_handling(void)
|
||||
{
|
||||
/* Note: cpu_interrupt() is currently not SMP safe, so we force
|
||||
QEMU to run on a single CPU */
|
||||
HANDLE h;
|
||||
DWORD_PTR mask, smask;
|
||||
int i;
|
||||
|
||||
SetConsoleCtrlHandler(qemu_ctrl_handler, TRUE);
|
||||
|
||||
h = GetCurrentProcess();
|
||||
if (GetProcessAffinityMask(h, &mask, &smask)) {
|
||||
for(i = 0; i < 32; i++) {
|
||||
if (mask & (1 << i))
|
||||
break;
|
||||
}
|
||||
if (i != 32) {
|
||||
mask = 1 << i;
|
||||
SetProcessAffinityMask(h, mask);
|
||||
}
|
||||
}
|
||||
timeGetDevCaps(&mm_tc, sizeof(mm_tc));
|
||||
timeBeginPeriod(mm_tc.wPeriodMin);
|
||||
atexit(os_undo_timer_resolution);
|
||||
}
|
||||
|
||||
/* Look for support files in the same directory as the executable. */
|
||||
|
24
qemu-timer.c
24
qemu-timer.c
@ -624,28 +624,14 @@ static void CALLBACK mm_alarm_handler(UINT uTimerID, UINT uMsg,
|
||||
static int mm_start_timer(struct qemu_alarm_timer *t)
|
||||
{
|
||||
timeGetDevCaps(&mm_tc, sizeof(mm_tc));
|
||||
|
||||
timeBeginPeriod(mm_tc.wPeriodMin);
|
||||
|
||||
mm_timer = timeSetEvent(mm_tc.wPeriodMin, /* interval (ms) */
|
||||
mm_tc.wPeriodMin, /* resolution */
|
||||
mm_alarm_handler, /* function */
|
||||
(DWORD_PTR)t, /* parameter */
|
||||
TIME_ONESHOT | TIME_CALLBACK_FUNCTION);
|
||||
|
||||
if (!mm_timer) {
|
||||
fprintf(stderr, "Failed to initialize win32 alarm timer\n");
|
||||
timeEndPeriod(mm_tc.wPeriodMin);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mm_stop_timer(struct qemu_alarm_timer *t)
|
||||
{
|
||||
timeKillEvent(mm_timer);
|
||||
timeEndPeriod(mm_tc.wPeriodMin);
|
||||
if (mm_timer) {
|
||||
timeKillEvent(mm_timer);
|
||||
}
|
||||
}
|
||||
|
||||
static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta)
|
||||
@ -657,7 +643,9 @@ static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta)
|
||||
nearest_delta_ms = mm_tc.wPeriodMax;
|
||||
}
|
||||
|
||||
timeKillEvent(mm_timer);
|
||||
if (mm_timer) {
|
||||
timeKillEvent(mm_timer);
|
||||
}
|
||||
mm_timer = timeSetEvent((UINT)nearest_delta_ms,
|
||||
mm_tc.wPeriodMin,
|
||||
mm_alarm_handler,
|
||||
|
Loading…
Reference in New Issue
Block a user