Commit 75312e74 authored by Aurelien Jarno's avatar Aurelien Jarno
Browse files

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
parents d640045a 0727b867
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -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;
    }
+22 −2
Original line number Diff line number Diff line
@@ -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
}
+11 −18
Original line number Diff line number Diff line
@@ -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;
}

void os_setup_early_signal_handling(void)
static TIMECAPS mm_tc;

static void os_undo_timer_resolution(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;
    timeEndPeriod(mm_tc.wPeriodMin);
}

void os_setup_early_signal_handling(void)
{
    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.  */
+6 −18
Original line number Diff line number Diff line
@@ -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)
{
    if (mm_timer) {
        timeKillEvent(mm_timer);
    timeEndPeriod(mm_tc.wPeriodMin);
    }
}

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;
    }

    if (mm_timer) {
        timeKillEvent(mm_timer);
    }
    mm_timer = timeSetEvent((UINT)nearest_delta_ms,
                            mm_tc.wPeriodMin,
                            mm_alarm_handler,