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;
|
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)) {
|
if (unlikely(exit_request)) {
|
||||||
cpu->exit_request = 1;
|
cpu->exit_request = 1;
|
||||||
}
|
}
|
||||||
|
24
cpus.c
24
cpus.c
@ -862,9 +862,29 @@ static void qemu_cpu_kick_thread(CPUState *cpu)
|
|||||||
}
|
}
|
||||||
#else /* _WIN32 */
|
#else /* _WIN32 */
|
||||||
if (!qemu_cpu_is_self(cpu)) {
|
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);
|
cpu_signal(0);
|
||||||
ResumeThread(cpu->hThread);
|
|
||||||
|
if (ResumeThread(cpu->hThread) == (DWORD)-1) {
|
||||||
|
fprintf(stderr, "qemu:%s: GetLastError:%d\n", __func__,
|
||||||
|
GetLastError());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
29
os-win32.c
29
os-win32.c
@ -23,6 +23,7 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <mmsystem.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@ -67,27 +68,19 @@ static BOOL WINAPI qemu_ctrl_handler(DWORD type)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static TIMECAPS mm_tc;
|
||||||
|
|
||||||
|
static void os_undo_timer_resolution(void)
|
||||||
|
{
|
||||||
|
timeEndPeriod(mm_tc.wPeriodMin);
|
||||||
|
}
|
||||||
|
|
||||||
void os_setup_early_signal_handling(void)
|
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);
|
SetConsoleCtrlHandler(qemu_ctrl_handler, TRUE);
|
||||||
|
timeGetDevCaps(&mm_tc, sizeof(mm_tc));
|
||||||
h = GetCurrentProcess();
|
timeBeginPeriod(mm_tc.wPeriodMin);
|
||||||
if (GetProcessAffinityMask(h, &mask, &smask)) {
|
atexit(os_undo_timer_resolution);
|
||||||
for(i = 0; i < 32; i++) {
|
|
||||||
if (mask & (1 << i))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i != 32) {
|
|
||||||
mask = 1 << i;
|
|
||||||
SetProcessAffinityMask(h, mask);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Look for support files in the same directory as the executable. */
|
/* 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)
|
static int mm_start_timer(struct qemu_alarm_timer *t)
|
||||||
{
|
{
|
||||||
timeGetDevCaps(&mm_tc, sizeof(mm_tc));
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mm_stop_timer(struct qemu_alarm_timer *t)
|
static void mm_stop_timer(struct qemu_alarm_timer *t)
|
||||||
{
|
{
|
||||||
timeKillEvent(mm_timer);
|
if (mm_timer) {
|
||||||
timeEndPeriod(mm_tc.wPeriodMin);
|
timeKillEvent(mm_timer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta)
|
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;
|
nearest_delta_ms = mm_tc.wPeriodMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
timeKillEvent(mm_timer);
|
if (mm_timer) {
|
||||||
|
timeKillEvent(mm_timer);
|
||||||
|
}
|
||||||
mm_timer = timeSetEvent((UINT)nearest_delta_ms,
|
mm_timer = timeSetEvent((UINT)nearest_delta_ms,
|
||||||
mm_tc.wPeriodMin,
|
mm_tc.wPeriodMin,
|
||||||
mm_alarm_handler,
|
mm_alarm_handler,
|
||||||
|
Loading…
Reference in New Issue
Block a user