Commit e088e162 authored by Aram Hăvărneanu's avatar Aram Hăvărneanu

[dev.cc] runtime: convert Solaris port to Go

Memory management was consolitated with the BSD ports, since
it was almost identical.

Assembly thunks are gone, being replaced by the new //go:linkname
feature.

This change supersedes CL 138390043 (runtime: convert solaris
netpoll to Go), which was previously reviewed and tested.

This change is only the first step, the port now builds,
but doesn't run. Binaries fail to exec:

    ld.so.1: 6.out: fatal: 6.out: TLS requirement failure : TLS support is unavailable
    Killed

This seems to happen because binaries don't link with libc.so
anymore. We will have to solve that in a different CL.

Also this change is just a rough translation of the original
C code, cleanup will come in a different CL.

[This CL is part of the removal of C code from package runtime.
See golang.org/s/dev.cc for an overview.]

LGTM=rsc
R=rsc, dave
CC=golang-codereviews, iant, khr, minux, r, rlh
https://golang.org/cl/174960043
parent a0862a17
...@@ -1543,9 +1543,8 @@ static vlong vaddr(Link*, Addr*, Reloc*); ...@@ -1543,9 +1543,8 @@ static vlong vaddr(Link*, Addr*, Reloc*);
static int static int
isextern(LSym *s) isextern(LSym *s)
{ {
// All the Solaris dynamic imports from libc.so begin with "libc·", which // All the Solaris dynamic imports from libc.so begin with "libc_".
// the compiler rewrites to "libc." by the time liblink gets it. return strncmp(s->name, "libc_", 5) == 0;
return strncmp(s->name, "libc.", 5) == 0;
} }
// single-instruction no-ops of various lengths. // single-instruction no-ops of various lengths.
......
...@@ -172,6 +172,10 @@ type timeval struct { ...@@ -172,6 +172,10 @@ type timeval struct {
tv_usec int64 tv_usec int64
} }
func (tv *timeval) set_usec(x int32) {
tv.tv_usec = int64(x)
}
type itimerval struct { type itimerval struct {
it_interval timeval it_interval timeval
it_value timeval it_value timeval
...@@ -185,6 +189,7 @@ type portevent struct { ...@@ -185,6 +189,7 @@ type portevent struct {
portev_user *byte portev_user *byte
} }
type pthread uint32
type pthreadattr struct { type pthreadattr struct {
__pthread_attrp *byte __pthread_attrp *byte
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// 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.
// +build dragonfly freebsd netbsd openbsd // +build dragonfly freebsd netbsd openbsd solaris
package runtime package runtime
......
// Copyright 2010 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.
#include "runtime.h"
#include "arch_GOARCH.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
#include "malloc.h"
#include "textflag.h"
enum
{
ENOMEM = 12,
};
#pragma textflag NOSPLIT
void*
runtime·sysAlloc(uintptr n, uint64 *stat)
{
void *v;
v = runtime·mmap(nil, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
if(v < (void*)4096)
return nil;
runtime·xadd64(stat, n);
return v;
}
void
runtime·SysUnused(void *v, uintptr n)
{
USED(v);
USED(n);
}
void
runtime·SysUsed(void *v, uintptr n)
{
USED(v);
USED(n);
}
void
runtime·SysFree(void *v, uintptr n, uint64 *stat)
{
runtime·xadd64(stat, -(uint64)n);
runtime·munmap(v, n);
}
void
runtime·SysFault(void *v, uintptr n)
{
runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0);
}
void*
runtime·SysReserve(void *v, uintptr n, bool *reserved)
{
void *p;
// On 64-bit, people with ulimit -v set complain if we reserve too
// much address space. Instead, assume that the reservation is okay
// and check the assumption in SysMap.
if(sizeof(void*) == 8 && n > 1LL<<32) {
*reserved = false;
return v;
}
p = runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
if(p < (void*)4096)
return nil;
*reserved = true;
return p;
}
void
runtime·SysMap(void *v, uintptr n, bool reserved, uint64 *stat)
{
void *p;
runtime·xadd64(stat, n);
// On 64-bit, we don't actually have v reserved, so tread carefully.
if(!reserved) {
p = runtime·mmap(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
if(p == (void*)ENOMEM)
runtime·throw("runtime: out of memory");
if(p != v) {
runtime·printf("runtime: address space conflict: map(%p) = %p\n", v, p);
runtime·throw("runtime: address space conflict");
}
return;
}
p = runtime·mmap(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
if(p == (void*)ENOMEM)
runtime·throw("runtime: out of memory");
if(p != v)
runtime·throw("runtime: cannot map pages in arena address space");
}
...@@ -56,7 +56,7 @@ type pollDesc struct { ...@@ -56,7 +56,7 @@ type pollDesc struct {
wg uintptr // pdReady, pdWait, G waiting for write or nil wg uintptr // pdReady, pdWait, G waiting for write or nil
wt timer // write deadline timer wt timer // write deadline timer
wd int64 // write deadline wd int64 // write deadline
user unsafe.Pointer // user settable cookie user uint32 // user settable cookie
} }
type pollCache struct { type pollCache struct {
...@@ -72,7 +72,7 @@ type pollCache struct { ...@@ -72,7 +72,7 @@ type pollCache struct {
var pollcache pollCache var pollcache pollCache
func netpollServerInit() { func netpollServerInit() {
systemstack(netpollinit) netpollinit()
} }
func netpollOpen(fd uintptr) (*pollDesc, int) { func netpollOpen(fd uintptr) (*pollDesc, int) {
...@@ -94,9 +94,7 @@ func netpollOpen(fd uintptr) (*pollDesc, int) { ...@@ -94,9 +94,7 @@ func netpollOpen(fd uintptr) (*pollDesc, int) {
unlock(&pd.lock) unlock(&pd.lock)
var errno int32 var errno int32
systemstack(func() {
errno = netpollopen(fd, pd) errno = netpollopen(fd, pd)
})
return pd, int(errno) return pd, int(errno)
} }
...@@ -110,9 +108,7 @@ func netpollClose(pd *pollDesc) { ...@@ -110,9 +108,7 @@ func netpollClose(pd *pollDesc) {
if pd.rg != 0 && pd.rg != pdReady { if pd.rg != 0 && pd.rg != pdReady {
gothrow("netpollClose: blocked read on closing descriptor") gothrow("netpollClose: blocked read on closing descriptor")
} }
systemstack(func() {
netpollclose(uintptr(pd.fd)) netpollclose(uintptr(pd.fd))
})
pollcache.free(pd) pollcache.free(pd)
} }
...@@ -143,9 +139,7 @@ func netpollWait(pd *pollDesc, mode int) int { ...@@ -143,9 +139,7 @@ func netpollWait(pd *pollDesc, mode int) int {
} }
// As for now only Solaris uses level-triggered IO. // As for now only Solaris uses level-triggered IO.
if GOOS == "solaris" { if GOOS == "solaris" {
systemstack(func() {
netpollarm(pd, mode) netpollarm(pd, mode)
})
} }
for !netpollblock(pd, int32(mode), false) { for !netpollblock(pd, int32(mode), false) {
err = netpollcheckerr(pd, int32(mode)) err = netpollcheckerr(pd, int32(mode))
...@@ -263,26 +257,6 @@ func netpollUnblock(pd *pollDesc) { ...@@ -263,26 +257,6 @@ func netpollUnblock(pd *pollDesc) {
} }
} }
func netpollfd(pd *pollDesc) uintptr {
return pd.fd
}
func netpolluser(pd *pollDesc) *unsafe.Pointer {
return &pd.user
}
func netpollclosing(pd *pollDesc) bool {
return pd.closing
}
func netpolllock(pd *pollDesc) {
lock(&pd.lock)
}
func netpollunlock(pd *pollDesc) {
unlock(&pd.lock)
}
// make pd ready, newly runnable goroutines (if any) are returned in rg/wg // make pd ready, newly runnable goroutines (if any) are returned in rg/wg
func netpollready(gpp **g, pd *pollDesc, mode int32) { func netpollready(gpp **g, pd *pollDesc, mode int32) {
var rg, wg *g var rg, wg *g
......
...@@ -2,10 +2,9 @@ ...@@ -2,10 +2,9 @@
// 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" package runtime
#include "arch_GOARCH.h"
#include "defs_GOOS_GOARCH.h" import "unsafe"
#include "os_GOOS.h"
// Solaris runtime-integrated network poller. // Solaris runtime-integrated network poller.
// //
...@@ -68,179 +67,157 @@ ...@@ -68,179 +67,157 @@
// again we know for sure we are always talking about the same file // again we know for sure we are always talking about the same file
// descriptor and can safely access the data we want (the event set). // descriptor and can safely access the data we want (the event set).
#pragma dynimport libc·fcntl fcntl "libc.so" //go:cgo_import_dynamic libc_port_create port_create "libc.so"
#pragma dynimport libc·port_create port_create "libc.so" //go:cgo_import_dynamic libc_port_associate port_associate "libc.so"
#pragma dynimport libc·port_associate port_associate "libc.so" //go:cgo_import_dynamic libc_port_dissociate port_dissociate "libc.so"
#pragma dynimport libc·port_dissociate port_dissociate "libc.so" //go:cgo_import_dynamic libc_port_getn port_getn "libc.so"
#pragma dynimport libc·port_getn port_getn "libc.so"
extern uintptr libc·fcntl; //go:linkname libc_port_create libc_port_create
extern uintptr libc·port_create; //go:linkname libc_port_associate libc_port_associate
extern uintptr libc·port_associate; //go:linkname libc_port_dissociate libc_port_dissociate
extern uintptr libc·port_dissociate; //go:linkname libc_port_getn libc_port_getn
extern uintptr libc·port_getn;
var (
#define errno (*g->m->perrno) libc_port_create,
libc_port_associate,
libc_port_dissociate,
libc_port_getn libcFunc
)
func errno() int32 {
return *getg().m.perrno
}
int32 func fcntl(fd, cmd int32, arg uintptr) int32 {
runtime·fcntl(int32 fd, int32 cmd, uintptr arg) return int32(sysvicall3(libc_fcntl, uintptr(fd), uintptr(cmd), arg))
{
return runtime·sysvicall3(libc·fcntl, (uintptr)fd, (uintptr)cmd, (uintptr)arg);
} }
int32 func port_create() int32 {
runtime·port_create(void) return int32(sysvicall0(libc_port_create))
{
return runtime·sysvicall0(libc·port_create);
} }
int32 func port_associate(port, source int32, object uintptr, events uint32, user uintptr) int32 {
runtime·port_associate(int32 port, int32 source, uintptr object, int32 events, uintptr user) return int32(sysvicall5(libc_port_associate, uintptr(port), uintptr(source), object, uintptr(events), user))
{
return runtime·sysvicall5(libc·port_associate, (uintptr)port, (uintptr)source, object, (uintptr)events, user);
} }
int32 func port_dissociate(port, source int32, object uintptr) int32 {
runtime·port_dissociate(int32 port, int32 source, uintptr object) return int32(sysvicall3(libc_port_dissociate, uintptr(port), uintptr(source), object))
{
return runtime·sysvicall3(libc·port_dissociate, (uintptr)port, (uintptr)source, object);
} }
int32 func port_getn(port int32, evs *portevent, max uint32, nget *uint32, timeout *timespec) int32 {
runtime·port_getn(int32 port, PortEvent *evs, uint32 max, uint32 *nget, Timespec *timeout) return int32(sysvicall5(libc_port_getn, uintptr(port), uintptr(unsafe.Pointer(evs)), uintptr(max), uintptr(unsafe.Pointer(nget)), uintptr(unsafe.Pointer(timeout))))
{
return runtime·sysvicall5(libc·port_getn, (uintptr)port, (uintptr)evs, (uintptr)max, (uintptr)nget, (uintptr)timeout);
} }
static int32 portfd = -1; var portfd int32 = -1
void func netpollinit() {
runtime·netpollinit(void) portfd = port_create()
{ if portfd >= 0 {
if((portfd = runtime·port_create()) >= 0) { fcntl(portfd, _F_SETFD, _FD_CLOEXEC)
runtime·fcntl(portfd, F_SETFD, FD_CLOEXEC); return
return;
} }
runtime·printf("netpollinit: failed to create port (%d)\n", errno); print("netpollinit: failed to create port (", errno(), ")\n")
runtime·throw("netpollinit: failed to create port"); gothrow("netpollinit: failed to create port")
} }
int32 func netpollopen(fd uintptr, pd *pollDesc) int32 {
runtime·netpollopen(uintptr fd, PollDesc *pd) lock(&pd.lock)
{
int32 r;
runtime·netpolllock(pd);
// We don't register for any specific type of events yet, that's // We don't register for any specific type of events yet, that's
// netpollarm's job. We merely ensure we call port_associate before // netpollarm's job. We merely ensure we call port_associate before
// asynchonous connect/accept completes, so when we actually want // asynchonous connect/accept completes, so when we actually want
// to do any I/O, the call to port_associate (from netpollarm, // to do any I/O, the call to port_associate (from netpollarm,
// with the interested event set) will unblock port_getn right away // with the interested event set) will unblock port_getn right away
// because of the I/O readiness notification. // because of the I/O readiness notification.
*runtime·netpolluser(pd) = 0; pd.user = 0
r = runtime·port_associate(portfd, PORT_SOURCE_FD, fd, 0, (uintptr)pd); r := port_associate(portfd, _PORT_SOURCE_FD, fd, 0, uintptr(unsafe.Pointer(pd)))
runtime·netpollunlock(pd); unlock(&pd.lock)
return r; return r
} }
int32 func netpollclose(fd uintptr) int32 {
runtime·netpollclose(uintptr fd) return port_dissociate(portfd, _PORT_SOURCE_FD, fd)
{
return runtime·port_dissociate(portfd, PORT_SOURCE_FD, fd);
} }
// Updates the association with a new set of interested events. After // Updates the association with a new set of interested events. After
// this call, port_getn will return one and only one event for that // this call, port_getn will return one and only one event for that
// particular descriptor, so this function needs to be called again. // particular descriptor, so this function needs to be called again.
void func netpollupdate(pd *pollDesc, set, clear uint32) {
runtime·netpollupdate(PollDesc* pd, uint32 set, uint32 clear) if pd.closing {
{ return
uint32 *ep, old, events; }
uintptr fd = runtime·netpollfd(pd);
ep = (uint32*)runtime·netpolluser(pd);
if(runtime·netpollclosing(pd))
return;
old = *ep; old := pd.user
events = (old & ~clear) | set; events := (old & ^clear) | set
if(old == events) if old == events {
return; return
}
if(events && runtime·port_associate(portfd, PORT_SOURCE_FD, fd, events, (uintptr)pd) != 0) { if events != 0 && port_associate(portfd, _PORT_SOURCE_FD, pd.fd, events, uintptr(unsafe.Pointer(pd))) != 0 {
runtime·printf("netpollupdate: failed to associate (%d)\n", errno); print("netpollupdate: failed to associate (", errno(), ")\n")
runtime·throw("netpollupdate: failed to associate"); gothrow("netpollupdate: failed to associate")
} }
*ep = events; pd.user = events
} }
// subscribe the fd to the port such that port_getn will return one event. // subscribe the fd to the port such that port_getn will return one event.
void func netpollarm(pd *pollDesc, mode int) {
runtime·netpollarm(PollDesc* pd, int32 mode) lock(&pd.lock)
{ switch mode {
runtime·netpolllock(pd);
switch(mode) {
case 'r': case 'r':
runtime·netpollupdate(pd, POLLIN, 0); netpollupdate(pd, _POLLIN, 0)
break;
case 'w': case 'w':
runtime·netpollupdate(pd, POLLOUT, 0); netpollupdate(pd, _POLLOUT, 0)
break;
default: default:
runtime·throw("netpollarm: bad mode"); gothrow("netpollarm: bad mode")
} }
runtime·netpollunlock(pd); unlock(&pd.lock)
} }
// netpolllasterr holds the last error code returned by port_getn to prevent log spamming
var netpolllasterr int32
// polls for ready network connections // polls for ready network connections
// returns list of goroutines that become runnable // returns list of goroutines that become runnable
G* func netpoll(block bool) (gp *g) {
runtime·netpoll(bool block) if portfd == -1 {
{ return
static int32 lasterr; }
PortEvent events[128], *ev;
PollDesc *pd;
int32 i, mode, clear;
uint32 n;
Timespec *wait = nil, zero;
G *gp;
if(portfd == -1)
return (nil);
if(!block) { var wait *timespec
zero.tv_sec = 0; var zero timespec
zero.tv_nsec = 0; if !block {
wait = &zero; wait = &zero
} }
var events [128]portevent
retry: retry:
n = 1; var n uint32 = 1
if(runtime·port_getn(portfd, events, nelem(events), &n, wait) < 0) { if port_getn(portfd, &events[0], uint32(len(events)), &n, wait) < 0 {
if(errno != EINTR && errno != lasterr) { if e := errno(); e != _EINTR && e != netpolllasterr {
lasterr = errno; netpolllasterr = e
runtime·printf("runtime: port_getn on fd %d failed with %d\n", portfd, errno); print("runtime: port_getn on fd ", portfd, " failed with ", e, "\n")
} }
goto retry; goto retry
} }
gp = nil; gp = nil
for(i = 0; i < n; i++) { for i := 0; i < int(n); i++ {
ev = &events[i]; ev := &events[i]
if(ev->portev_events == 0) if ev.portev_events == 0 {
continue; continue
pd = (PollDesc *)ev->portev_user; }
pd := (*pollDesc)(unsafe.Pointer(ev.portev_user))
mode = 0; var mode, clear int32
clear = 0; if (ev.portev_events & (_POLLIN | _POLLHUP | _POLLERR)) != 0 {
if(ev->portev_events & (POLLIN|POLLHUP|POLLERR)) { mode += 'r'
mode += 'r'; clear |= _POLLIN
clear |= POLLIN;
} }
if(ev->portev_events & (POLLOUT|POLLHUP|POLLERR)) { if (ev.portev_events & (_POLLOUT | _POLLHUP | _POLLERR)) != 0 {
mode += 'w'; mode += 'w'
clear |= POLLOUT; clear |= _POLLOUT
} }
// To effect edge-triggered events, we need to be sure to // To effect edge-triggered events, we need to be sure to
// update our association with whatever events were not // update our association with whatever events were not
...@@ -248,17 +225,19 @@ retry: ...@@ -248,17 +225,19 @@ retry:
// for POLLIN|POLLOUT, and we get POLLIN, besides waking // for POLLIN|POLLOUT, and we get POLLIN, besides waking
// the goroutine interested in POLLIN we have to not forget // the goroutine interested in POLLIN we have to not forget
// about the one interested in POLLOUT. // about the one interested in POLLOUT.
if(clear != 0) { if clear != 0 {
runtime·netpolllock(pd); lock(&pd.lock)
runtime·netpollupdate(pd, 0, clear); netpollupdate(pd, 0, uint32(clear))
runtime·netpollunlock(pd); unlock(&pd.lock)
} }
if(mode) if mode != 0 {
runtime·netpollready(&gp, pd, mode); netpollready((**g)(noescape(unsafe.Pointer(&gp))), pd, mode)
}
} }
if(block && gp == nil) if block && gp == nil {
goto retry; goto retry
return gp; }
return gp
} }
// Copyright 2014 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.
package runtime
const (
_SS_DISABLE = 2
_SIG_SETMASK = 3
_NSIG = 73 /* number of signals in sigtable array */
_SI_USER = 0
_RLIMIT_AS = 10
)
// Copyright 2011 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.
package runtime
import "unsafe"
//go:cgo_export_dynamic runtime.end _end
//go:cgo_export_dynamic runtime.etext _etext
//go:cgo_export_dynamic runtime.edata _edata
//go:cgo_import_dynamic libc____errno ___errno "libc.so"
//go:cgo_import_dynamic libc_clock_gettime clock_gettime "libc.so"
//go:cgo_import_dynamic libc_close close "libc.so"
//go:cgo_import_dynamic libc_exit exit "libc.so"
//go:cgo_import_dynamic libc_fstat fstat "libc.so"
//go:cgo_import_dynamic libc_getcontext getcontext "libc.so"
//go:cgo_import_dynamic libc_getrlimit getrlimit "libc.so"
//go:cgo_import_dynamic libc_madvise madvise "libc.so"
//go:cgo_import_dynamic libc_malloc malloc "libc.so"
//go:cgo_import_dynamic libc_mmap mmap "libc.so"
//go:cgo_import_dynamic libc_munmap munmap "libc.so"
//go:cgo_import_dynamic libc_open open "libc.so"
//go:cgo_import_dynamic libc_pthread_attr_destroy pthread_attr_destroy "libc.so"
//go:cgo_import_dynamic libc_pthread_attr_getstack pthread_attr_getstack "libc.so"
//go:cgo_import_dynamic libc_pthread_attr_init pthread_attr_init "libc.so"
//go:cgo_import_dynamic libc_pthread_attr_setdetachstate pthread_attr_setdetachstate "libc.so"
//go:cgo_import_dynamic libc_pthread_attr_setstack pthread_attr_setstack "libc.so"
//go:cgo_import_dynamic libc_pthread_create pthread_create "libc.so"
//go:cgo_import_dynamic libc_raise raise "libc.so"
//go:cgo_import_dynamic libc_read read "libc.so"
//go:cgo_import_dynamic libc_select select "libc.so"
//go:cgo_import_dynamic libc_sched_yield sched_yield "libc.so"
//go:cgo_import_dynamic libc_sem_init sem_init "libc.so"
//go:cgo_import_dynamic libc_sem_post sem_post "libc.so"
//go:cgo_import_dynamic libc_sem_reltimedwait_np sem_reltimedwait_np "libc.so"
//go:cgo_import_dynamic libc_sem_wait sem_wait "libc.so"
//go:cgo_import_dynamic libc_setitimer setitimer "libc.so"
//go:cgo_import_dynamic libc_sigaction sigaction "libc.so"
//go:cgo_import_dynamic libc_sigaltstack sigaltstack "libc.so"
//go:cgo_import_dynamic libc_sigprocmask sigprocmask "libc.so"
//go:cgo_import_dynamic libc_sysconf sysconf "libc.so"
//go:cgo_import_dynamic libc_usleep usleep "libc.so"
//go:cgo_import_dynamic libc_write write "libc.so"
//go:linkname libc____errno libc____errno
//go:linkname libc_clock_gettime libc_clock_gettime
//go:linkname libc_close libc_close
//go:linkname libc_exit libc_exit
//go:linkname libc_fstat libc_fstat
//go:linkname libc_getcontext libc_getcontext
//go:linkname libc_getrlimit libc_getrlimit
//go:linkname libc_madvise libc_madvise
//go:linkname libc_malloc libc_malloc
//go:linkname libc_mmap libc_mmap
//go:linkname libc_munmap libc_munmap
//go:linkname libc_open libc_open
//go:linkname libc_pthread_attr_destroy libc_pthread_attr_destroy
//go:linkname libc_pthread_attr_getstack libc_pthread_attr_getstack
//go:linkname libc_pthread_attr_init libc_pthread_attr_init
//go:linkname libc_pthread_attr_setdetachstate libc_pthread_attr_setdetachstate
//go:linkname libc_pthread_attr_setstack libc_pthread_attr_setstack
//go:linkname libc_pthread_create libc_pthread_create
//go:linkname libc_raise libc_raise
//go:linkname libc_read libc_read
//go:linkname libc_select libc_select
//go:linkname libc_sched_yield libc_sched_yield
//go:linkname libc_sem_init libc_sem_init
//go:linkname libc_sem_post libc_sem_post
//go:linkname libc_sem_reltimedwait_np libc_sem_reltimedwait_np
//go:linkname libc_sem_wait libc_sem_wait
//go:linkname libc_setitimer libc_setitimer
//go:linkname libc_sigaction libc_sigaction
//go:linkname libc_sigaltstack libc_sigaltstack
//go:linkname libc_sigprocmask libc_sigprocmask
//go:linkname libc_sysconf libc_sysconf
//go:linkname libc_usleep libc_usleep
//go:linkname libc_write libc_write
var (
libc____errno,
libc_clock_gettime,
libc_close,
libc_exit,
libc_fstat,
libc_getcontext,
libc_getrlimit,
libc_madvise,
libc_malloc,
libc_mmap,
libc_munmap,
libc_open,
libc_pthread_attr_destroy,
libc_pthread_attr_getstack,
libc_pthread_attr_init,
libc_pthread_attr_setdetachstate,
libc_pthread_attr_setstack,
libc_pthread_create,
libc_raise,
libc_read,
libc_sched_yield,
libc_select,
libc_sem_init,
libc_sem_post,
libc_sem_reltimedwait_np,
libc_sem_wait,
libc_setitimer,
libc_sigaction,
libc_sigaltstack,
libc_sigprocmask,
libc_sysconf,
libc_usleep,
libc_write libcFunc
)
var sigset_none = sigset{}
var sigset_all = sigset{[4]uint32{^uint32(0), ^uint32(0), ^uint32(0), ^uint32(0)}}
func getncpu() int32 {
n := int32(sysconf(__SC_NPROCESSORS_ONLN))
if n < 1 {
return 1
}
return n
}
func osinit() {
ncpu = getncpu()
}
func tstart_sysvicall()
func newosproc(mp *m, _ unsafe.Pointer) {
var (
attr pthreadattr
oset sigset
tid pthread
ret int32
size uint64
)
if pthread_attr_init(&attr) != 0 {
gothrow("pthread_attr_init")
}
if pthread_attr_setstack(&attr, 0, 0x200000) != 0 {
gothrow("pthread_attr_setstack")
}
if pthread_attr_getstack(&attr, unsafe.Pointer(&mp.g0.stack.hi), &size) != 0 {
gothrow("pthread_attr_getstack")
}
mp.g0.stack.lo = mp.g0.stack.hi - uintptr(size)
if pthread_attr_setdetachstate(&attr, _PTHREAD_CREATE_DETACHED) != 0 {
gothrow("pthread_attr_setdetachstate")
}
// Disable signals during create, so that the new thread starts
// with signals disabled. It will enable them in minit.
sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
ret = pthread_create(&tid, &attr, funcPC(tstart_sysvicall), unsafe.Pointer(mp))
sigprocmask(_SIG_SETMASK, &oset, nil)
if ret != 0 {
print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", ret, ")\n")
gothrow("newosproc")
}
}
var urandom_data [_HashRandomBytes]byte
var urandom_dev = []byte("/dev/random\x00")
//go:nosplit
func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) {
fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
if read(fd, unsafe.Pointer(&urandom_data), _HashRandomBytes) == _HashRandomBytes {
*rnd = unsafe.Pointer(&urandom_data[0])
*rnd_len = _HashRandomBytes
} else {
*rnd = nil
*rnd_len = 0
}
close(fd)
}
func goenvs() {
goenvs_unix()
}
// Called to initialize a new m (including the bootstrap m).
// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
func mpreinit(mp *m) {
mp.gsignal = malg(32 * 1024)
mp.gsignal.m = mp
}
func miniterrno()
// Called to initialize a new m (including the bootstrap m).
// Called on the new thread, can not allocate memory.
func minit() {
_g_ := getg()
asmcgocall(unsafe.Pointer(funcPC(miniterrno)), unsafe.Pointer(libc____errno))
// Initialize signal handling
signalstack((*byte)(unsafe.Pointer(_g_.m.gsignal.stack.lo)), 32*1024)
sigprocmask(_SIG_SETMASK, &sigset_none, nil)
}
// Called from dropm to undo the effect of an minit.
func unminit() {
signalstack(nil, 0)
}
func memlimit() uintptr {
/*
TODO: Convert to Go when something actually uses the result.
Rlimit rl;
extern byte runtime·text[], runtime·end[];
uintptr used;
if(runtime·getrlimit(RLIMIT_AS, &rl) != 0)
return 0;
if(rl.rlim_cur >= 0x7fffffff)
return 0;
// Estimate our VM footprint excluding the heap.
// Not an exact science: use size of binary plus
// some room for thread stacks.
used = runtime·end - runtime·text + (64<<20);
if(used >= rl.rlim_cur)
return 0;
// If there's not at least 16 MB left, we're probably
// not going to be able to do much. Treat as no limit.
rl.rlim_cur -= used;
if(rl.rlim_cur < (16<<20))
return 0;
return rl.rlim_cur - used;
*/
return 0
}
func sigtramp()
func setsig(i int32, fn uintptr, restart bool) {
var sa sigactiont
sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK
sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK
if restart {
sa.sa_flags |= _SA_RESTART
}
sa.sa_mask = sigset_all
if fn == funcPC(sighandler) {
fn = funcPC(sigtramp)
}
*((*uintptr)(unsafe.Pointer(&sa._funcptr))) = fn
sigaction(i, &sa, nil)
}
func getsig(i int32) uintptr {
var sa sigactiont
sigaction(i, nil, &sa)
if *((*uintptr)(unsafe.Pointer(&sa._funcptr))) == funcPC(sigtramp) {
return funcPC(sighandler)
}
return *((*uintptr)(unsafe.Pointer(&sa._funcptr)))
}
func signalstack(p *byte, n int32) {
var st sigaltstackt
st.ss_sp = (*byte)(unsafe.Pointer(p))
st.ss_size = uint64(n)
st.ss_flags = 0
if p == nil {
st.ss_flags = _SS_DISABLE
}
sigaltstack(&st, nil)
}
func unblocksignals() {
sigprocmask(_SIG_SETMASK, &sigset_none, nil)
}
//go:nosplit
func semacreate() uintptr {
var sem *semt
_g_ := getg()
// Call libc's malloc rather than malloc. This will
// allocate space on the C heap. We can't call malloc
// here because it could cause a deadlock.
_g_.m.libcall.fn = uintptr(libc_malloc)
_g_.m.libcall.n = 1
memclr(unsafe.Pointer(&_g_.m.scratch), uintptr(len(_g_.m.scratch.v)))
_g_.m.scratch.v[0] = unsafe.Sizeof(*sem)
_g_.m.libcall.args = uintptr(unsafe.Pointer(&_g_.m.scratch))
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&_g_.m.libcall))
sem = (*semt)(unsafe.Pointer(_g_.m.libcall.r1))
if sem_init(sem, 0, 0) != 0 {
gothrow("sem_init")
}
return uintptr(unsafe.Pointer(sem))
}
//go:nosplit
func semasleep(ns int64) int32 {
_m_ := getg().m
if ns >= 0 {
_m_.ts.tv_sec = ns / 1000000000
_m_.ts.tv_nsec = ns % 1000000000
_m_.libcall.fn = uintptr(unsafe.Pointer(libc_sem_reltimedwait_np))
_m_.libcall.n = 2
memclr(unsafe.Pointer(&_m_.scratch), uintptr(len(_m_.scratch.v)))
_m_.scratch.v[0] = _m_.waitsema
_m_.scratch.v[1] = uintptr(unsafe.Pointer(&_m_.ts))
_m_.libcall.args = uintptr(unsafe.Pointer(&_m_.scratch))
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&_m_.libcall))
if *_m_.perrno != 0 {
if *_m_.perrno == _ETIMEDOUT || *_m_.perrno == _EAGAIN || *_m_.perrno == _EINTR {
return -1
}
gothrow("sem_reltimedwait_np")
}
return 0
}
for {
_m_.libcall.fn = uintptr(unsafe.Pointer(libc_sem_wait))
_m_.libcall.n = 1
memclr(unsafe.Pointer(&_m_.scratch), uintptr(len(_m_.scratch.v)))
_m_.scratch.v[0] = _m_.waitsema
_m_.libcall.args = uintptr(unsafe.Pointer(&_m_.scratch))
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&_m_.libcall))
if _m_.libcall.r1 == 0 {
break
}
if *_m_.perrno == _EINTR {
continue
}
gothrow("sem_wait")
}
return 0
}
//go:nosplit
func semawakeup(mp *m) {
if sem_post((*semt)(unsafe.Pointer(mp.waitsema))) != 0 {
gothrow("sem_post")
}
}
//go:nosplit
func close(fd int32) int32 {
return int32(sysvicall1(libc_close, uintptr(fd)))
}
//go:nosplit
func exit(r int32) {
sysvicall1(libc_exit, uintptr(r))
}
//go:nosplit
func getcontext(context *ucontext) /* int32 */ {
sysvicall1(libc_getcontext, uintptr(unsafe.Pointer(context)))
}
//go:nosplit
func madvise(addr unsafe.Pointer, n uintptr, flags int32) {
sysvicall3(libc_madvise, uintptr(addr), uintptr(n), uintptr(flags))
}
//go:nosplit
func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer {
return unsafe.Pointer(sysvicall6(libc_mmap, uintptr(addr), uintptr(n), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(off)))
}
//go:nosplit
func munmap(addr unsafe.Pointer, n uintptr) {
sysvicall2(libc_munmap, uintptr(addr), uintptr(n))
}
func nanotime1()
//go:nosplit
func nanotime() int64 {
return int64(sysvicall0(libcFunc(funcPC(nanotime1))))
}
//go:nosplit
func open(path *byte, mode, perm int32) int32 {
return int32(sysvicall3(libc_open, uintptr(unsafe.Pointer(path)), uintptr(mode), uintptr(perm)))
}
func pthread_attr_destroy(attr *pthreadattr) int32 {
return int32(sysvicall1(libc_pthread_attr_destroy, uintptr(unsafe.Pointer(attr))))
}
func pthread_attr_getstack(attr *pthreadattr, addr unsafe.Pointer, size *uint64) int32 {
return int32(sysvicall3(libc_pthread_attr_getstack, uintptr(unsafe.Pointer(attr)), uintptr(addr), uintptr(unsafe.Pointer(size))))
}
func pthread_attr_init(attr *pthreadattr) int32 {
return int32(sysvicall1(libc_pthread_attr_init, uintptr(unsafe.Pointer(attr))))
}
func pthread_attr_setdetachstate(attr *pthreadattr, state int32) int32 {
return int32(sysvicall2(libc_pthread_attr_setdetachstate, uintptr(unsafe.Pointer(attr)), uintptr(state)))
}
func pthread_attr_setstack(attr *pthreadattr, addr uintptr, size uint64) int32 {
return int32(sysvicall3(libc_pthread_attr_setstack, uintptr(unsafe.Pointer(attr)), uintptr(addr), uintptr(size)))
}
func pthread_create(thread *pthread, attr *pthreadattr, fn uintptr, arg unsafe.Pointer) int32 {
return int32(sysvicall4(libc_pthread_create, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(fn), uintptr(arg)))
}
func raise(sig int32) /* int32 */ {
sysvicall1(libc_raise, uintptr(sig))
}
//go:nosplit
func read(fd int32, buf unsafe.Pointer, nbyte int32) int32 {
return int32(sysvicall3(libc_read, uintptr(fd), uintptr(buf), uintptr(nbyte)))
}
//go:nosplit
func sem_init(sem *semt, pshared int32, value uint32) int32 {
return int32(sysvicall3(libc_sem_init, uintptr(unsafe.Pointer(sem)), uintptr(pshared), uintptr(value)))
}
//go:nosplit
func sem_post(sem *semt) int32 {
return int32(sysvicall1(libc_sem_post, uintptr(unsafe.Pointer(sem))))
}
//go:nosplit
func sem_reltimedwait_np(sem *semt, timeout *timespec) int32 {
return int32(sysvicall2(libc_sem_reltimedwait_np, uintptr(unsafe.Pointer(sem)), uintptr(unsafe.Pointer(timeout))))
}
//go:nosplit
func sem_wait(sem *semt) int32 {
return int32(sysvicall1(libc_sem_wait, uintptr(unsafe.Pointer(sem))))
}
func setitimer(which int32, value *itimerval, ovalue *itimerval) /* int32 */ {
sysvicall3(libc_setitimer, uintptr(which), uintptr(unsafe.Pointer(value)), uintptr(unsafe.Pointer(ovalue)))
}
func sigaction(sig int32, act *sigactiont, oact *sigactiont) /* int32 */ {
sysvicall3(libc_sigaction, uintptr(sig), uintptr(unsafe.Pointer(act)), uintptr(unsafe.Pointer(oact)))
}
func sigaltstack(ss *sigaltstackt, oss *sigaltstackt) /* int32 */ {
sysvicall2(libc_sigaltstack, uintptr(unsafe.Pointer(ss)), uintptr(unsafe.Pointer(oss)))
}
func sigprocmask(how int32, set *sigset, oset *sigset) /* int32 */ {
sysvicall3(libc_sigprocmask, uintptr(how), uintptr(unsafe.Pointer(set)), uintptr(unsafe.Pointer(oset)))
}
func sysconf(name int32) int64 {
return int64(sysvicall1(libc_sysconf, uintptr(name)))
}
func usleep1(uint32)
//go:nosplit
func usleep(µs uint32) {
usleep1(µs)
}
//go:nosplit
func write(fd uintptr, buf unsafe.Pointer, nbyte int32) int32 {
return int32(sysvicall3(libc_write, uintptr(fd), uintptr(buf), uintptr(nbyte)))
}
func osyield1()
//go:nosplit
func osyield() {
_g_ := getg()
// 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_ != nil && _g_.m != nil {
sysvicall0(libc_sched_yield)
return
}
osyield1()
}
// Copyright 2011 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.
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
#include "signal_unix.h"
#include "stack.h"
#include "textflag.h"
#pragma dynexport runtime·end _end
#pragma dynexport runtime·etext _etext
#pragma dynexport runtime·edata _edata
#pragma dynimport libc·___errno ___errno "libc.so"
#pragma dynimport libc·clock_gettime clock_gettime "libc.so"
#pragma dynimport libc·close close "libc.so"
#pragma dynimport libc·exit exit "libc.so"
#pragma dynimport libc·fstat fstat "libc.so"
#pragma dynimport libc·getcontext getcontext "libc.so"
#pragma dynimport libc·getrlimit getrlimit "libc.so"
#pragma dynimport libc·malloc malloc "libc.so"
#pragma dynimport libc·mmap mmap "libc.so"
#pragma dynimport libc·munmap munmap "libc.so"
#pragma dynimport libc·open open "libc.so"
#pragma dynimport libc·pthread_attr_destroy pthread_attr_destroy "libc.so"
#pragma dynimport libc·pthread_attr_getstack pthread_attr_getstack "libc.so"
#pragma dynimport libc·pthread_attr_init pthread_attr_init "libc.so"
#pragma dynimport libc·pthread_attr_setdetachstate pthread_attr_setdetachstate "libc.so"
#pragma dynimport libc·pthread_attr_setstack pthread_attr_setstack "libc.so"
#pragma dynimport libc·pthread_create pthread_create "libc.so"
#pragma dynimport libc·raise raise "libc.so"
#pragma dynimport libc·read read "libc.so"
#pragma dynimport libc·select select "libc.so"
#pragma dynimport libc·sched_yield sched_yield "libc.so"
#pragma dynimport libc·sem_init sem_init "libc.so"
#pragma dynimport libc·sem_post sem_post "libc.so"
#pragma dynimport libc·sem_reltimedwait_np sem_reltimedwait_np "libc.so"
#pragma dynimport libc·sem_wait sem_wait "libc.so"
#pragma dynimport libc·setitimer setitimer "libc.so"
#pragma dynimport libc·sigaction sigaction "libc.so"
#pragma dynimport libc·sigaltstack sigaltstack "libc.so"
#pragma dynimport libc·sigprocmask sigprocmask "libc.so"
#pragma dynimport libc·sysconf sysconf "libc.so"
#pragma dynimport libc·usleep usleep "libc.so"
#pragma dynimport libc·write write "libc.so"
extern uintptr libc·___errno;
extern uintptr libc·clock_gettime;
extern uintptr libc·close;
extern uintptr libc·exit;
extern uintptr libc·fstat;
extern uintptr libc·getcontext;
extern uintptr libc·getrlimit;
extern uintptr libc·malloc;
extern uintptr libc·mmap;
extern uintptr libc·munmap;
extern uintptr libc·open;
extern uintptr libc·pthread_attr_destroy;
extern uintptr libc·pthread_attr_getstack;
extern uintptr libc·pthread_attr_init;
extern uintptr libc·pthread_attr_setdetachstate;
extern uintptr libc·pthread_attr_setstack;
extern uintptr libc·pthread_create;
extern uintptr libc·raise;
extern uintptr libc·read;
extern uintptr libc·sched_yield;
extern uintptr libc·select;
extern uintptr libc·sem_init;
extern uintptr libc·sem_post;
extern uintptr libc·sem_reltimedwait_np;
extern uintptr libc·sem_wait;
extern uintptr libc·setitimer;
extern uintptr libc·sigaction;
extern uintptr libc·sigaltstack;
extern uintptr libc·sigprocmask;
extern uintptr libc·sysconf;
extern uintptr libc·usleep;
extern uintptr libc·write;
void runtime·getcontext(Ucontext *context);
int32 runtime·pthread_attr_destroy(PthreadAttr* attr);
int32 runtime·pthread_attr_init(PthreadAttr* attr);
int32 runtime·pthread_attr_getstack(PthreadAttr* attr, void** addr, uint64* size);
int32 runtime·pthread_attr_setdetachstate(PthreadAttr* attr, int32 state);
int32 runtime·pthread_attr_setstack(PthreadAttr* attr, void* addr, uint64 size);
int32 runtime·pthread_create(Pthread* thread, PthreadAttr* attr, void(*fn)(void), void *arg);
uint32 runtime·tstart_sysvicall(M *newm);
int32 runtime·sem_init(SemT* sem, int32 pshared, uint32 value);
int32 runtime·sem_post(SemT* sem);
int32 runtime·sem_reltimedwait_np(SemT* sem, Timespec* timeout);
int32 runtime·sem_wait(SemT* sem);
int64 runtime·sysconf(int32 name);
extern SigTab runtime·sigtab[];
static Sigset sigset_none;
static Sigset sigset_all = { ~(uint32)0, ~(uint32)0, ~(uint32)0, ~(uint32)0, };
static int32
getncpu(void)
{
int32 n;
n = (int32)runtime·sysconf(_SC_NPROCESSORS_ONLN);
if(n < 1)
return 1;
return n;
}
void
runtime·osinit(void)
{
runtime·ncpu = getncpu();
}
void
runtime·newosproc(M *mp, void *stk)
{
PthreadAttr attr;
Sigset oset;
Pthread tid;
int32 ret;
uint64 size;
USED(stk);
if(runtime·pthread_attr_init(&attr) != 0)
runtime·throw("pthread_attr_init");
if(runtime·pthread_attr_setstack(&attr, 0, 0x200000) != 0)
runtime·throw("pthread_attr_setstack");
size = 0;
if(runtime·pthread_attr_getstack(&attr, (void**)&mp->g0->stack.hi, &size) != 0)
runtime·throw("pthread_attr_getstack");
mp->g0->stack.lo = mp->g0->stack.hi - size;
if(runtime·pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
runtime·throw("pthread_attr_setdetachstate");
// Disable signals during create, so that the new thread starts
// with signals disabled. It will enable them in minit.
runtime·sigprocmask(SIG_SETMASK, &sigset_all, &oset);
ret = runtime·pthread_create(&tid, &attr, (void (*)(void))runtime·tstart_sysvicall, mp);
runtime·sigprocmask(SIG_SETMASK, &oset, nil);
if(ret != 0) {
runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount(), ret);
runtime·throw("runtime.newosproc");
}
}
#pragma textflag NOSPLIT
void
runtime·get_random_data(byte **rnd, int32 *rnd_len)
{
#pragma dataflag NOPTR
static byte urandom_data[HashRandomBytes];
int32 fd;
fd = runtime·open("/dev/urandom", 0 /* O_RDONLY */, 0);
if(runtime·read(fd, urandom_data, HashRandomBytes) == HashRandomBytes) {
*rnd = urandom_data;
*rnd_len = HashRandomBytes;
} else {
*rnd = nil;
*rnd_len = 0;
}
runtime·close(fd);
}
void
runtime·goenvs(void)
{
runtime·goenvs_unix();
}
// Called to initialize a new m (including the bootstrap m).
// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
void
runtime·mpreinit(M *mp)
{
mp->gsignal = runtime·malg(32*1024);
mp->gsignal->m = mp;
}
// Called to initialize a new m (including the bootstrap m).
// Called on the new thread, can not allocate memory.
void
runtime·minit(void)
{
runtime·asmcgocall(runtime·miniterrno, (void *)libc·___errno);
// Initialize signal handling
runtime·signalstack((byte*)g->m->gsignal->stack.lo, 32*1024);
runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil);
}
// Called from dropm to undo the effect of an minit.
void
runtime·unminit(void)
{
runtime·signalstack(nil, 0);
}
uintptr
runtime·memlimit(void)
{
Rlimit rl;
extern byte runtime·text[], runtime·end[];
uintptr used;
if(runtime·getrlimit(RLIMIT_AS, &rl) != 0)
return 0;
if(rl.rlim_cur >= 0x7fffffff)
return 0;
// Estimate our VM footprint excluding the heap.
// Not an exact science: use size of binary plus
// some room for thread stacks.
used = runtime·end - runtime·text + (64<<20);
if(used >= rl.rlim_cur)
return 0;
// If there's not at least 16 MB left, we're probably
// not going to be able to do much. Treat as no limit.
rl.rlim_cur -= used;
if(rl.rlim_cur < (16<<20))
return 0;
return rl.rlim_cur - used;
}
void
runtime·setprof(bool on)
{
USED(on);
}
extern void runtime·sigtramp(void);
void
runtime·setsig(int32 i, GoSighandler *fn, bool restart)
{
SigactionT sa;
runtime·memclr((byte*)&sa, sizeof sa);
sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
if(restart)
sa.sa_flags |= SA_RESTART;
sa.sa_mask.__sigbits[0] = ~(uint32)0;
sa.sa_mask.__sigbits[1] = ~(uint32)0;
sa.sa_mask.__sigbits[2] = ~(uint32)0;
sa.sa_mask.__sigbits[3] = ~(uint32)0;
if(fn == runtime·sighandler)
fn = (void*)runtime·sigtramp;
*((void**)&sa._funcptr[0]) = (void*)fn;
runtime·sigaction(i, &sa, nil);
}
GoSighandler*
runtime·getsig(int32 i)
{
SigactionT sa;
runtime·memclr((byte*)&sa, sizeof sa);
runtime·sigaction(i, nil, &sa);
if(*((void**)&sa._funcptr[0]) == runtime·sigtramp)
return runtime·sighandler;
return *((void**)&sa._funcptr[0]);
}
void
runtime·signalstack(byte *p, int32 n)
{
StackT st;
st.ss_sp = (void*)p;
st.ss_size = n;
st.ss_flags = 0;
if(p == nil)
st.ss_flags = SS_DISABLE;
runtime·sigaltstack(&st, nil);
}
void
runtime·unblocksignals(void)
{
runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil);
}
#pragma textflag NOSPLIT
uintptr
runtime·semacreate(void)
{
SemT* sem;
// Call libc's malloc rather than runtime·malloc. This will
// allocate space on the C heap. We can't call runtime·malloc
// here because it could cause a deadlock.
g->m->libcall.fn = (uintptr)(void*)libc·malloc;
g->m->libcall.n = 1;
runtime·memclr((byte*)&g->m->scratch, sizeof(g->m->scratch));
g->m->scratch.v[0] = (uintptr)sizeof(*sem);
g->m->libcall.args = (uintptr)(uintptr*)&g->m->scratch;
runtime·asmcgocall(runtime·asmsysvicall6, &g->m->libcall);
sem = (void*)g->m->libcall.r1;
if(runtime·sem_init(sem, 0, 0) != 0)
runtime·throw("sem_init");
return (uintptr)sem;
}
#pragma textflag NOSPLIT
int32
runtime·semasleep(int64 ns)
{
M *m;
m = g->m;
if(ns >= 0) {
m->ts.tv_sec = ns / 1000000000LL;
m->ts.tv_nsec = ns % 1000000000LL;
m->libcall.fn = (uintptr)(void*)libc·sem_reltimedwait_np;
m->libcall.n = 2;
runtime·memclr((byte*)&m->scratch, sizeof(m->scratch));
m->scratch.v[0] = m->waitsema;
m->scratch.v[1] = (uintptr)&m->ts;
m->libcall.args = (uintptr)(uintptr*)&m->scratch;
runtime·asmcgocall(runtime·asmsysvicall6, &m->libcall);
if(*m->perrno != 0) {
if(*m->perrno == ETIMEDOUT || *m->perrno == EAGAIN || *m->perrno == EINTR)
return -1;
runtime·throw("sem_reltimedwait_np");
}
return 0;
}
for(;;) {
m->libcall.fn = (uintptr)(void*)libc·sem_wait;
m->libcall.n = 1;
runtime·memclr((byte*)&m->scratch, sizeof(m->scratch));
m->scratch.v[0] = m->waitsema;
m->libcall.args = (uintptr)(uintptr*)&m->scratch;
runtime·asmcgocall(runtime·asmsysvicall6, &m->libcall);
if(m->libcall.r1 == 0)
break;
if(*m->perrno == EINTR)
continue;
runtime·throw("sem_wait");
}
return 0;
}
#pragma textflag NOSPLIT
void
runtime·semawakeup(M *mp)
{
SemT* sem = (SemT*)mp->waitsema;
if(runtime·sem_post(sem) != 0)
runtime·throw("sem_post");
}
#pragma textflag NOSPLIT
int32
runtime·close(int32 fd)
{
return runtime·sysvicall1(libc·close, (uintptr)fd);
}
#pragma textflag NOSPLIT
void
runtime·exit(int32 r)
{
runtime·sysvicall1(libc·exit, (uintptr)r);
}
#pragma textflag NOSPLIT
/* int32 */ void
runtime·getcontext(Ucontext* context)
{
runtime·sysvicall1(libc·getcontext, (uintptr)context);
}
#pragma textflag NOSPLIT
int32
runtime·getrlimit(int32 res, Rlimit* rlp)
{
return runtime·sysvicall2(libc·getrlimit, (uintptr)res, (uintptr)rlp);
}
#pragma textflag NOSPLIT
uint8*
runtime·mmap(byte* addr, uintptr len, int32 prot, int32 flags, int32 fildes, uint32 off)
{
return (uint8*)runtime·sysvicall6(libc·mmap, (uintptr)addr, (uintptr)len, (uintptr)prot, (uintptr)flags, (uintptr)fildes, (uintptr)off);
}
#pragma textflag NOSPLIT
void
runtime·munmap(byte* addr, uintptr len)
{
runtime·sysvicall2(libc·munmap, (uintptr)addr, (uintptr)len);
}
extern int64 runtime·nanotime1(void);
#pragma textflag NOSPLIT
int64
runtime·nanotime(void)
{
return runtime·sysvicall0((uintptr)runtime·nanotime1);
}
#pragma textflag NOSPLIT
int32
runtime·open(int8* path, int32 oflag, int32 mode)
{
return runtime·sysvicall3(libc·open, (uintptr)path, (uintptr)oflag, (uintptr)mode);
}
int32
runtime·pthread_attr_destroy(PthreadAttr* attr)
{
return runtime·sysvicall1(libc·pthread_attr_destroy, (uintptr)attr);
}
int32
runtime·pthread_attr_getstack(PthreadAttr* attr, void** addr, uint64* size)
{
return runtime·sysvicall3(libc·pthread_attr_getstack, (uintptr)attr, (uintptr)addr, (uintptr)size);
}
int32
runtime·pthread_attr_init(PthreadAttr* attr)
{
return runtime·sysvicall1(libc·pthread_attr_init, (uintptr)attr);
}
int32
runtime·pthread_attr_setdetachstate(PthreadAttr* attr, int32 state)
{
return runtime·sysvicall2(libc·pthread_attr_setdetachstate, (uintptr)attr, (uintptr)state);
}
int32
runtime·pthread_attr_setstack(PthreadAttr* attr, void* addr, uint64 size)
{
return runtime·sysvicall3(libc·pthread_attr_setstack, (uintptr)attr, (uintptr)addr, (uintptr)size);
}
int32
runtime·pthread_create(Pthread* thread, PthreadAttr* attr, void(*fn)(void), void *arg)
{
return runtime·sysvicall4(libc·pthread_create, (uintptr)thread, (uintptr)attr, (uintptr)fn, (uintptr)arg);
}
/* int32 */ void
runtime·raise(int32 sig)
{
runtime·sysvicall1(libc·raise, (uintptr)sig);
}
#pragma textflag NOSPLIT
int32
runtime·read(int32 fd, void* buf, int32 nbyte)
{
return runtime·sysvicall3(libc·read, (uintptr)fd, (uintptr)buf, (uintptr)nbyte);
}
#pragma textflag NOSPLIT
int32
runtime·sem_init(SemT* sem, int32 pshared, uint32 value)
{
return runtime·sysvicall3(libc·sem_init, (uintptr)sem, (uintptr)pshared, (uintptr)value);
}
#pragma textflag NOSPLIT
int32
runtime·sem_post(SemT* sem)
{
return runtime·sysvicall1(libc·sem_post, (uintptr)sem);
}
#pragma textflag NOSPLIT
int32
runtime·sem_reltimedwait_np(SemT* sem, Timespec* timeout)
{
return runtime·sysvicall2(libc·sem_reltimedwait_np, (uintptr)sem, (uintptr)timeout);
}
#pragma textflag NOSPLIT
int32
runtime·sem_wait(SemT* sem)
{
return runtime·sysvicall1(libc·sem_wait, (uintptr)sem);
}
/* int32 */ void
runtime·setitimer(int32 which, Itimerval* value, Itimerval* ovalue)
{
runtime·sysvicall3(libc·setitimer, (uintptr)which, (uintptr)value, (uintptr)ovalue);
}
/* int32 */ void
runtime·sigaction(int32 sig, struct SigactionT* act, struct SigactionT* oact)
{
runtime·sysvicall3(libc·sigaction, (uintptr)sig, (uintptr)act, (uintptr)oact);
}
/* int32 */ void
runtime·sigaltstack(SigaltstackT* ss, SigaltstackT* oss)
{
runtime·sysvicall2(libc·sigaltstack, (uintptr)ss, (uintptr)oss);
}
/* int32 */ void
runtime·sigprocmask(int32 how, Sigset* set, Sigset* oset)
{
runtime·sysvicall3(libc·sigprocmask, (uintptr)how, (uintptr)set, (uintptr)oset);
}
int64
runtime·sysconf(int32 name)
{
return runtime·sysvicall1(libc·sysconf, (uintptr)name);
}
extern void runtime·usleep1(uint32);
#pragma textflag NOSPLIT
void
runtime·usleep(uint32 µs)
{
runtime·usleep1(µs);
}
#pragma textflag NOSPLIT
int32
runtime·write(uintptr fd, void* buf, int32 nbyte)
{
return runtime·sysvicall3(libc·write, (uintptr)fd, (uintptr)buf, (uintptr)nbyte);
}
extern void runtime·osyield1(void);
#pragma textflag NOSPLIT
void
runtime·osyield(void)
{
// 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·sysvicall0(libc·sched_yield);
return;
}
runtime·osyield1();
}
#pragma textflag NOSPLIT
int8*
runtime·signame(int32 sig)
{
return runtime·sigtab[sig].name;
}
...@@ -6,53 +6,35 @@ package runtime ...@@ -6,53 +6,35 @@ package runtime
import "unsafe" import "unsafe"
func setitimer(mode int32, new, old unsafe.Pointer) type libcFunc uintptr
func sigaction(sig int32, new, old unsafe.Pointer)
func sigaltstack(new, old unsafe.Pointer)
func sigprocmask(mode int32, new, old unsafe.Pointer)
func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
func getrlimit(kind int32, limit unsafe.Pointer)
func miniterrno(fn unsafe.Pointer)
func raise(sig int32)
func getcontext(ctxt unsafe.Pointer)
func tstart_sysvicall(mm unsafe.Pointer) uint32
func nanotime1() int64
func usleep1(usec uint32)
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
var asmsysvicall6 libcFunc var asmsysvicall6 libcFunc
//go:nosplit //go:nosplit
func sysvicall0(fn *libcFunc) uintptr { func sysvicall0(fn libcFunc) uintptr {
libcall := &getg().m.libcall libcall := &getg().m.libcall
libcall.fn = uintptr(unsafe.Pointer(fn)) libcall.fn = uintptr(fn)
libcall.n = 0 libcall.n = 0
// TODO(rsc): Why is noescape necessary here and below? libcall.args = uintptr(fn) // it's unused but must be non-nil, otherwise crashes
libcall.args = uintptr(noescape(unsafe.Pointer(&fn))) // it's unused but must be non-nil, otherwise crashes
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall)) asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
return libcall.r1 return libcall.r1
} }
//go:nosplit //go:nosplit
func sysvicall1(fn *libcFunc, a1 uintptr) uintptr { func sysvicall1(fn libcFunc, a1 uintptr) uintptr {
libcall := &getg().m.libcall libcall := &getg().m.libcall
libcall.fn = uintptr(unsafe.Pointer(fn)) libcall.fn = uintptr(fn)
libcall.n = 1 libcall.n = 1
// TODO(rsc): Why is noescape necessary here and below?
libcall.args = uintptr(noescape(unsafe.Pointer(&a1))) libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall)) asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
return libcall.r1 return libcall.r1
} }
//go:nosplit //go:nosplit
func sysvicall2(fn *libcFunc, a1, a2 uintptr) uintptr { func sysvicall2(fn libcFunc, a1, a2 uintptr) uintptr {
libcall := &getg().m.libcall libcall := &getg().m.libcall
libcall.fn = uintptr(unsafe.Pointer(fn)) libcall.fn = uintptr(fn)
libcall.n = 2 libcall.n = 2
libcall.args = uintptr(noescape(unsafe.Pointer(&a1))) libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall)) asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
...@@ -60,9 +42,9 @@ func sysvicall2(fn *libcFunc, a1, a2 uintptr) uintptr { ...@@ -60,9 +42,9 @@ func sysvicall2(fn *libcFunc, a1, a2 uintptr) uintptr {
} }
//go:nosplit //go:nosplit
func sysvicall3(fn *libcFunc, a1, a2, a3 uintptr) uintptr { func sysvicall3(fn libcFunc, a1, a2, a3 uintptr) uintptr {
libcall := &getg().m.libcall libcall := &getg().m.libcall
libcall.fn = uintptr(unsafe.Pointer(fn)) libcall.fn = uintptr(fn)
libcall.n = 3 libcall.n = 3
libcall.args = uintptr(noescape(unsafe.Pointer(&a1))) libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall)) asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
...@@ -70,9 +52,9 @@ func sysvicall3(fn *libcFunc, a1, a2, a3 uintptr) uintptr { ...@@ -70,9 +52,9 @@ func sysvicall3(fn *libcFunc, a1, a2, a3 uintptr) uintptr {
} }
//go:nosplit //go:nosplit
func sysvicall4(fn *libcFunc, a1, a2, a3, a4 uintptr) uintptr { func sysvicall4(fn libcFunc, a1, a2, a3, a4 uintptr) uintptr {
libcall := &getg().m.libcall libcall := &getg().m.libcall
libcall.fn = uintptr(unsafe.Pointer(fn)) libcall.fn = uintptr(fn)
libcall.n = 4 libcall.n = 4
libcall.args = uintptr(noescape(unsafe.Pointer(&a1))) libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall)) asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
...@@ -80,9 +62,9 @@ func sysvicall4(fn *libcFunc, a1, a2, a3, a4 uintptr) uintptr { ...@@ -80,9 +62,9 @@ func sysvicall4(fn *libcFunc, a1, a2, a3, a4 uintptr) uintptr {
} }
//go:nosplit //go:nosplit
func sysvicall5(fn *libcFunc, a1, a2, a3, a4, a5 uintptr) uintptr { func sysvicall5(fn libcFunc, a1, a2, a3, a4, a5 uintptr) uintptr {
libcall := &getg().m.libcall libcall := &getg().m.libcall
libcall.fn = uintptr(unsafe.Pointer(fn)) libcall.fn = uintptr(fn)
libcall.n = 5 libcall.n = 5
libcall.args = uintptr(noescape(unsafe.Pointer(&a1))) libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall)) asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
...@@ -90,9 +72,9 @@ func sysvicall5(fn *libcFunc, a1, a2, a3, a4, a5 uintptr) uintptr { ...@@ -90,9 +72,9 @@ func sysvicall5(fn *libcFunc, a1, a2, a3, a4, a5 uintptr) uintptr {
} }
//go:nosplit //go:nosplit
func sysvicall6(fn *libcFunc, a1, a2, a3, a4, a5, a6 uintptr) uintptr { func sysvicall6(fn libcFunc, a1, a2, a3, a4, a5, a6 uintptr) uintptr {
libcall := &getg().m.libcall libcall := &getg().m.libcall
libcall.fn = uintptr(unsafe.Pointer(fn)) libcall.fn = uintptr(fn)
libcall.n = 6 libcall.n = 6
libcall.args = uintptr(noescape(unsafe.Pointer(&a1))) libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall)) asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
......
// Copyright 2014 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.
typedef uintptr kevent_udata;
struct sigaction;
void runtime·sigpanic(void);
void runtime·setitimer(int32, Itimerval*, Itimerval*);
void runtime·sigaction(int32, struct SigactionT*, struct SigactionT*);
void runtime·sigaltstack(SigaltstackT*, SigaltstackT*);
void runtime·sigprocmask(int32, Sigset*, Sigset*);
void runtime·unblocksignals(void);
int32 runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
void runtime·raisesigpipe(void);
void runtime·setsig(int32, void(*)(int32, Siginfo*, void*, G*), bool);
void runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp);
void runtime·sigpanic(void);
enum {
SS_DISABLE = 2,
SIG_BLOCK = 1,
SIG_UNBLOCK = 2,
SIG_SETMASK = 3,
NSIG = 73, /* number of signals in runtime·SigTab array */
SI_USER = 0,
_UC_SIGMASK = 0x01,
_UC_CPU = 0x04,
RLIMIT_AS = 10,
};
typedef struct Rlimit Rlimit;
struct Rlimit {
int64 rlim_cur;
int64 rlim_max;
};
int32 runtime·getrlimit(int32, Rlimit*);
// Call an external library function described by {fn, a0, ..., an}, with
// SysV conventions, switching to os stack during the call, if necessary.
uintptr runtime·sysvicall0(uintptr fn);
uintptr runtime·sysvicall1(uintptr fn, uintptr a1);
uintptr runtime·sysvicall2(uintptr fn, uintptr a1, uintptr a2);
uintptr runtime·sysvicall3(uintptr fn, uintptr a1, uintptr a2, uintptr a3);
uintptr runtime·sysvicall4(uintptr fn, uintptr a1, uintptr a2, uintptr a3, uintptr a4);
uintptr runtime·sysvicall5(uintptr fn, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5);
uintptr runtime·sysvicall6(uintptr fn, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5, uintptr a6);
void runtime·asmsysvicall6(void *c);
void runtime·miniterrno(void *fn);
// Copyright 2014 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.
package runtime
type sigTabT struct {
flags int32
name string
}
var sigtable = [...]sigTabT{
/* 0 */ {0, "SIGNONE: no trap"},
/* 1 */ {_SigNotify + _SigKill, "SIGHUP: hangup"},
/* 2 */ {_SigNotify + _SigKill, "SIGINT: interrupt (rubout)"},
/* 3 */ {_SigNotify + _SigThrow, "SIGQUIT: quit (ASCII FS)"},
/* 4 */ {_SigThrow, "SIGILL: illegal instruction (not reset when caught)"},
/* 5 */ {_SigThrow, "SIGTRAP: trace trap (not reset when caught)"},
/* 6 */ {_SigNotify + _SigThrow, "SIGABRT: used by abort, replace SIGIOT in the future"},
/* 7 */ {_SigThrow, "SIGEMT: EMT instruction"},
/* 8 */ {_SigPanic, "SIGFPE: floating point exception"},
/* 9 */ {0, "SIGKILL: kill (cannot be caught or ignored)"},
/* 10 */ {_SigPanic, "SIGBUS: bus error"},
/* 11 */ {_SigPanic, "SIGSEGV: segmentation violation"},
/* 12 */ {_SigThrow, "SIGSYS: bad argument to system call"},
/* 13 */ {_SigNotify, "SIGPIPE: write on a pipe with no one to read it"},
/* 14 */ {_SigNotify, "SIGALRM: alarm clock"},
/* 15 */ {_SigNotify + _SigKill, "SIGTERM: software termination signal from kill"},
/* 16 */ {_SigNotify, "SIGUSR1: user defined signal 1"},
/* 17 */ {_SigNotify, "SIGUSR2: user defined signal 2"},
/* 18 */ {_SigNotify, "SIGCHLD: child status change alias (POSIX)"},
/* 19 */ {_SigNotify, "SIGPWR: power-fail restart"},
/* 20 */ {_SigNotify, "SIGWINCH: window size change"},
/* 21 */ {_SigNotify, "SIGURG: urgent socket condition"},
/* 22 */ {_SigNotify, "SIGPOLL: pollable event occured"},
/* 23 */ {_SigNotify + _SigDefault, "SIGSTOP: stop (cannot be caught or ignored)"},
/* 24 */ {0, "SIGTSTP: user stop requested from tty"},
/* 25 */ {0, "SIGCONT: stopped process has been continued"},
/* 26 */ {_SigNotify + _SigDefault, "SIGTTIN: background tty read attempted"},
/* 27 */ {_SigNotify + _SigDefault, "SIGTTOU: background tty write attempted"},
/* 28 */ {_SigNotify, "SIGVTALRM: virtual timer expired"},
/* 29 */ {_SigNotify, "SIGPROF: profiling timer expired"},
/* 30 */ {_SigNotify, "SIGXCPU: exceeded cpu limit"},
/* 31 */ {_SigNotify, "SIGXFSZ: exceeded file size limit"},
/* 32 */ {_SigNotify, "SIGWAITING: reserved signal no longer used by"},
/* 33 */ {_SigNotify, "SIGLWP: reserved signal no longer used by"},
/* 34 */ {_SigNotify, "SIGFREEZE: special signal used by CPR"},
/* 35 */ {_SigNotify, "SIGTHAW: special signal used by CPR"},
/* 36 */ {0, "SIGCANCEL: reserved signal for thread cancellation"},
/* 37 */ {_SigNotify, "SIGLOST: resource lost (eg, record-lock lost)"},
/* 38 */ {_SigNotify, "SIGXRES: resource control exceeded"},
/* 39 */ {_SigNotify, "SIGJVM1: reserved signal for Java Virtual Machine"},
/* 40 */ {_SigNotify, "SIGJVM2: reserved signal for Java Virtual Machine"},
/* TODO(aram): what should be do about these signals? _SigDefault or _SigNotify? is this set static? */
/* 41 */ {_SigNotify, "real time signal"},
/* 42 */ {_SigNotify, "real time signal"},
/* 43 */ {_SigNotify, "real time signal"},
/* 44 */ {_SigNotify, "real time signal"},
/* 45 */ {_SigNotify, "real time signal"},
/* 46 */ {_SigNotify, "real time signal"},
/* 47 */ {_SigNotify, "real time signal"},
/* 48 */ {_SigNotify, "real time signal"},
/* 49 */ {_SigNotify, "real time signal"},
/* 50 */ {_SigNotify, "real time signal"},
/* 51 */ {_SigNotify, "real time signal"},
/* 52 */ {_SigNotify, "real time signal"},
/* 53 */ {_SigNotify, "real time signal"},
/* 54 */ {_SigNotify, "real time signal"},
/* 55 */ {_SigNotify, "real time signal"},
/* 56 */ {_SigNotify, "real time signal"},
/* 57 */ {_SigNotify, "real time signal"},
/* 58 */ {_SigNotify, "real time signal"},
/* 59 */ {_SigNotify, "real time signal"},
/* 60 */ {_SigNotify, "real time signal"},
/* 61 */ {_SigNotify, "real time signal"},
/* 62 */ {_SigNotify, "real time signal"},
/* 63 */ {_SigNotify, "real time signal"},
/* 64 */ {_SigNotify, "real time signal"},
/* 65 */ {_SigNotify, "real time signal"},
/* 66 */ {_SigNotify, "real time signal"},
/* 67 */ {_SigNotify, "real time signal"},
/* 68 */ {_SigNotify, "real time signal"},
/* 69 */ {_SigNotify, "real time signal"},
/* 70 */ {_SigNotify, "real time signal"},
/* 71 */ {_SigNotify, "real time signal"},
/* 72 */ {_SigNotify, "real time signal"},
}
// Copyright 2014 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.
package runtime
import "unsafe"
type sigctxt struct {
info *siginfo
ctxt unsafe.Pointer
}
func (c *sigctxt) regs() *mcontext {
return (*mcontext)(unsafe.Pointer(&(*ucontext)(c.ctxt).uc_mcontext))
}
func (c *sigctxt) rax() uint64 { return uint64(c.regs().gregs[_REG_RAX]) }
func (c *sigctxt) rbx() uint64 { return uint64(c.regs().gregs[_REG_RBX]) }
func (c *sigctxt) rcx() uint64 { return uint64(c.regs().gregs[_REG_RCX]) }
func (c *sigctxt) rdx() uint64 { return uint64(c.regs().gregs[_REG_RDX]) }
func (c *sigctxt) rdi() uint64 { return uint64(c.regs().gregs[_REG_RDI]) }
func (c *sigctxt) rsi() uint64 { return uint64(c.regs().gregs[_REG_RSI]) }
func (c *sigctxt) rbp() uint64 { return uint64(c.regs().gregs[_REG_RBP]) }
func (c *sigctxt) rsp() uint64 { return uint64(c.regs().gregs[_REG_RSP]) }
func (c *sigctxt) r8() uint64 { return uint64(c.regs().gregs[_REG_R8]) }
func (c *sigctxt) r9() uint64 { return uint64(c.regs().gregs[_REG_R9]) }
func (c *sigctxt) r10() uint64 { return uint64(c.regs().gregs[_REG_R10]) }
func (c *sigctxt) r11() uint64 { return uint64(c.regs().gregs[_REG_R11]) }
func (c *sigctxt) r12() uint64 { return uint64(c.regs().gregs[_REG_R12]) }
func (c *sigctxt) r13() uint64 { return uint64(c.regs().gregs[_REG_R13]) }
func (c *sigctxt) r14() uint64 { return uint64(c.regs().gregs[_REG_R14]) }
func (c *sigctxt) r15() uint64 { return uint64(c.regs().gregs[_REG_R15]) }
func (c *sigctxt) rip() uint64 { return uint64(c.regs().gregs[_REG_RIP]) }
func (c *sigctxt) rflags() uint64 { return uint64(c.regs().gregs[_REG_RFLAGS]) }
func (c *sigctxt) cs() uint64 { return uint64(c.regs().gregs[_REG_CS]) }
func (c *sigctxt) fs() uint64 { return uint64(c.regs().gregs[_REG_FS]) }
func (c *sigctxt) gs() uint64 { return uint64(c.regs().gregs[_REG_GS]) }
func (c *sigctxt) sigcode() uint64 { return uint64(c.info.si_code) }
func (c *sigctxt) sigaddr() uint64 { return uint64(uintptr(unsafe.Pointer(&c.info.__data[0]))) }
func (c *sigctxt) set_rip(x uint64) { c.regs().gregs[_REG_RIP] = int64(x) }
func (c *sigctxt) set_rsp(x uint64) { c.regs().gregs[_REG_RSP] = int64(x) }
func (c *sigctxt) set_sigcode(x uint64) { c.info.si_code = int32(x) }
func (c *sigctxt) set_sigaddr(x uint64) {
*(*uintptr)(unsafe.Pointer(&c.info.__data[0])) = uintptr(x)
}
// Copyright 2014 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.
#define SIG_REGS(ctxt) (((Ucontext*)(ctxt))->uc_mcontext)
#define SIG_RAX(info, ctxt) (SIG_REGS(ctxt).gregs[REG_RAX])
#define SIG_RBX(info, ctxt) (SIG_REGS(ctxt).gregs[REG_RBX])
#define SIG_RCX(info, ctxt) (SIG_REGS(ctxt).gregs[REG_RCX])
#define SIG_RDX(info, ctxt) (SIG_REGS(ctxt).gregs[REG_RDX])
#define SIG_RDI(info, ctxt) (SIG_REGS(ctxt).gregs[REG_RDI])
#define SIG_RSI(info, ctxt) (SIG_REGS(ctxt).gregs[REG_RSI])
#define SIG_RBP(info, ctxt) (SIG_REGS(ctxt).gregs[REG_RBP])
#define SIG_RSP(info, ctxt) (SIG_REGS(ctxt).gregs[REG_RSP])
#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).gregs[REG_R8])
#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).gregs[REG_R9])
#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).gregs[REG_R10])
#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).gregs[REG_R11])
#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).gregs[REG_R12])
#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).gregs[REG_R13])
#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).gregs[REG_R14])
#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).gregs[REG_R15])
#define SIG_RIP(info, ctxt) (SIG_REGS(ctxt).gregs[REG_RIP])
#define SIG_RFLAGS(info, ctxt) (SIG_REGS(ctxt).gregs[REG_RFLAGS])
#define SIG_CS(info, ctxt) (SIG_REGS(ctxt).gregs[REG_CS])
#define SIG_FS(info, ctxt) (SIG_REGS(ctxt).gregs[REG_FS])
#define SIG_GS(info, ctxt) (SIG_REGS(ctxt).gregs[REG_GS])
#define SIG_CODE0(info, ctxt) ((info)->si_code)
#define SIG_CODE1(info, ctxt) (*(uintptr*)&(info)->__data[0])
// Copyright 2014 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.
#include "textflag.h"
#define N SigNotify
#define K SigKill
#define T SigThrow
#define P SigPanic
#define D SigDefault
#pragma dataflag NOPTR
SigTab runtime·sigtab[] = {
/* 0 */ 0, "SIGNONE: no trap",
/* 1 */ N+K, "SIGHUP: hangup",
/* 2 */ N+K, "SIGINT: interrupt (rubout)",
/* 3 */ N+T, "SIGQUIT: quit (ASCII FS)",
/* 4 */ T, "SIGILL: illegal instruction (not reset when caught)",
/* 5 */ T, "SIGTRAP: trace trap (not reset when caught)",
/* 6 */ N+T, "SIGABRT: used by abort, replace SIGIOT in the future",
/* 7 */ T, "SIGEMT: EMT instruction",
/* 8 */ P, "SIGFPE: floating point exception",
/* 9 */ 0, "SIGKILL: kill (cannot be caught or ignored)",
/* 10 */ P, "SIGBUS: bus error",
/* 11 */ P, "SIGSEGV: segmentation violation",
/* 12 */ T, "SIGSYS: bad argument to system call",
/* 13 */ N, "SIGPIPE: write on a pipe with no one to read it",
/* 14 */ N, "SIGALRM: alarm clock",
/* 15 */ N+K, "SIGTERM: software termination signal from kill",
/* 16 */ N, "SIGUSR1: user defined signal 1",
/* 17 */ N, "SIGUSR2: user defined signal 2",
/* 18 */ N, "SIGCLD: child status change",
/* 18 */ N, "SIGCHLD: child status change alias (POSIX)",
/* 19 */ N, "SIGPWR: power-fail restart",
/* 20 */ N, "SIGWINCH: window size change",
/* 21 */ N, "SIGURG: urgent socket condition",
/* 22 */ N, "SIGPOLL: pollable event occured",
/* 23 */ N+D, "SIGSTOP: stop (cannot be caught or ignored)",
/* 24 */ 0, "SIGTSTP: user stop requested from tty",
/* 25 */ 0, "SIGCONT: stopped process has been continued",
/* 26 */ N+D, "SIGTTIN: background tty read attempted",
/* 27 */ N+D, "SIGTTOU: background tty write attempted",
/* 28 */ N, "SIGVTALRM: virtual timer expired",
/* 29 */ N, "SIGPROF: profiling timer expired",
/* 30 */ N, "SIGXCPU: exceeded cpu limit",
/* 31 */ N, "SIGXFSZ: exceeded file size limit",
/* 32 */ N, "SIGWAITING: reserved signal no longer used by",
/* 33 */ N, "SIGLWP: reserved signal no longer used by",
/* 34 */ N, "SIGFREEZE: special signal used by CPR",
/* 35 */ N, "SIGTHAW: special signal used by CPR",
/* 36 */ 0, "SIGCANCEL: reserved signal for thread cancellation",
/* 37 */ N, "SIGLOST: resource lost (eg, record-lock lost)",
/* 38 */ N, "SIGXRES: resource control exceeded",
/* 39 */ N, "SIGJVM1: reserved signal for Java Virtual Machine",
/* 40 */ N, "SIGJVM2: reserved signal for Java Virtual Machine",
/* TODO(aram): what should be do about these signals? D or N? is this set static? */
/* 41 */ N, "real time signal",
/* 42 */ N, "real time signal",
/* 43 */ N, "real time signal",
/* 44 */ N, "real time signal",
/* 45 */ N, "real time signal",
/* 46 */ N, "real time signal",
/* 47 */ N, "real time signal",
/* 48 */ N, "real time signal",
/* 49 */ N, "real time signal",
/* 50 */ N, "real time signal",
/* 51 */ N, "real time signal",
/* 52 */ N, "real time signal",
/* 53 */ N, "real time signal",
/* 54 */ N, "real time signal",
/* 55 */ N, "real time signal",
/* 56 */ N, "real time signal",
/* 57 */ N, "real time signal",
/* 58 */ N, "real time signal",
/* 59 */ N, "real time signal",
/* 60 */ N, "real time signal",
/* 61 */ N, "real time signal",
/* 62 */ N, "real time signal",
/* 63 */ N, "real time signal",
/* 64 */ N, "real time signal",
/* 65 */ N, "real time signal",
/* 66 */ N, "real time signal",
/* 67 */ N, "real time signal",
/* 68 */ N, "real time signal",
/* 69 */ N, "real time signal",
/* 70 */ N, "real time signal",
/* 71 */ N, "real time signal",
/* 72 */ N, "real time signal",
};
#undef N
#undef K
#undef T
#undef P
#undef D
...@@ -96,8 +96,6 @@ func noescape(p unsafe.Pointer) unsafe.Pointer { ...@@ -96,8 +96,6 @@ func noescape(p unsafe.Pointer) unsafe.Pointer {
func cgocallback(fn, frame unsafe.Pointer, framesize uintptr) func cgocallback(fn, frame unsafe.Pointer, framesize uintptr)
func gogo(buf *gobuf) func gogo(buf *gobuf)
func gosave(buf *gobuf) func gosave(buf *gobuf)
func read(fd int32, p unsafe.Pointer, n int32) int32
func close(fd int32) int32
func mincore(addr unsafe.Pointer, n uintptr, dst *byte) int32 func mincore(addr unsafe.Pointer, n uintptr, dst *byte) int32
//go:noescape //go:noescape
...@@ -105,22 +103,13 @@ func jmpdefer(fv *funcval, argp uintptr) ...@@ -105,22 +103,13 @@ func jmpdefer(fv *funcval, argp uintptr)
func exit1(code int32) func exit1(code int32)
func asminit() func asminit()
func setg(gg *g) func setg(gg *g)
func exit(code int32)
func breakpoint() func breakpoint()
func nanotime() int64
func usleep(usec uint32)
func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer
func munmap(addr unsafe.Pointer, n uintptr)
func madvise(addr unsafe.Pointer, n uintptr, flags int32)
func reflectcall(fn, arg unsafe.Pointer, n uint32, retoffset uint32) func reflectcall(fn, arg unsafe.Pointer, n uint32, retoffset uint32)
func procyield(cycles uint32) func procyield(cycles uint32)
func cgocallback_gofunc(fv *funcval, frame unsafe.Pointer, framesize uintptr) func cgocallback_gofunc(fv *funcval, frame unsafe.Pointer, framesize uintptr)
func goexit() func goexit()
//go:noescape
func write(fd uintptr, p unsafe.Pointer, n int32) int32
//go:noescape //go:noescape
func cas(ptr *uint32, old, new uint32) bool func cas(ptr *uint32, old, new uint32) bool
...@@ -195,9 +184,6 @@ func asmcgocall(fn, arg unsafe.Pointer) ...@@ -195,9 +184,6 @@ func asmcgocall(fn, arg unsafe.Pointer)
//go:noescape //go:noescape
func asmcgocall_errno(fn, arg unsafe.Pointer) int32 func asmcgocall_errno(fn, arg unsafe.Pointer) int32
//go:noescape
func open(name *byte, mode, perm int32) int32
// argp used in Defer structs when there is no argp. // argp used in Defer structs when there is no argp.
const _NoArgs = ^uintptr(0) const _NoArgs = ^uintptr(0)
......
// Copyright 2014 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 !solaris
package runtime
import "unsafe"
func read(fd int32, p unsafe.Pointer, n int32) int32
func close(fd int32) int32
func exit(code int32)
func nanotime() int64
func usleep(usec uint32)
func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer
func munmap(addr unsafe.Pointer, n uintptr)
//go:noescape
func write(fd uintptr, p unsafe.Pointer, n int32) int32
//go:noescape
func open(name *byte, mode, perm int32) int32
func madvise(addr unsafe.Pointer, n uintptr, flags int32)
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
TEXT runtime·settls(SB),NOSPLIT,$8 TEXT runtime·settls(SB),NOSPLIT,$8
RET RET
// void libc·miniterrno(void *(*___errno)(void)); // void libc_miniterrno(void *(*___errno)(void));
// //
// Set the TLS errno pointer in M. // Set the TLS errno pointer in M.
// //
...@@ -41,7 +41,7 @@ TEXT runtime·nanotime1(SB),NOSPLIT,$0 ...@@ -41,7 +41,7 @@ TEXT runtime·nanotime1(SB),NOSPLIT,$0
SUBQ $64, SP // 16 bytes will do, but who knows in the future? SUBQ $64, SP // 16 bytes will do, but who knows in the future?
MOVQ $3, DI // CLOCK_REALTIME from <sys/time_impl.h> MOVQ $3, DI // CLOCK_REALTIME from <sys/time_impl.h>
MOVQ SP, SI MOVQ SP, SI
MOVQ libc·clock_gettime(SB), AX MOVQ libc_clock_gettime(SB), AX
CALL AX CALL AX
MOVQ (SP), AX // tv_sec from struct timespec MOVQ (SP), AX // tv_sec from struct timespec
IMULQ $1000000000, AX // multiply into nanoseconds IMULQ $1000000000, AX // multiply into nanoseconds
...@@ -54,7 +54,7 @@ TEXT runtime·nanotime1(SB),NOSPLIT,$0 ...@@ -54,7 +54,7 @@ TEXT runtime·nanotime1(SB),NOSPLIT,$0
TEXT runtime·pipe1(SB),NOSPLIT,$0 TEXT runtime·pipe1(SB),NOSPLIT,$0
SUBQ $16, SP // 8 bytes will do, but stack has to be 16-byte alligned SUBQ $16, SP // 8 bytes will do, but stack has to be 16-byte alligned
MOVQ SP, DI MOVQ SP, DI
MOVQ libc·pipe(SB), AX MOVQ libc_pipe(SB), AX
CALL AX CALL AX
MOVL 0(SP), AX MOVL 0(SP), AX
MOVL 4(SP), DX MOVL 4(SP), DX
...@@ -133,7 +133,7 @@ TEXT runtime·tstart_sysvicall(SB),NOSPLIT,$0 ...@@ -133,7 +133,7 @@ TEXT runtime·tstart_sysvicall(SB),NOSPLIT,$0
MOVQ AX, (g_stack+stack_hi)(DX) MOVQ AX, (g_stack+stack_hi)(DX)
SUBQ $(0x100000), AX // stack size SUBQ $(0x100000), AX // stack size
MOVQ AX, (g_stack+stack_lo)(DX) MOVQ AX, (g_stack+stack_lo)(DX)
ADDQ $const_StackGuard, AX ADDQ $const__StackGuard, AX
MOVQ AX, g_stackguard0(DX) MOVQ AX, g_stackguard0(DX)
MOVQ AX, g_stackguard1(DX) MOVQ AX, g_stackguard1(DX)
...@@ -321,13 +321,13 @@ usleep1_noswitch: ...@@ -321,13 +321,13 @@ usleep1_noswitch:
// Runs on OS stack. duration (in µs units) is in DI. // Runs on OS stack. duration (in µs units) is in DI.
TEXT runtime·usleep2(SB),NOSPLIT,$0 TEXT runtime·usleep2(SB),NOSPLIT,$0
MOVQ libc·usleep(SB), AX MOVQ libc_usleep(SB), AX
CALL AX CALL AX
RET RET
// Runs on OS stack, called from runtime·osyield. // Runs on OS stack, called from runtime·osyield.
TEXT runtime·osyield1(SB),NOSPLIT,$0 TEXT runtime·osyield1(SB),NOSPLIT,$0
MOVQ libc·sched_yield(SB), AX MOVQ libc_sched_yield(SB), AX
CALL AX CALL AX
RET RET
......
// Copyright 2014 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.
package runtime
import _ "unsafe"
//go:cgo_import_dynamic libc_chdir chdir "libc.so"
//go:cgo_import_dynamic libc_chroot chroot "libc.so"
//go:cgo_import_dynamic libc_close close "libc.so"
//go:cgo_import_dynamic libc_dlclose dlclose "libc.so"
//go:cgo_import_dynamic libc_dlopen dlopen "libc.so"
//go:cgo_import_dynamic libc_dlsym dlsym "libc.so"
//go:cgo_import_dynamic libc_execve execve "libc.so"
//go:cgo_import_dynamic libc_fcntl fcntl "libc.so"
//go:cgo_import_dynamic libc_gethostname gethostname "libc.so"
//go:cgo_import_dynamic libc_ioctl ioctl "libc.so"
//go:cgo_import_dynamic libc_pipe pipe "libc.so"
//go:cgo_import_dynamic libc_setgid setgid "libc.so"
//go:cgo_import_dynamic libc_setgroups setgroups "libc.so"
//go:cgo_import_dynamic libc_setsid setsid "libc.so"
//go:cgo_import_dynamic libc_setuid setuid "libc.so"
//go:cgo_import_dynamic libc_setpgid setsid "libc.so"
//go:cgo_import_dynamic libc_syscall syscall "libc.so"
//go:cgo_import_dynamic libc_forkx forkx "libc.so"
//go:cgo_import_dynamic libc_wait4 wait4 "libc.so"
//go:linkname libc_chdir libc_chdir
//go:linkname libc_chroot libc_chroot
//go:linkname libc_close libc_close
//go:linkname libc_dlclose libc_dlclose
//go:linkname libc_dlopen libc_dlopen
//go:linkname libc_dlsym libc_dlsym
//go:linkname libc_execve libc_execve
//go:linkname libc_fcntl libc_fcntl
//go:linkname libc_gethostname libc_gethostname
//go:linkname libc_ioctl libc_ioctl
//go:linkname libc_pipe libc_pipe
//go:linkname libc_setgid libc_setgid
//go:linkname libc_setgroups libc_setgroups
//go:linkname libc_setsid libc_setsid
//go:linkname libc_setuid libc_setuid
//go:linkname libc_setpgid libc_setpgid
//go:linkname libc_syscall libc_syscall
//go:linkname libc_forkx libc_forkx
//go:linkname libc_wait4 libc_wait4
// Copyright 2014 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.
#pragma dynimport libc·chdir chdir "libc.so"
#pragma dynimport libc·chroot chroot "libc.so"
#pragma dynimport libc·close close "libc.so"
#pragma dynimport libc·dlclose dlclose "libc.so"
#pragma dynimport libc·dlopen dlopen "libc.so"
#pragma dynimport libc·dlsym dlsym "libc.so"
#pragma dynimport libc·execve execve "libc.so"
#pragma dynimport libc·fcntl fcntl "libc.so"
#pragma dynimport libc·gethostname gethostname "libc.so"
#pragma dynimport libc·ioctl ioctl "libc.so"
#pragma dynimport libc·pipe pipe "libc.so"
#pragma dynimport libc·setgid setgid "libc.so"
#pragma dynimport libc·setgroups setgroups "libc.so"
#pragma dynimport libc·setsid setsid "libc.so"
#pragma dynimport libc·setuid setuid "libc.so"
#pragma dynimport libc·setpgid setsid "libc.so"
#pragma dynimport libc·syscall syscall "libc.so"
#pragma dynimport libc·forkx forkx "libc.so"
#pragma dynimport libc·wait4 wait4 "libc.so"
...@@ -9,12 +9,10 @@ import "unsafe" ...@@ -9,12 +9,10 @@ import "unsafe"
var ( var (
libc_chdir, libc_chdir,
libc_chroot, libc_chroot,
libc_close,
libc_dlopen, libc_dlopen,
libc_dlclose, libc_dlclose,
libc_dlsym, libc_dlsym,
libc_execve, libc_execve,
libc_exit,
libc_fcntl, libc_fcntl,
libc_forkx, libc_forkx,
libc_gethostname, libc_gethostname,
...@@ -27,7 +25,6 @@ var ( ...@@ -27,7 +25,6 @@ var (
libc_setpgid, libc_setpgid,
libc_syscall, libc_syscall,
libc_wait4, libc_wait4,
libc_write,
pipe1 libcFunc pipe1 libcFunc
) )
...@@ -38,9 +35,9 @@ func syscall_sysvicall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err ...@@ -38,9 +35,9 @@ func syscall_sysvicall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err
n: nargs, n: nargs,
args: uintptr(unsafe.Pointer(&a1)), args: uintptr(unsafe.Pointer(&a1)),
} }
entersyscallblock() entersyscallblock(0)
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call)) asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
exitsyscall() exitsyscall(0)
return call.r1, call.r2, call.err return call.r1, call.r2, call.err
} }
...@@ -62,7 +59,7 @@ func syscall_rawsysvicall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, e ...@@ -62,7 +59,7 @@ func syscall_rawsysvicall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, e
//go:nosplit //go:nosplit
func syscall_chdir(path uintptr) (err uintptr) { func syscall_chdir(path uintptr) (err uintptr) {
call := libcall{ call := libcall{
fn: uintptr(unsafe.Pointer(&libc_chdir)), fn: uintptr(unsafe.Pointer(libc_chdir)),
n: 1, n: 1,
args: uintptr(unsafe.Pointer(&path)), args: uintptr(unsafe.Pointer(&path)),
} }
...@@ -73,7 +70,7 @@ func syscall_chdir(path uintptr) (err uintptr) { ...@@ -73,7 +70,7 @@ func syscall_chdir(path uintptr) (err uintptr) {
//go:nosplit //go:nosplit
func syscall_chroot(path uintptr) (err uintptr) { func syscall_chroot(path uintptr) (err uintptr) {
call := libcall{ call := libcall{
fn: uintptr(unsafe.Pointer(&libc_chroot)), fn: uintptr(unsafe.Pointer(libc_chroot)),
n: 1, n: 1,
args: uintptr(unsafe.Pointer(&path)), args: uintptr(unsafe.Pointer(&path)),
} }
...@@ -84,18 +81,18 @@ func syscall_chroot(path uintptr) (err uintptr) { ...@@ -84,18 +81,18 @@ func syscall_chroot(path uintptr) (err uintptr) {
// like close, but must not split stack, for forkx. // like close, but must not split stack, for forkx.
//go:nosplit //go:nosplit
func syscall_close(fd int32) int32 { func syscall_close(fd int32) int32 {
return int32(sysvicall1(&libc_close, uintptr(fd))) return int32(sysvicall1(libc_close, uintptr(fd)))
} }
func syscall_dlopen(name *byte, mode uintptr) (handle uintptr, err uintptr) { func syscall_dlopen(name *byte, mode uintptr) (handle uintptr, err uintptr) {
call := libcall{ call := libcall{
fn: uintptr(unsafe.Pointer(&libc_dlopen)), fn: uintptr(unsafe.Pointer(libc_dlopen)),
n: 2, n: 2,
args: uintptr(unsafe.Pointer(&name)), args: uintptr(unsafe.Pointer(&name)),
} }
entersyscallblock() entersyscallblock(0)
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call)) asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
exitsyscall() exitsyscall(0)
if call.r1 == 0 { if call.r1 == 0 {
return call.r1, call.err return call.r1, call.err
} }
...@@ -104,25 +101,25 @@ func syscall_dlopen(name *byte, mode uintptr) (handle uintptr, err uintptr) { ...@@ -104,25 +101,25 @@ func syscall_dlopen(name *byte, mode uintptr) (handle uintptr, err uintptr) {
func syscall_dlclose(handle uintptr) (err uintptr) { func syscall_dlclose(handle uintptr) (err uintptr) {
call := libcall{ call := libcall{
fn: uintptr(unsafe.Pointer(&libc_dlclose)), fn: uintptr(unsafe.Pointer(libc_dlclose)),
n: 1, n: 1,
args: uintptr(unsafe.Pointer(&handle)), args: uintptr(unsafe.Pointer(&handle)),
} }
entersyscallblock() entersyscallblock(0)
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call)) asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
exitsyscall() exitsyscall(0)
return call.r1 return call.r1
} }
func syscall_dlsym(handle uintptr, name *byte) (proc uintptr, err uintptr) { func syscall_dlsym(handle uintptr, name *byte) (proc uintptr, err uintptr) {
call := libcall{ call := libcall{
fn: uintptr(unsafe.Pointer(&libc_dlsym)), fn: uintptr(unsafe.Pointer(libc_dlsym)),
n: 2, n: 2,
args: uintptr(unsafe.Pointer(&handle)), args: uintptr(unsafe.Pointer(&handle)),
} }
entersyscallblock() entersyscallblock(0)
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call)) asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
exitsyscall() exitsyscall(0)
if call.r1 == 0 { if call.r1 == 0 {
return call.r1, call.err return call.r1, call.err
} }
...@@ -132,7 +129,7 @@ func syscall_dlsym(handle uintptr, name *byte) (proc uintptr, err uintptr) { ...@@ -132,7 +129,7 @@ func syscall_dlsym(handle uintptr, name *byte) (proc uintptr, err uintptr) {
//go:nosplit //go:nosplit
func syscall_execve(path, argv, envp uintptr) (err uintptr) { func syscall_execve(path, argv, envp uintptr) (err uintptr) {
call := libcall{ call := libcall{
fn: uintptr(unsafe.Pointer(&libc_execve)), fn: uintptr(unsafe.Pointer(libc_execve)),
n: 3, n: 3,
args: uintptr(unsafe.Pointer(&path)), args: uintptr(unsafe.Pointer(&path)),
} }
...@@ -143,13 +140,13 @@ func syscall_execve(path, argv, envp uintptr) (err uintptr) { ...@@ -143,13 +140,13 @@ func syscall_execve(path, argv, envp uintptr) (err uintptr) {
// like exit, but must not split stack, for forkx. // like exit, but must not split stack, for forkx.
//go:nosplit //go:nosplit
func syscall_exit(code uintptr) { func syscall_exit(code uintptr) {
sysvicall1(&libc_exit, code) sysvicall1(libc_exit, code)
} }
//go:nosplit //go:nosplit
func syscall_fcntl(fd, cmd, arg uintptr) (val, err uintptr) { func syscall_fcntl(fd, cmd, arg uintptr) (val, err uintptr) {
call := libcall{ call := libcall{
fn: uintptr(unsafe.Pointer(&libc_fcntl)), fn: uintptr(unsafe.Pointer(libc_fcntl)),
n: 3, n: 3,
args: uintptr(unsafe.Pointer(&fd)), args: uintptr(unsafe.Pointer(&fd)),
} }
...@@ -160,7 +157,7 @@ func syscall_fcntl(fd, cmd, arg uintptr) (val, err uintptr) { ...@@ -160,7 +157,7 @@ func syscall_fcntl(fd, cmd, arg uintptr) (val, err uintptr) {
//go:nosplit //go:nosplit
func syscall_forkx(flags uintptr) (pid uintptr, err uintptr) { func syscall_forkx(flags uintptr) (pid uintptr, err uintptr) {
call := libcall{ call := libcall{
fn: uintptr(unsafe.Pointer(&libc_forkx)), fn: uintptr(unsafe.Pointer(libc_forkx)),
n: 1, n: 1,
args: uintptr(unsafe.Pointer(&flags)), args: uintptr(unsafe.Pointer(&flags)),
} }
...@@ -172,13 +169,13 @@ func syscall_gethostname() (name string, err uintptr) { ...@@ -172,13 +169,13 @@ func syscall_gethostname() (name string, err uintptr) {
cname := new([_MAXHOSTNAMELEN]byte) cname := new([_MAXHOSTNAMELEN]byte)
var args = [2]uintptr{uintptr(unsafe.Pointer(&cname[0])), _MAXHOSTNAMELEN} var args = [2]uintptr{uintptr(unsafe.Pointer(&cname[0])), _MAXHOSTNAMELEN}
call := libcall{ call := libcall{
fn: uintptr(unsafe.Pointer(&libc_gethostname)), fn: uintptr(unsafe.Pointer(libc_gethostname)),
n: 2, n: 2,
args: uintptr(unsafe.Pointer(&args[0])), args: uintptr(unsafe.Pointer(&args[0])),
} }
entersyscallblock() entersyscallblock(0)
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call)) asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
exitsyscall() exitsyscall(0)
if call.r1 != 0 { if call.r1 != 0 {
return "", call.err return "", call.err
} }
...@@ -189,7 +186,7 @@ func syscall_gethostname() (name string, err uintptr) { ...@@ -189,7 +186,7 @@ func syscall_gethostname() (name string, err uintptr) {
//go:nosplit //go:nosplit
func syscall_ioctl(fd, req, arg uintptr) (err uintptr) { func syscall_ioctl(fd, req, arg uintptr) (err uintptr) {
call := libcall{ call := libcall{
fn: uintptr(unsafe.Pointer(&libc_ioctl)), fn: uintptr(unsafe.Pointer(libc_ioctl)),
n: 3, n: 3,
args: uintptr(unsafe.Pointer(&fd)), args: uintptr(unsafe.Pointer(&fd)),
} }
...@@ -203,9 +200,9 @@ func syscall_pipe() (r, w, err uintptr) { ...@@ -203,9 +200,9 @@ func syscall_pipe() (r, w, err uintptr) {
n: 0, n: 0,
args: uintptr(unsafe.Pointer(&pipe1)), // it's unused but must be non-nil, otherwise crashes args: uintptr(unsafe.Pointer(&pipe1)), // it's unused but must be non-nil, otherwise crashes
} }
entersyscallblock() entersyscallblock(0)
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call)) asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
exitsyscall() exitsyscall(0)
return call.r1, call.r2, call.err return call.r1, call.r2, call.err
} }
...@@ -217,7 +214,7 @@ func syscall_pipe() (r, w, err uintptr) { ...@@ -217,7 +214,7 @@ func syscall_pipe() (r, w, err uintptr) {
// TODO(aram): make this panic once we stop calling fcntl(2) in net using it. // TODO(aram): make this panic once we stop calling fcntl(2) in net using it.
func syscall_rawsyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) { func syscall_rawsyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
call := libcall{ call := libcall{
fn: uintptr(unsafe.Pointer(&libc_syscall)), fn: uintptr(unsafe.Pointer(libc_syscall)),
n: 4, n: 4,
args: uintptr(unsafe.Pointer(&trap)), args: uintptr(unsafe.Pointer(&trap)),
} }
...@@ -228,7 +225,7 @@ func syscall_rawsyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) { ...@@ -228,7 +225,7 @@ func syscall_rawsyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
//go:nosplit //go:nosplit
func syscall_setgid(gid uintptr) (err uintptr) { func syscall_setgid(gid uintptr) (err uintptr) {
call := libcall{ call := libcall{
fn: uintptr(unsafe.Pointer(&libc_setgid)), fn: uintptr(unsafe.Pointer(libc_setgid)),
n: 1, n: 1,
args: uintptr(unsafe.Pointer(&gid)), args: uintptr(unsafe.Pointer(&gid)),
} }
...@@ -239,7 +236,7 @@ func syscall_setgid(gid uintptr) (err uintptr) { ...@@ -239,7 +236,7 @@ func syscall_setgid(gid uintptr) (err uintptr) {
//go:nosplit //go:nosplit
func syscall_setgroups(ngid, gid uintptr) (err uintptr) { func syscall_setgroups(ngid, gid uintptr) (err uintptr) {
call := libcall{ call := libcall{
fn: uintptr(unsafe.Pointer(&libc_setgroups)), fn: uintptr(unsafe.Pointer(libc_setgroups)),
n: 2, n: 2,
args: uintptr(unsafe.Pointer(&ngid)), args: uintptr(unsafe.Pointer(&ngid)),
} }
...@@ -250,9 +247,9 @@ func syscall_setgroups(ngid, gid uintptr) (err uintptr) { ...@@ -250,9 +247,9 @@ func syscall_setgroups(ngid, gid uintptr) (err uintptr) {
//go:nosplit //go:nosplit
func syscall_setsid() (pid, err uintptr) { func syscall_setsid() (pid, err uintptr) {
call := libcall{ call := libcall{
fn: uintptr(unsafe.Pointer(&libc_setsid)), fn: uintptr(unsafe.Pointer(libc_setsid)),
n: 0, n: 0,
args: uintptr(unsafe.Pointer(&libc_setsid)), // it's unused but must be non-nil, otherwise crashes args: uintptr(unsafe.Pointer(libc_setsid)), // it's unused but must be non-nil, otherwise crashes
} }
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call)) asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
return call.r1, call.err return call.r1, call.err
...@@ -261,7 +258,7 @@ func syscall_setsid() (pid, err uintptr) { ...@@ -261,7 +258,7 @@ func syscall_setsid() (pid, err uintptr) {
//go:nosplit //go:nosplit
func syscall_setuid(uid uintptr) (err uintptr) { func syscall_setuid(uid uintptr) (err uintptr) {
call := libcall{ call := libcall{
fn: uintptr(unsafe.Pointer(&libc_setuid)), fn: uintptr(unsafe.Pointer(libc_setuid)),
n: 1, n: 1,
args: uintptr(unsafe.Pointer(&uid)), args: uintptr(unsafe.Pointer(&uid)),
} }
...@@ -272,7 +269,7 @@ func syscall_setuid(uid uintptr) (err uintptr) { ...@@ -272,7 +269,7 @@ func syscall_setuid(uid uintptr) (err uintptr) {
//go:nosplit //go:nosplit
func syscall_setpgid(pid, pgid uintptr) (err uintptr) { func syscall_setpgid(pid, pgid uintptr) (err uintptr) {
call := libcall{ call := libcall{
fn: uintptr(unsafe.Pointer(&libc_setpgid)), fn: uintptr(unsafe.Pointer(libc_setpgid)),
n: 2, n: 2,
args: uintptr(unsafe.Pointer(&pid)), args: uintptr(unsafe.Pointer(&pid)),
} }
...@@ -288,32 +285,32 @@ func syscall_setpgid(pid, pgid uintptr) (err uintptr) { ...@@ -288,32 +285,32 @@ func syscall_setpgid(pid, pgid uintptr) (err uintptr) {
// TODO(aram): make this panic once we stop calling fcntl(2) in net using it. // TODO(aram): make this panic once we stop calling fcntl(2) in net using it.
func syscall_syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) { func syscall_syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
call := libcall{ call := libcall{
fn: uintptr(unsafe.Pointer(&libc_syscall)), fn: uintptr(unsafe.Pointer(libc_syscall)),
n: 4, n: 4,
args: uintptr(unsafe.Pointer(&trap)), args: uintptr(unsafe.Pointer(&trap)),
} }
entersyscallblock() entersyscallblock(0)
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call)) asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
exitsyscall() exitsyscall(0)
return call.r1, call.r2, call.err return call.r1, call.r2, call.err
} }
func syscall_wait4(pid uintptr, wstatus *uint32, options uintptr, rusage unsafe.Pointer) (wpid int, err uintptr) { func syscall_wait4(pid uintptr, wstatus *uint32, options uintptr, rusage unsafe.Pointer) (wpid int, err uintptr) {
call := libcall{ call := libcall{
fn: uintptr(unsafe.Pointer(&libc_wait4)), fn: uintptr(unsafe.Pointer(libc_wait4)),
n: 4, n: 4,
args: uintptr(unsafe.Pointer(&pid)), args: uintptr(unsafe.Pointer(&pid)),
} }
entersyscallblock() entersyscallblock(0)
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call)) asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
exitsyscall() exitsyscall(0)
return int(call.r1), call.err return int(call.r1), call.err
} }
//go:nosplit //go:nosplit
func syscall_write(fd, buf, nbyte uintptr) (n, err uintptr) { func syscall_write(fd, buf, nbyte uintptr) (n, err uintptr) {
call := libcall{ call := libcall{
fn: uintptr(unsafe.Pointer(&libc_write)), fn: uintptr(unsafe.Pointer(libc_write)),
n: 3, n: 3,
args: uintptr(unsafe.Pointer(&fd)), args: uintptr(unsafe.Pointer(&fd)),
} }
......
// Copyright 2014 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.
// This file exposes various external library functions to Go code in the runtime.
#include "go_asm.h"
#include "go_tls.h"
#include "textflag.h"
TEXT runtime·libc_chdir(SB),NOSPLIT,$0
MOVQ libc·chdir(SB), AX
JMP AX
TEXT runtime·libc_chroot(SB),NOSPLIT,$0
MOVQ libc·chroot(SB), AX
JMP AX
TEXT runtime·libc_close(SB),NOSPLIT,$0
MOVQ libc·close(SB), AX
JMP AX
TEXT runtime·libc_dlopen(SB),NOSPLIT,$0
MOVQ libc·dlopen(SB), AX
JMP AX
TEXT runtime·libc_dlclose(SB),NOSPLIT,$0
MOVQ libc·dlclose(SB), AX
JMP AX
TEXT runtime·libc_dlsym(SB),NOSPLIT,$0
MOVQ libc·dlsym(SB), AX
JMP AX
TEXT runtime·libc_execve(SB),NOSPLIT,$0
MOVQ libc·execve(SB), AX
JMP AX
TEXT runtime·libc_exit(SB),NOSPLIT,$0
MOVQ libc·exit(SB), AX
JMP AX
TEXT runtime·libc_fcntl(SB),NOSPLIT,$0
MOVQ libc·fcntl(SB), AX
JMP AX
TEXT runtime·libc_forkx(SB),NOSPLIT,$0
MOVQ libc·forkx(SB), AX
JMP AX
TEXT runtime·libc_gethostname(SB),NOSPLIT,$0
MOVQ libc·gethostname(SB), AX
JMP AX
TEXT runtime·libc_ioctl(SB),NOSPLIT,$0
MOVQ libc·ioctl(SB), AX
JMP AX
TEXT runtime·libc_setgid(SB),NOSPLIT,$0
MOVQ libc·setgid(SB), AX
JMP AX
TEXT runtime·libc_setgroups(SB),NOSPLIT,$0
MOVQ libc·setgroups(SB), AX
JMP AX
TEXT runtime·libc_setsid(SB),NOSPLIT,$0
MOVQ libc·setsid(SB), AX
JMP AX
TEXT runtime·libc_setuid(SB),NOSPLIT,$0
MOVQ libc·setuid(SB), AX
JMP AX
TEXT runtime·libc_setpgid(SB),NOSPLIT,$0
MOVQ libc·setpgid(SB), AX
JMP AX
TEXT runtime·libc_syscall(SB),NOSPLIT,$0
MOVQ libc·syscall(SB), AX
JMP AX
TEXT runtime·libc_wait4(SB),NOSPLIT,$0
MOVQ libc·wait4(SB), AX
JMP AX
TEXT runtime·libc_write(SB),NOSPLIT,$0
MOVQ libc·write(SB), AX
JMP AX
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