Commit 91a670d1 authored by Dmitriy Vyukov's avatar Dmitriy Vyukov

runtime: convert netpoll to Go

The common code is converted, epoll and kqueue are converted.
Windows and solaris are still C.

LGTM=rsc
R=golang-codereviews, rsc, dave
CC=golang-codereviews, iant, khr, rsc
https://golang.org/cl/132910043
parent dae80386
...@@ -405,6 +405,9 @@ func (w *Walker) parseFile(dir, file string) (*ast.File, error) { ...@@ -405,6 +405,9 @@ func (w *Walker) parseFile(dir, file string) (*ast.File, error) {
" sudog struct{};" + " sudog struct{};" +
" waitq struct{};" + " waitq struct{};" +
" wincallbackcontext struct{};" + " wincallbackcontext struct{};" +
" keventt struct{};" +
" timespec struct{};" +
" epollevent struct{};" +
"); " + "); " +
"const (" + "const (" +
" cb_max = 2000;" + " cb_max = 2000;" +
......
...@@ -598,6 +598,9 @@ TEXT runtime·xchgp(SB), NOSPLIT, $0-12 ...@@ -598,6 +598,9 @@ TEXT runtime·xchgp(SB), NOSPLIT, $0-12
MOVL AX, ret+8(FP) MOVL AX, ret+8(FP)
RET RET
TEXT runtime·xchguintptr(SB), NOSPLIT, $0-12
JMP runtime·xchg(SB)
TEXT runtime·procyield(SB),NOSPLIT,$0-0 TEXT runtime·procyield(SB),NOSPLIT,$0-0
MOVL cycles+0(FP), AX MOVL cycles+0(FP), AX
again: again:
......
...@@ -709,6 +709,9 @@ TEXT runtime·xchgp(SB), NOSPLIT, $0-24 ...@@ -709,6 +709,9 @@ TEXT runtime·xchgp(SB), NOSPLIT, $0-24
MOVQ AX, ret+16(FP) MOVQ AX, ret+16(FP)
RET RET
TEXT runtime·xchguintptr(SB), NOSPLIT, $0-24
JMP runtime·xchg64(SB)
TEXT runtime·procyield(SB),NOSPLIT,$0-0 TEXT runtime·procyield(SB),NOSPLIT,$0-0
MOVL cycles+0(FP), AX MOVL cycles+0(FP), AX
again: again:
......
...@@ -666,6 +666,16 @@ TEXT runtime·xchg64(SB), NOSPLIT, $0-24 ...@@ -666,6 +666,16 @@ TEXT runtime·xchg64(SB), NOSPLIT, $0-24
MOVQ AX, ret+16(FP) MOVQ AX, ret+16(FP)
RET RET
TEXT runtime·xchgp(SB), NOSPLIT, $0-12
MOVL ptr+0(FP), BX
MOVL new+4(FP), AX
XCHGL AX, 0(BX)
MOVL AX, ret+8(FP)
RET
TEXT runtime·xchguintptr(SB), NOSPLIT, $0-12
JMP runtime·xchg(SB)
TEXT runtime·procyield(SB),NOSPLIT,$0-0 TEXT runtime·procyield(SB),NOSPLIT,$0-0
MOVL cycles+0(FP), AX MOVL cycles+0(FP), AX
again: again:
......
...@@ -54,6 +54,13 @@ runtime·xchgp(void* volatile* addr, void* v) ...@@ -54,6 +54,13 @@ runtime·xchgp(void* volatile* addr, void* v)
} }
} }
#pragma textflag NOSPLIT
void*
runtime·xchguintptr(void* volatile* addr, void* v)
{
return runtime·xchg((uint32*)addr, (uint32)v);
}
#pragma textflag NOSPLIT #pragma textflag NOSPLIT
void void
runtime·procyield(uint32 cnt) runtime·procyield(uint32 cnt)
......
This diff is collapsed.
This diff is collapsed.
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build linux
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
int32 runtime·epollcreate(int32 size);
int32 runtime·epollcreate1(int32 flags);
int32 runtime·epollctl(int32 epfd, int32 op, int32 fd, EpollEvent *ev);
int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout);
void runtime·closeonexec(int32 fd);
static int32 epfd = -1; // epoll descriptor
void
runtime·netpollinit(void)
{
epfd = runtime·epollcreate1(EPOLL_CLOEXEC);
if(epfd >= 0)
return;
epfd = runtime·epollcreate(1024);
if(epfd >= 0) {
runtime·closeonexec(epfd);
return;
}
runtime·printf("netpollinit: failed to create descriptor (%d)\n", -epfd);
runtime·throw("netpollinit: failed to create descriptor");
}
int32
runtime·netpollopen(uintptr fd, PollDesc *pd)
{
EpollEvent ev;
int32 res;
ev.events = EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLET;
*(uint64*)ev.data = (uint64)(uintptr)pd;
res = runtime·epollctl(epfd, EPOLL_CTL_ADD, (int32)fd, &ev);
return -res;
}
int32
runtime·netpollclose(uintptr fd)
{
EpollEvent ev;
int32 res;
res = runtime·epollctl(epfd, EPOLL_CTL_DEL, (int32)fd, &ev);
return -res;
}
void
runtime·netpollarm(PollDesc* pd, int32 mode)
{
USED(pd);
USED(mode);
runtime·throw("unused");
}
// polls for ready network connections
// returns list of goroutines that become runnable
G*
runtime·netpoll(bool block)
{
static int32 lasterr;
EpollEvent events[128], *ev;
int32 n, i, waitms, mode;
G *gp;
if(epfd == -1)
return nil;
waitms = -1;
if(!block)
waitms = 0;
retry:
n = runtime·epollwait(epfd, events, nelem(events), waitms);
if(n < 0) {
if(n != -EINTR && n != lasterr) {
lasterr = n;
runtime·printf("runtime: epollwait on fd %d failed with %d\n", epfd, -n);
}
goto retry;
}
gp = nil;
for(i = 0; i < n; i++) {
ev = &events[i];
if(ev->events == 0)
continue;
mode = 0;
if(ev->events & (EPOLLIN|EPOLLRDHUP|EPOLLHUP|EPOLLERR))
mode += 'r';
if(ev->events & (EPOLLOUT|EPOLLHUP|EPOLLERR))
mode += 'w';
if(mode)
runtime·netpollready(&gp, (void*)(uintptr)*(uint64*)ev->data, mode);
}
if(block && gp == nil)
goto retry;
return gp;
}
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build linux
package runtime
import "unsafe"
func epollcreate(size int32) int32
func epollcreate1(flags int32) int32
//go:noescape
func epollctl(epfd, op, fd int32, ev *epollevent) int32
//go:noescape
func epollwait(epfd int32, ev *epollevent, nev, timeout int32) int32
func closeonexec(fd int32)
var (
epfd int32 = -1 // epoll descriptor
netpolllasterr int32
)
func netpollinit() {
epfd = epollcreate1(_EPOLL_CLOEXEC)
if epfd >= 0 {
return
}
epfd = epollcreate(1024)
if epfd >= 0 {
closeonexec(epfd)
return
}
println("netpollinit: failed to create epoll descriptor", -epfd)
gothrow("netpollinit: failed to create descriptor")
}
func netpollopen(fd uintptr, pd *pollDesc) int32 {
var ev epollevent
ev.events = _EPOLLIN | _EPOLLOUT | _EPOLLRDHUP | _EPOLLET
*(**pollDesc)(unsafe.Pointer(&ev.data)) = pd
return -epollctl(epfd, _EPOLL_CTL_ADD, int32(fd), &ev)
}
func netpollclose(fd uintptr) int32 {
var ev epollevent
return -epollctl(epfd, _EPOLL_CTL_DEL, int32(fd), &ev)
}
func netpollarm(pd *pollDesc, mode int) {
gothrow("unused")
}
// polls for ready network connections
// returns list of goroutines that become runnable
func netpoll(block bool) (gp *g) {
if epfd == -1 {
return
}
waitms := int32(-1)
if !block {
waitms = 0
}
var events [128]epollevent
retry:
n := epollwait(epfd, &events[0], int32(len(events)), waitms)
if n < 0 {
if n != -_EINTR && n != netpolllasterr {
netpolllasterr = n
println("runtime: epollwait on fd", epfd, "failed with", -n)
}
goto retry
}
for i := int32(0); i < n; i++ {
ev := &events[i]
if ev.events == 0 {
continue
}
var mode int32
if ev.events&(_EPOLLIN|_EPOLLRDHUP|_EPOLLHUP|_EPOLLERR) != 0 {
mode += 'r'
}
if ev.events&(_EPOLLOUT|_EPOLLHUP|_EPOLLERR) != 0 {
mode += 'w'
}
if mode != 0 {
pd := *(**pollDesc)(unsafe.Pointer(&ev.data))
netpollready((**g)(noescape(unsafe.Pointer(&gp))), pd, mode)
}
}
if block && gp == nil {
goto retry
}
return gp
}
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd netbsd openbsd
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
// Integrated network poller (kqueue-based implementation).
int32 runtime·kqueue(void);
int32 runtime·kevent(int32, KeventT*, int32, KeventT*, int32, Timespec*);
void runtime·closeonexec(int32);
static int32 kq = -1;
void
runtime·netpollinit(void)
{
kq = runtime·kqueue();
if(kq < 0) {
runtime·printf("netpollinit: kqueue failed with %d\n", -kq);
runtime·throw("netpollinit: kqueue failed");
}
runtime·closeonexec(kq);
}
int32
runtime·netpollopen(uintptr fd, PollDesc *pd)
{
KeventT ev[2];
int32 n;
// Arm both EVFILT_READ and EVFILT_WRITE in edge-triggered mode (EV_CLEAR)
// for the whole fd lifetime. The notifications are automatically unregistered
// when fd is closed.
ev[0].ident = (uint32)fd;
ev[0].filter = EVFILT_READ;
ev[0].flags = EV_ADD|EV_CLEAR;
ev[0].fflags = 0;
ev[0].data = 0;
ev[0].udata = (kevent_udata)pd;
ev[1] = ev[0];
ev[1].filter = EVFILT_WRITE;
n = runtime·kevent(kq, ev, 2, nil, 0, nil);
if(n < 0)
return -n;
return 0;
}
int32
runtime·netpollclose(uintptr fd)
{
// Don't need to unregister because calling close()
// on fd will remove any kevents that reference the descriptor.
USED(fd);
return 0;
}
void
runtime·netpollarm(PollDesc* pd, int32 mode)
{
USED(pd, mode);
runtime·throw("unused");
}
// Polls for ready network connections.
// Returns list of goroutines that become runnable.
G*
runtime·netpoll(bool block)
{
static int32 lasterr;
KeventT events[64], *ev;
Timespec ts, *tp;
int32 n, i, mode;
G *gp;
if(kq == -1)
return nil;
tp = nil;
if(!block) {
ts.tv_sec = 0;
ts.tv_nsec = 0;
tp = &ts;
}
gp = nil;
retry:
n = runtime·kevent(kq, nil, 0, events, nelem(events), tp);
if(n < 0) {
if(n != -EINTR && n != lasterr) {
lasterr = n;
runtime·printf("runtime: kevent on fd %d failed with %d\n", kq, -n);
}
goto retry;
}
for(i = 0; i < n; i++) {
ev = &events[i];
mode = 0;
if(ev->filter == EVFILT_READ)
mode += 'r';
if(ev->filter == EVFILT_WRITE)
mode += 'w';
if(mode)
runtime·netpollready(&gp, (PollDesc*)ev->udata, mode);
}
if(block && gp == nil)
goto retry;
return gp;
}
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd netbsd openbsd
package runtime
// Integrated network poller (kqueue-based implementation).
import "unsafe"
func kqueue() int32
//go:noescape
func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32
func closeonexec(fd int32)
var (
kq int32 = -1
netpolllasterr int32
)
func netpollinit() {
kq = kqueue()
if kq < 0 {
println("netpollinit: kqueue failed with", -kq)
gothrow("netpollinit: kqueue failed")
}
closeonexec(kq)
}
func netpollopen(fd uintptr, pd *pollDesc) int32 {
// Arm both EVFILT_READ and EVFILT_WRITE in edge-triggered mode (EV_CLEAR)
// for the whole fd lifetime. The notifications are automatically unregistered
// when fd is closed.
var ev [2]keventt
*(*uintptr)(unsafe.Pointer(&ev[0].ident)) = fd
ev[0].filter = _EVFILT_READ
ev[0].flags = _EV_ADD | _EV_CLEAR
ev[0].fflags = 0
ev[0].data = 0
ev[0].udata = (*byte)(unsafe.Pointer(pd))
ev[1] = ev[0]
ev[1].filter = _EVFILT_WRITE
n := kevent(kq, &ev[0], 2, nil, 0, nil)
if n < 0 {
return -n
}
return 0
}
func netpollclose(fd uintptr) int32 {
// Don't need to unregister because calling close()
// on fd will remove any kevents that reference the descriptor.
return 0
}
func netpollarm(pd *pollDesc, mode int) {
gothrow("unused")
}
// Polls for ready network connections.
// Returns list of goroutines that become runnable.
func netpoll(block bool) (gp *g) {
if kq == -1 {
return
}
var tp *timespec
var ts timespec
if !block {
tp = &ts
}
var events [64]keventt
retry:
n := kevent(kq, nil, 0, &events[0], int32(len(events)), tp)
if n < 0 {
if n != -_EINTR && n != netpolllasterr {
netpolllasterr = n
println("runtime: kevent on fd", kq, "failed with", -n)
}
goto retry
}
for i := 0; i < int(n); i++ {
ev := &events[i]
var mode int32
if ev.filter == _EVFILT_READ {
mode += 'r'
}
if ev.filter == _EVFILT_WRITE {
mode += 'w'
}
if mode != 0 {
netpollready((**g)(noescape(unsafe.Pointer(&gp))), (*pollDesc)(unsafe.Pointer(ev.udata)), mode)
}
}
if block && gp == nil {
goto retry
}
return gp
}
...@@ -2,36 +2,25 @@ ...@@ -2,36 +2,25 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
// Fake network poller for NaCl. // Fake network poller for NaCl.
// Should never be used, because NaCl network connections do not honor "SetNonblock". // Should never be used, because NaCl network connections do not honor "SetNonblock".
void package runtime
runtime·netpollinit(void)
{ func netpollinit() {
}
func netpollopen(fd uintptr, pd *pollDesc) int32 {
return 0
} }
int32 func netpollclose(fd uintptr) int32 {
runtime·netpollopen(uintptr fd, PollDesc *pd) return 0
{
USED(fd);
USED(pd);
return 0;
} }
int32 func netpollarm(pd *pollDesc, mode int) {
runtime·netpollclose(uintptr fd)
{
USED(fd);
return 0;
} }
G* func netpoll(block bool) *g {
runtime·netpoll(bool block) return nil
{
USED(block);
return nil;
} }
...@@ -18,9 +18,6 @@ func sigaction(mode uint32, new, old unsafe.Pointer) ...@@ -18,9 +18,6 @@ func sigaction(mode uint32, new, old unsafe.Pointer)
func sigaltstack(new, old unsafe.Pointer) func sigaltstack(new, old unsafe.Pointer)
func sigtramp() func sigtramp()
func setitimer(mode int32, new, old unsafe.Pointer) func setitimer(mode int32, new, old unsafe.Pointer)
func kqueue() int32
func kevent(fd int32, ev1 unsafe.Pointer, nev1 int32, ev2 unsafe.Pointer, nev2 int32, ts unsafe.Pointer) int32
func closeonexec(fd int32)
func mach_semaphore_wait(sema uint32) int32 func mach_semaphore_wait(sema uint32) int32
func mach_semaphore_timedwait(sema, sec, nsec uint32) int32 func mach_semaphore_timedwait(sema, sec, nsec uint32) int32
func mach_semaphore_signal(sema uint32) int32 func mach_semaphore_signal(sema uint32) int32
......
...@@ -14,9 +14,6 @@ func setitimer(mode int32, new, old unsafe.Pointer) ...@@ -14,9 +14,6 @@ func setitimer(mode int32, new, old unsafe.Pointer)
func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32 func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
func getrlimit(kind int32, limit unsafe.Pointer) int32 func getrlimit(kind int32, limit unsafe.Pointer) int32
func raise(sig int32) func raise(sig int32)
func kqueue() int32
func kevent(fd int32, ev1 unsafe.Pointer, nev1 int32, ev2 unsafe.Pointer, nev2 int32, ts unsafe.Pointer) int32
func closeonexec(fd int32)
func sys_umtx_sleep(addr unsafe.Pointer, val, timeout int32) int32 func sys_umtx_sleep(addr unsafe.Pointer, val, timeout int32) int32
func sys_umtx_wakeup(addr unsafe.Pointer, val int32) int32 func sys_umtx_wakeup(addr unsafe.Pointer, val int32) int32
......
...@@ -14,9 +14,6 @@ func setitimer(mode int32, new, old unsafe.Pointer) ...@@ -14,9 +14,6 @@ func setitimer(mode int32, new, old unsafe.Pointer)
func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32 func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
func getrlimit(kind int32, limit unsafe.Pointer) int32 func getrlimit(kind int32, limit unsafe.Pointer) int32
func raise(sig int32) func raise(sig int32)
func kqueue() int32
func kevent(fd int32, ev1 unsafe.Pointer, nev1 int32, ev2 unsafe.Pointer, nev2 int32, ts unsafe.Pointer) int32
func closeonexec(fd int32)
func sys_umtx_op(addr unsafe.Pointer, mode int32, val uint32, ptr2, ts unsafe.Pointer) int32 func sys_umtx_op(addr unsafe.Pointer, mode int32, val uint32, ptr2, ts unsafe.Pointer) int32
const stackSystem = 0 const stackSystem = 0
...@@ -14,11 +14,6 @@ func setitimer(mode int32, new, old unsafe.Pointer) ...@@ -14,11 +14,6 @@ func setitimer(mode int32, new, old unsafe.Pointer)
func rtsigprocmask(sig int32, new, old unsafe.Pointer, size int32) func rtsigprocmask(sig int32, new, old unsafe.Pointer, size int32)
func getrlimit(kind int32, limit unsafe.Pointer) int32 func getrlimit(kind int32, limit unsafe.Pointer) int32
func raise(sig int32) func raise(sig int32)
func epollcreate(size int32) int32
func epollcreate1(flags int32) int32
func epollctl(epfd, op, fd int32, ev unsafe.Pointer) int32
func epollwait(epfd int32, ev unsafe.Pointer, nev, timeout int32) int32
func closeonexec(fd int32)
func sched_getaffinity(pid, len uintptr, buf *uintptr) int32 func sched_getaffinity(pid, len uintptr, buf *uintptr) int32
const stackSystem = 0 const stackSystem = 0
...@@ -13,9 +13,6 @@ func sigprocmask(mode int32, new, old unsafe.Pointer) ...@@ -13,9 +13,6 @@ func sigprocmask(mode int32, new, old unsafe.Pointer)
func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32 func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
func lwp_tramp() func lwp_tramp()
func raise(sig int32) func raise(sig int32)
func kqueue() int32
func kevent(fd int32, ev1 unsafe.Pointer, nev1 int32, ev2 unsafe.Pointer, nev2 int32, ts unsafe.Pointer) int32
func closeonexec(fd int32)
func getcontext(ctxt unsafe.Pointer) func getcontext(ctxt unsafe.Pointer)
func lwp_create(ctxt unsafe.Pointer, flags uintptr, lwpid unsafe.Pointer) int32 func lwp_create(ctxt unsafe.Pointer, flags uintptr, lwpid unsafe.Pointer) int32
func lwp_park(abstime unsafe.Pointer, unpark int32, hint, unparkhint unsafe.Pointer) int32 func lwp_park(abstime unsafe.Pointer, unpark int32, hint, unparkhint unsafe.Pointer) int32
......
...@@ -12,9 +12,6 @@ func sigaltstack(new, old unsafe.Pointer) ...@@ -12,9 +12,6 @@ func sigaltstack(new, old unsafe.Pointer)
func sigprocmask(mode int32, new uint32) uint32 func sigprocmask(mode int32, new uint32) uint32
func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32 func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
func raise(sig int32) func raise(sig int32)
func kqueue() int32
func kevent(fd int32, ev1 unsafe.Pointer, nev1 int32, ev2 unsafe.Pointer, nev2 int32, ts unsafe.Pointer) int32
func closeonexec(fd int32)
func tfork(param unsafe.Pointer, psize uintptr, mm, gg, fn unsafe.Pointer) int32 func tfork(param unsafe.Pointer, psize uintptr, mm, gg, fn unsafe.Pointer) int32
func thrsleep(ident unsafe.Pointer, clock_id int32, tsp, lock, abort unsafe.Pointer) int32 func thrsleep(ident unsafe.Pointer, clock_id int32, tsp, lock, abort unsafe.Pointer) int32
func thrwakeup(ident unsafe.Pointer, n int32) int32 func thrwakeup(ident unsafe.Pointer, n int32) int32
......
...@@ -19,6 +19,10 @@ func tstart_sysvicall(mm unsafe.Pointer) uint32 ...@@ -19,6 +19,10 @@ func tstart_sysvicall(mm unsafe.Pointer) uint32
func nanotime1() int64 func nanotime1() int64
func usleep1(usec uint32) func usleep1(usec uint32)
func osyield1() func osyield1()
func netpollinit()
func netpollopen(fd uintptr, pd *pollDesc) int32
func netpollclose(fd uintptr) int32
func netpollarm(pd *pollDesc, mode int)
type libcFunc byte type libcFunc byte
......
...@@ -21,6 +21,10 @@ func asmstdcall(fn unsafe.Pointer) ...@@ -21,6 +21,10 @@ func asmstdcall(fn unsafe.Pointer)
func getlasterror() uint32 func getlasterror() uint32
func setlasterror(err uint32) func setlasterror(err uint32)
func usleep1(usec uint32) func usleep1(usec uint32)
func netpollinit()
func netpollopen(fd uintptr, pd *pollDesc) int32
func netpollclose(fd uintptr) int32
func netpollarm(pd *pollDesc, mode int)
const stackSystem = 512 * ptrSize const stackSystem = 512 * ptrSize
......
...@@ -886,12 +886,8 @@ int64 runtime·cputicks(void); ...@@ -886,12 +886,8 @@ int64 runtime·cputicks(void);
int64 runtime·tickspersecond(void); int64 runtime·tickspersecond(void);
void runtime·blockevent(int64, intgo); void runtime·blockevent(int64, intgo);
G* runtime·netpoll(bool); G* runtime·netpoll(bool);
void runtime·netpollinit(void);
int32 runtime·netpollopen(uintptr, PollDesc*);
int32 runtime·netpollclose(uintptr);
void runtime·netpollready(G**, PollDesc*, int32); void runtime·netpollready(G**, PollDesc*, int32);
uintptr runtime·netpollfd(PollDesc*); uintptr runtime·netpollfd(PollDesc*);
void runtime·netpollarm(PollDesc*, int32);
void** runtime·netpolluser(PollDesc*); void** runtime·netpolluser(PollDesc*);
bool runtime·netpollclosing(PollDesc*); bool runtime·netpollclosing(PollDesc*);
void runtime·netpolllock(PollDesc*); void runtime·netpolllock(PollDesc*);
......
...@@ -237,6 +237,9 @@ func xchg64(ptr *uint64, new uint64) uint64 ...@@ -237,6 +237,9 @@ func xchg64(ptr *uint64, new uint64) uint64
//go:noescape //go:noescape
func xchgp(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer func xchgp(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer
//go:noescape
func xchguintptr(ptr *uintptr, new uintptr) uintptr
//go:noescape //go:noescape
func atomicstore(ptr *uint32, val uint32) func atomicstore(ptr *uint32, val uint32)
......
...@@ -457,7 +457,7 @@ TEXT runtime·epollcreate1(SB),NOSPLIT,$0 ...@@ -457,7 +457,7 @@ TEXT runtime·epollcreate1(SB),NOSPLIT,$0
MOVL AX, ret+4(FP) MOVL AX, ret+4(FP)
RET RET
// int32 runtime·epollctl(int32 epfd, int32 op, int32 fd, EpollEvent *ev); // func epollctl(epfd, op, fd int32, ev *epollEvent) int
TEXT runtime·epollctl(SB),NOSPLIT,$0 TEXT runtime·epollctl(SB),NOSPLIT,$0
MOVL $255, AX MOVL $255, AX
MOVL epfd+0(FP), BX MOVL epfd+0(FP), BX
......
...@@ -378,7 +378,7 @@ TEXT runtime·epollcreate1(SB),NOSPLIT,$0 ...@@ -378,7 +378,7 @@ TEXT runtime·epollcreate1(SB),NOSPLIT,$0
MOVL AX, ret+8(FP) MOVL AX, ret+8(FP)
RET RET
// int32 runtime·epollctl(int32 epfd, int32 op, int32 fd, EpollEvent *ev); // func epollctl(epfd, op, fd int32, ev *epollEvent) int
TEXT runtime·epollctl(SB),NOSPLIT,$0 TEXT runtime·epollctl(SB),NOSPLIT,$0
MOVL epfd+0(FP), DI MOVL epfd+0(FP), DI
MOVL op+4(FP), SI MOVL op+4(FP), SI
......
...@@ -424,12 +424,12 @@ TEXT runtime·epollcreate1(SB),NOSPLIT,$0 ...@@ -424,12 +424,12 @@ TEXT runtime·epollcreate1(SB),NOSPLIT,$0
MOVW R0, ret+4(FP) MOVW R0, ret+4(FP)
RET RET
// int32 runtime·epollctl(int32 epfd, int32 op, int32 fd, EpollEvent *ev) // func epollctl(epfd, op, fd int32, ev *epollEvent) int
TEXT runtime·epollctl(SB),NOSPLIT,$0 TEXT runtime·epollctl(SB),NOSPLIT,$0
MOVW 0(FP), R0 MOVW epfd+0(FP), R0
MOVW 4(FP), R1 MOVW op+4(FP), R1
MOVW 8(FP), R2 MOVW fd+8(FP), R2
MOVW 12(FP), R3 MOVW ev+12(FP), R3
MOVW $SYS_epoll_ctl, R7 MOVW $SYS_epoll_ctl, R7
SWI $0 SWI $0
MOVW R0, ret+16(FP) MOVW R0, ret+16(FP)
......
...@@ -11,6 +11,9 @@ ...@@ -11,6 +11,9 @@
#define JMP B #define JMP B
#endif #endif
TEXT net·runtimeNano(SB),NOSPLIT,$0-0
JMP runtime·nanotime(SB)
TEXT time·runtimeNano(SB),NOSPLIT,$0-0 TEXT time·runtimeNano(SB),NOSPLIT,$0-0
JMP runtime·nanotime(SB) JMP runtime·nanotime(SB)
...@@ -74,6 +77,30 @@ TEXT reflect·chanrecv(SB), NOSPLIT, $0-0 ...@@ -74,6 +77,30 @@ TEXT reflect·chanrecv(SB), NOSPLIT, $0-0
TEXT runtimedebug·freeOSMemory(SB), NOSPLIT, $0-0 TEXT runtimedebug·freeOSMemory(SB), NOSPLIT, $0-0
JMP runtime·freeOSMemory(SB) JMP runtime·freeOSMemory(SB)
TEXT net·runtime_pollServerInit(SB),NOSPLIT,$0-0
JMP runtime·netpollServerInit(SB)
TEXT net·runtime_pollOpen(SB),NOSPLIT,$0-0
JMP runtime·netpollOpen(SB)
TEXT net·runtime_pollClose(SB),NOSPLIT,$0-0
JMP runtime·netpollClose(SB)
TEXT net·runtime_pollReset(SB),NOSPLIT,$0-0
JMP runtime·netpollReset(SB)
TEXT net·runtime_pollWait(SB),NOSPLIT,$0-0
JMP runtime·netpollWait(SB)
TEXT net·runtime_pollWaitCanceled(SB),NOSPLIT,$0-0
JMP runtime·netpollWaitCanceled(SB)
TEXT net·runtime_pollSetDeadline(SB),NOSPLIT,$0-0
JMP runtime·netpollSetDeadline(SB)
TEXT net·runtime_pollUnblock(SB),NOSPLIT,$0-0
JMP runtime·netpollUnblock(SB)
TEXT syscall·setenv_c(SB), NOSPLIT, $0-0 TEXT syscall·setenv_c(SB), NOSPLIT, $0-0
JMP runtime·syscall_setenv_c(SB) JMP runtime·syscall_setenv_c(SB)
......
...@@ -9,7 +9,7 @@ package runtime ...@@ -9,7 +9,7 @@ package runtime
import "unsafe" import "unsafe"
// Package time knows the layout of this structure. // Package time knows the layout of this structure.
// If this struct changes, adjust ../time/sleep.go:/runtimeTimer and netpoll.goc:/timer. // If this struct changes, adjust ../time/sleep.go:/runtimeTimer.
// For GOOS=nacl, package syscall knows the layout of this structure. // For GOOS=nacl, package syscall knows the layout of this structure.
// If this struct changes, adjust ../syscall/net_nacl.go:/runtimeTimer. // If this struct changes, adjust ../syscall/net_nacl.go:/runtimeTimer.
type timer struct { type timer struct {
...@@ -20,8 +20,9 @@ type timer struct { ...@@ -20,8 +20,9 @@ type timer struct {
// a well-behaved function and not block. // a well-behaved function and not block.
when int64 when int64
period int64 period int64
f func(interface{}) f func(interface{}, uintptr)
arg interface{} arg interface{}
seq uintptr
} }
var timers struct { var timers struct {
...@@ -74,7 +75,7 @@ func stopTimer(t *timer) bool { ...@@ -74,7 +75,7 @@ func stopTimer(t *timer) bool {
// Go runtime. // Go runtime.
// Ready the goroutine arg. // Ready the goroutine arg.
func goroutineReady(arg interface{}) { func goroutineReady(arg interface{}, seq uintptr) {
goready(arg.(*g)) goready(arg.(*g))
} }
...@@ -185,11 +186,12 @@ func timerproc() { ...@@ -185,11 +186,12 @@ func timerproc() {
} }
f := t.f f := t.f
arg := t.arg arg := t.arg
seq := t.seq
unlock(&timers.lock) unlock(&timers.lock)
if raceenabled { if raceenabled {
raceacquire(unsafe.Pointer(t)) raceacquire(unsafe.Pointer(t))
} }
f(arg) f(arg, seq)
lock(&timers.lock) lock(&timers.lock)
} }
if delta < 0 { if delta < 0 {
......
...@@ -21,8 +21,9 @@ type runtimeTimer struct { ...@@ -21,8 +21,9 @@ type runtimeTimer struct {
i int i int
when int64 when int64
period int64 period int64
f func(interface{}) // NOTE: must not be closure f func(interface{}, uintptr) // NOTE: must not be closure
arg interface{} arg interface{}
seq uintptr
} }
func startTimer(*runtimeTimer) func startTimer(*runtimeTimer)
...@@ -49,7 +50,7 @@ func (t *timer) stop() { ...@@ -49,7 +50,7 @@ func (t *timer) stop() {
stopTimer(&t.r) stopTimer(&t.r)
} }
func timerExpired(i interface{}) { func timerExpired(i interface{}, seq uintptr) {
t := i.(*timer) t := i.(*timer)
go func() { go func() {
t.q.Lock() t.q.Lock()
......
...@@ -12,7 +12,7 @@ func init() { ...@@ -12,7 +12,7 @@ func init() {
var Interrupt = interrupt var Interrupt = interrupt
var DaysIn = daysIn var DaysIn = daysIn
func empty(arg interface{}) {} func empty(arg interface{}, seq uintptr) {}
// Test that a runtimeTimer with a duration so large it overflows // Test that a runtimeTimer with a duration so large it overflows
// does not cause other timers to hang. // does not cause other timers to hang.
......
...@@ -17,8 +17,9 @@ type runtimeTimer struct { ...@@ -17,8 +17,9 @@ type runtimeTimer struct {
i int i int
when int64 when int64
period int64 period int64
f func(interface{}) // NOTE: must not be closure f func(interface{}, uintptr) // NOTE: must not be closure
arg interface{} arg interface{}
seq uintptr
} }
// when is a helper function for setting the 'when' field of a runtimeTimer. // when is a helper function for setting the 'when' field of a runtimeTimer.
...@@ -83,7 +84,7 @@ func (t *Timer) Reset(d Duration) bool { ...@@ -83,7 +84,7 @@ func (t *Timer) Reset(d Duration) bool {
return active return active
} }
func sendTime(c interface{}) { func sendTime(c interface{}, seq uintptr) {
// Non-blocking send of time on c. // Non-blocking send of time on c.
// Used in NewTimer, it cannot block anyway (buffer). // Used in NewTimer, it cannot block anyway (buffer).
// Used in NewTicker, dropping sends on the floor is // Used in NewTicker, dropping sends on the floor is
...@@ -117,6 +118,6 @@ func AfterFunc(d Duration, f func()) *Timer { ...@@ -117,6 +118,6 @@ func AfterFunc(d Duration, f func()) *Timer {
return t return t
} }
func goFunc(arg interface{}) { func goFunc(arg interface{}, seq uintptr) {
go arg.(func())() go arg.(func())()
} }
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