mirror of
https://github.com/golang/go
synced 2024-11-12 09:20:22 -07:00
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
This commit is contained in:
parent
61ccc1f05f
commit
df75f082d3
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user