From 45cff65502ace2783f05cf27383d807f07627cf2 Mon Sep 17 00:00:00 2001 From: Alex Brainman Date: Tue, 16 Jul 2013 12:36:05 +1000 Subject: [PATCH] runtime: switch to os stack in windows osyield and usleep Fixes #5831 R=golang-dev, rsc CC=golang-dev https://golang.org/cl/11266043 --- src/pkg/runtime/os_windows.c | 17 +++++++++ src/pkg/runtime/sys_windows_386.s | 59 +++++++++++++++-------------- src/pkg/runtime/sys_windows_amd64.s | 52 +++++++++++++++---------- 3 files changed, 79 insertions(+), 49 deletions(-) diff --git a/src/pkg/runtime/os_windows.c b/src/pkg/runtime/os_windows.c index 60160c3e16..5dcbd2c1e1 100644 --- a/src/pkg/runtime/os_windows.c +++ b/src/pkg/runtime/os_windows.c @@ -275,6 +275,23 @@ runtime·stdcall(void *fn, int32 count, ...) return (void*)c.r1; } +extern void runtime·usleep1(uint32); + +#pragma textflag 7 +void +runtime·osyield(void) +{ + runtime·usleep1(1); +} + +#pragma textflag 7 +void +runtime·usleep(uint32 us) +{ + // Have 1us units; want 100ns units. + runtime·usleep1(10*us); +} + uint32 runtime·issigpanic(uint32 code) { diff --git a/src/pkg/runtime/sys_windows_386.s b/src/pkg/runtime/sys_windows_386.s index d232bd115d..d6f1259818 100644 --- a/src/pkg/runtime/sys_windows_386.s +++ b/src/pkg/runtime/sys_windows_386.s @@ -327,28 +327,39 @@ TEXT runtime·remove_exception_handler(SB),7,$0 RET -TEXT runtime·osyield(SB),7,$20 - // Tried NtYieldExecution but it doesn't yield hard enough. - // NtWaitForSingleObject being used here as Sleep(0). - MOVL runtime·NtWaitForSingleObject(SB), AX - MOVL $-1, hi-4(SP) - MOVL $-1, lo-8(SP) - LEAL lo-8(SP), BX - MOVL BX, ptime-12(SP) - MOVL $0, alertable-16(SP) - MOVL $-1, handle-20(SP) - MOVL SP, BP - CALL checkstack4<>(SB) +// Sleep duration is in 100ns units. +TEXT runtime·usleep1(SB),7,$0 + MOVL duration+0(FP), BX + MOVL $runtime·usleep2(SB), AX // to hide from 8l + + // Execute call on m->g0 stack, in case we are not actually + // calling a system call wrapper, like when running under WINE. + get_tls(CX) + CMPL CX, $0 + JNE 3(PC) + // Not a Go-managed thread. Do not switch stack. CALL AX - MOVL BP, SP RET -TEXT runtime·usleep(SB),7,$20 - MOVL runtime·NtWaitForSingleObject(SB), AX - // Have 1us units; need negative 100ns units. - // Assume multiply by 10 will not overflow 32-bit word. - MOVL usec+0(FP), BX - IMULL $10, BX + MOVL m(CX), BP + MOVL m_g0(BP), SI + CMPL g(CX), SI + JNE 3(PC) + // executing on m->g0 already + CALL AX + RET + + // Switch to m->g0 stack and back. + MOVL (g_sched+gobuf_sp)(SI), SI + MOVL SP, -4(SI) + LEAL -4(SI), SP + CALL AX + MOVL 0(SP), SP + RET + +// Runs on OS stack. duration (in 100ns units) is in BX. +TEXT runtime·usleep2(SB),7,$20 + // Want negative 100ns units. NEGL BX MOVL $-1, hi-4(SP) MOVL BX, lo-8(SP) @@ -357,15 +368,7 @@ TEXT runtime·usleep(SB),7,$20 MOVL $0, alertable-16(SP) MOVL $-1, handle-20(SP) MOVL SP, BP - CALL checkstack4<>(SB) + MOVL runtime·NtWaitForSingleObject(SB), AX CALL AX MOVL BP, SP RET - -// This function requires 4 bytes of stack, -// to simulate what calling NtWaitForSingleObject will use. -// (It is just a CALL to the system call dispatch.) -// If the linker okays the call to checkstack4 (a NOSPLIT function) -// then the call to NtWaitForSingleObject is okay too. -TEXT checkstack4<>(SB),7,$4 - RET diff --git a/src/pkg/runtime/sys_windows_amd64.s b/src/pkg/runtime/sys_windows_amd64.s index 4837a02a5a..a8953d5390 100644 --- a/src/pkg/runtime/sys_windows_amd64.s +++ b/src/pkg/runtime/sys_windows_amd64.s @@ -322,34 +322,44 @@ TEXT runtime·install_exception_handler(SB),7,$0 TEXT runtime·remove_exception_handler(SB),7,$0 RET -TEXT runtime·osyield(SB),7,$8 - // Tried NtYieldExecution but it doesn't yield hard enough. - // NtWaitForSingleObject being used here as Sleep(0). - // The CALL is safe because NtXxx is a system call wrapper: - // it puts the right system call number in AX, then does - // a SYSENTER and a RET. - MOVQ runtime·NtWaitForSingleObject(SB), AX - MOVQ $1, BX - NEGQ BX - MOVQ SP, R8 // ptime - MOVQ BX, (R8) - MOVQ $-1, CX // handle - MOVQ $0, DX // alertable +// Sleep duration is in 100ns units. +TEXT runtime·usleep1(SB),7,$0 + MOVL duration+0(FP), BX + MOVQ $runtime·usleep2(SB), AX // to hide from 6l + + // Execute call on m->g0 stack, in case we are not actually + // calling a system call wrapper, like when running under WINE. + get_tls(R15) + CMPQ R15, $0 + JNE 3(PC) + // Not a Go-managed thread. Do not switch stack. CALL AX RET -TEXT runtime·usleep(SB),7,$8 - // The CALL is safe because NtXxx is a system call wrapper: - // it puts the right system call number in AX, then does - // a SYSENTER and a RET. - MOVQ runtime·NtWaitForSingleObject(SB), AX - // Have 1us units; want negative 100ns units. - MOVL usec+0(FP), BX - IMULQ $10, BX + MOVQ m(R15), R14 + MOVQ m_g0(R14), R14 + CMPQ g(R15), R14 + JNE 3(PC) + // executing on m->g0 already + CALL AX + RET + + // Switch to m->g0 stack and back. + MOVQ (g_sched+gobuf_sp)(R14), R14 + MOVQ SP, -8(R14) + LEAQ -8(R14), SP + CALL AX + MOVQ 0(SP), SP + RET + +// Runs on OS stack. duration (in 100ns units) is in BX. +TEXT runtime·usleep2(SB),7,$8 + // Want negative 100ns units. NEGQ BX MOVQ SP, R8 // ptime MOVQ BX, (R8) MOVQ $-1, CX // handle MOVQ $0, DX // alertable + MOVQ runtime·NtWaitForSingleObject(SB), AX CALL AX RET -- 2.48.1