Commit df75f082 authored by Aram Hăvărneanu's avatar Aram Hăvărneanu Committed by Dave Cheney

runtime: make runtime·usleep and runtime·osyield callable from cgo callback

runtime·usleep and runtime·osyield fall back to calling an
assembly wrapper for the libc functions in the absence of a m,
so they can be called in cgo callback context.

LGTM=rsc
R=minux.ma, rsc
CC=dave, golang-codereviews
https://golang.org/cl/102620044
parent 61ccc1f0
......@@ -568,10 +568,13 @@ runtime·sysconf(int32 name)
return runtime·sysvicall6(libc·sysconf, 1, (uintptr)name);
}
extern void runtime·usleep1(uint32);
#pragma textflag NOSPLIT
void
runtime·usleep(uint32 us)
runtime·usleep(uint32 µs)
{
runtime·sysvicall6(libc·usleep, 1, (uintptr)us);
runtime·usleep1(µs);
}
int32
......@@ -580,8 +583,17 @@ runtime·write(uintptr fd, void* buf, int32 nbyte)
return runtime·sysvicall6(libc·write, 3, (uintptr)fd, (uintptr)buf, (uintptr)nbyte);
}
extern void runtime·osyield1(void);
#pragma textflag NOSPLIT
void
runtime·osyield(void)
{
runtime·sysvicall6(libc·sched_yield, 0);
// Check the validity of m because we might be called in cgo callback
// path early enough where there isn't a m available yet.
if(g && g->m != nil) {
runtime·sysvicall6(libc·sched_yield, 0);
return;
}
runtime·osyield1();
}
......@@ -270,3 +270,55 @@ exit:
ADDQ $184, SP
RET
// Called from runtime·usleep (Go). Can be called on Go stack, on OS stack,
// can also be called in cgo callback path without a g->m.
TEXT runtime·usleep1(SB),NOSPLIT,$0
MOVL us+0(FP), DI
MOVQ $runtime·usleep2(SB), AX // to hide from 6l
// Execute call on m->g0.
get_tls(R15)
CMPQ R15, $0
JE usleep1_noswitch
MOVQ g(R15), R13
CMPQ R13, $0
JE usleep1_noswitch
MOVQ g_m(R13), R13
CMPQ R13, $0
JE usleep1_noswitch
// TODO(aram): do something about the cpu profiler here.
MOVQ m_g0(R13), R14
CMPQ g(R15), R14
JNE usleep1_switch
// executing on m->g0 already
CALL AX
RET
usleep1_switch:
// 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
usleep1_noswitch:
// Not a Go-managed thread. Do not switch stack.
CALL AX
RET
// Runs on OS stack. duration (in µs units) is in DI.
TEXT runtime·usleep2(SB),NOSPLIT,$0
MOVQ libc·usleep(SB), AX
CALL AX
RET
// Runs on OS stack, called from runtime·osyield.
TEXT runtime·osyield1(SB),NOSPLIT,$0
MOVQ libc·sched_yield(SB), AX
CALL AX
RET
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment