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