mirror of
https://github.com/golang/go.git
synced 2025-05-29 03:11:26 +00:00
[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
This commit is contained in:
parent
a0862a175d
commit
e088e16256
@ -1543,9 +1543,8 @@ static vlong vaddr(Link*, Addr*, Reloc*);
|
||||
static int
|
||||
isextern(LSym *s)
|
||||
{
|
||||
// All the Solaris dynamic imports from libc.so begin with "libc·", which
|
||||
// the compiler rewrites to "libc." by the time liblink gets it.
|
||||
return strncmp(s->name, "libc.", 5) == 0;
|
||||
// All the Solaris dynamic imports from libc.so begin with "libc_".
|
||||
return strncmp(s->name, "libc_", 5) == 0;
|
||||
}
|
||||
|
||||
// single-instruction no-ops of various lengths.
|
||||
|
@ -172,6 +172,10 @@ type timeval struct {
|
||||
tv_usec int64
|
||||
}
|
||||
|
||||
func (tv *timeval) set_usec(x int32) {
|
||||
tv.tv_usec = int64(x)
|
||||
}
|
||||
|
||||
type itimerval struct {
|
||||
it_interval timeval
|
||||
it_value timeval
|
||||
@ -185,6 +189,7 @@ type portevent struct {
|
||||
portev_user *byte
|
||||
}
|
||||
|
||||
type pthread uint32
|
||||
type pthreadattr struct {
|
||||
__pthread_attrp *byte
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build dragonfly freebsd netbsd openbsd
|
||||
// +build dragonfly freebsd netbsd openbsd solaris
|
||||
|
||||
package runtime
|
||||
|
||||
|
@ -1,101 +0,0 @@
|
||||
// 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");
|
||||
}
|
@ -49,14 +49,14 @@ type pollDesc struct {
|
||||
lock mutex // protectes the following fields
|
||||
fd uintptr
|
||||
closing bool
|
||||
seq uintptr // protects from stale timers and ready notifications
|
||||
rg uintptr // pdReady, pdWait, G waiting for read or nil
|
||||
rt timer // read deadline timer (set if rt.f != nil)
|
||||
rd int64 // read deadline
|
||||
wg uintptr // pdReady, pdWait, G waiting for write or nil
|
||||
wt timer // write deadline timer
|
||||
wd int64 // write deadline
|
||||
user unsafe.Pointer // user settable cookie
|
||||
seq uintptr // protects from stale timers and ready notifications
|
||||
rg uintptr // pdReady, pdWait, G waiting for read or nil
|
||||
rt timer // read deadline timer (set if rt.f != nil)
|
||||
rd int64 // read deadline
|
||||
wg uintptr // pdReady, pdWait, G waiting for write or nil
|
||||
wt timer // write deadline timer
|
||||
wd int64 // write deadline
|
||||
user uint32 // user settable cookie
|
||||
}
|
||||
|
||||
type pollCache struct {
|
||||
@ -72,7 +72,7 @@ type pollCache struct {
|
||||
var pollcache pollCache
|
||||
|
||||
func netpollServerInit() {
|
||||
systemstack(netpollinit)
|
||||
netpollinit()
|
||||
}
|
||||
|
||||
func netpollOpen(fd uintptr) (*pollDesc, int) {
|
||||
@ -94,9 +94,7 @@ func netpollOpen(fd uintptr) (*pollDesc, int) {
|
||||
unlock(&pd.lock)
|
||||
|
||||
var errno int32
|
||||
systemstack(func() {
|
||||
errno = netpollopen(fd, pd)
|
||||
})
|
||||
errno = netpollopen(fd, pd)
|
||||
return pd, int(errno)
|
||||
}
|
||||
|
||||
@ -110,9 +108,7 @@ func netpollClose(pd *pollDesc) {
|
||||
if pd.rg != 0 && pd.rg != pdReady {
|
||||
gothrow("netpollClose: blocked read on closing descriptor")
|
||||
}
|
||||
systemstack(func() {
|
||||
netpollclose(uintptr(pd.fd))
|
||||
})
|
||||
netpollclose(uintptr(pd.fd))
|
||||
pollcache.free(pd)
|
||||
}
|
||||
|
||||
@ -143,9 +139,7 @@ func netpollWait(pd *pollDesc, mode int) int {
|
||||
}
|
||||
// As for now only Solaris uses level-triggered IO.
|
||||
if GOOS == "solaris" {
|
||||
systemstack(func() {
|
||||
netpollarm(pd, mode)
|
||||
})
|
||||
netpollarm(pd, mode)
|
||||
}
|
||||
for !netpollblock(pd, int32(mode), false) {
|
||||
err = netpollcheckerr(pd, int32(mode))
|
||||
@ -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
|
||||
func netpollready(gpp **g, pd *pollDesc, mode int32) {
|
||||
var rg, wg *g
|
||||
|
@ -2,13 +2,12 @@
|
||||
// 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"
|
||||
package runtime
|
||||
|
||||
import "unsafe"
|
||||
|
||||
// Solaris runtime-integrated network poller.
|
||||
//
|
||||
//
|
||||
// Solaris uses event ports for scalable network I/O. Event
|
||||
// ports are level-triggered, unlike epoll and kqueue which
|
||||
// can be configured in both level-triggered and edge-triggered
|
||||
@ -18,7 +17,7 @@
|
||||
// events for that descriptor. When doing this we must keep track of
|
||||
// what kind of events the goroutines are currently interested in,
|
||||
// for example a fd may be open both for reading and writing.
|
||||
//
|
||||
//
|
||||
// A description of the high level operation of this code
|
||||
// follows. Networking code will get a file descriptor by some means
|
||||
// and will register it with the netpolling mechanism by a code path
|
||||
@ -29,7 +28,7 @@
|
||||
// readiness notification at some point in the future. If I/O becomes
|
||||
// ready when nobody is listening, when we finally care about it,
|
||||
// nobody will tell us anymore.
|
||||
//
|
||||
//
|
||||
// Beside calling runtime·netpollopen, the networking code paths
|
||||
// will call runtime·netpollarm each time goroutines are interested
|
||||
// in doing network I/O. Because now we know what kind of I/O we
|
||||
@ -39,7 +38,7 @@
|
||||
// when we now call port_associate, we will unblock the main poller
|
||||
// loop (in runtime·netpoll) right away if the socket is actually
|
||||
// ready for I/O.
|
||||
//
|
||||
//
|
||||
// The main poller loop runs in its own thread waiting for events
|
||||
// using port_getn. When an event happens, it will tell the scheduler
|
||||
// about it using runtime·netpollready. Besides doing this, it must
|
||||
@ -47,7 +46,7 @@
|
||||
// notification with the file descriptor. Failing to do this would
|
||||
// mean each notification will prevent concurrent code using the
|
||||
// same file descriptor in parallel.
|
||||
//
|
||||
//
|
||||
// The logic dealing with re-associations is encapsulated in
|
||||
// runtime·netpollupdate. This function takes care to associate the
|
||||
// descriptor only with the subset of events that were previously
|
||||
@ -56,7 +55,7 @@
|
||||
// are level triggered so it would cause a busy loop. Instead, that
|
||||
// association is effected only by the runtime·netpollarm code path,
|
||||
// when Go code actually asks for I/O.
|
||||
//
|
||||
//
|
||||
// The open and arming mechanisms are serialized using the lock
|
||||
// inside PollDesc. This is required because the netpoll loop runs
|
||||
// asynchonously in respect to other Go code and by the time we get
|
||||
@ -68,179 +67,157 @@
|
||||
// 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).
|
||||
|
||||
#pragma dynimport libc·fcntl fcntl "libc.so"
|
||||
#pragma dynimport libc·port_create port_create "libc.so"
|
||||
#pragma dynimport libc·port_associate port_associate "libc.so"
|
||||
#pragma dynimport libc·port_dissociate port_dissociate "libc.so"
|
||||
#pragma dynimport libc·port_getn port_getn "libc.so"
|
||||
extern uintptr libc·fcntl;
|
||||
extern uintptr libc·port_create;
|
||||
extern uintptr libc·port_associate;
|
||||
extern uintptr libc·port_dissociate;
|
||||
extern uintptr libc·port_getn;
|
||||
//go:cgo_import_dynamic libc_port_create port_create "libc.so"
|
||||
//go:cgo_import_dynamic libc_port_associate port_associate "libc.so"
|
||||
//go:cgo_import_dynamic libc_port_dissociate port_dissociate "libc.so"
|
||||
//go:cgo_import_dynamic libc_port_getn port_getn "libc.so"
|
||||
|
||||
#define errno (*g->m->perrno)
|
||||
//go:linkname libc_port_create libc_port_create
|
||||
//go:linkname libc_port_associate libc_port_associate
|
||||
//go:linkname libc_port_dissociate libc_port_dissociate
|
||||
//go:linkname libc_port_getn libc_port_getn
|
||||
|
||||
int32
|
||||
runtime·fcntl(int32 fd, int32 cmd, uintptr arg)
|
||||
{
|
||||
return runtime·sysvicall3(libc·fcntl, (uintptr)fd, (uintptr)cmd, (uintptr)arg);
|
||||
var (
|
||||
libc_port_create,
|
||||
libc_port_associate,
|
||||
libc_port_dissociate,
|
||||
libc_port_getn libcFunc
|
||||
)
|
||||
|
||||
func errno() int32 {
|
||||
return *getg().m.perrno
|
||||
}
|
||||
|
||||
int32
|
||||
runtime·port_create(void)
|
||||
{
|
||||
return runtime·sysvicall0(libc·port_create);
|
||||
func fcntl(fd, cmd int32, arg uintptr) int32 {
|
||||
return int32(sysvicall3(libc_fcntl, uintptr(fd), uintptr(cmd), arg))
|
||||
}
|
||||
|
||||
int32
|
||||
runtime·port_associate(int32 port, int32 source, uintptr object, int32 events, uintptr user)
|
||||
{
|
||||
return runtime·sysvicall5(libc·port_associate, (uintptr)port, (uintptr)source, object, (uintptr)events, user);
|
||||
func port_create() int32 {
|
||||
return int32(sysvicall0(libc_port_create))
|
||||
}
|
||||
|
||||
int32
|
||||
runtime·port_dissociate(int32 port, int32 source, uintptr object)
|
||||
{
|
||||
return runtime·sysvicall3(libc·port_dissociate, (uintptr)port, (uintptr)source, object);
|
||||
func port_associate(port, source int32, object uintptr, events uint32, user uintptr) int32 {
|
||||
return int32(sysvicall5(libc_port_associate, uintptr(port), uintptr(source), object, uintptr(events), user))
|
||||
}
|
||||
|
||||
int32
|
||||
runtime·port_getn(int32 port, PortEvent *evs, uint32 max, uint32 *nget, Timespec *timeout)
|
||||
{
|
||||
return runtime·sysvicall5(libc·port_getn, (uintptr)port, (uintptr)evs, (uintptr)max, (uintptr)nget, (uintptr)timeout);
|
||||
func port_dissociate(port, source int32, object uintptr) int32 {
|
||||
return int32(sysvicall3(libc_port_dissociate, uintptr(port), uintptr(source), object))
|
||||
}
|
||||
|
||||
static int32 portfd = -1;
|
||||
func port_getn(port int32, evs *portevent, max uint32, nget *uint32, timeout *timespec) int32 {
|
||||
return int32(sysvicall5(libc_port_getn, uintptr(port), uintptr(unsafe.Pointer(evs)), uintptr(max), uintptr(unsafe.Pointer(nget)), uintptr(unsafe.Pointer(timeout))))
|
||||
}
|
||||
|
||||
void
|
||||
runtime·netpollinit(void)
|
||||
{
|
||||
if((portfd = runtime·port_create()) >= 0) {
|
||||
runtime·fcntl(portfd, F_SETFD, FD_CLOEXEC);
|
||||
return;
|
||||
var portfd int32 = -1
|
||||
|
||||
func netpollinit() {
|
||||
portfd = port_create()
|
||||
if portfd >= 0 {
|
||||
fcntl(portfd, _F_SETFD, _FD_CLOEXEC)
|
||||
return
|
||||
}
|
||||
|
||||
runtime·printf("netpollinit: failed to create port (%d)\n", errno);
|
||||
runtime·throw("netpollinit: failed to create port");
|
||||
print("netpollinit: failed to create port (", errno(), ")\n")
|
||||
gothrow("netpollinit: failed to create port")
|
||||
}
|
||||
|
||||
int32
|
||||
runtime·netpollopen(uintptr fd, PollDesc *pd)
|
||||
{
|
||||
int32 r;
|
||||
|
||||
runtime·netpolllock(pd);
|
||||
func netpollopen(fd uintptr, pd *pollDesc) int32 {
|
||||
lock(&pd.lock)
|
||||
// We don't register for any specific type of events yet, that's
|
||||
// netpollarm's job. We merely ensure we call port_associate before
|
||||
// asynchonous connect/accept completes, so when we actually want
|
||||
// to do any I/O, the call to port_associate (from netpollarm,
|
||||
// with the interested event set) will unblock port_getn right away
|
||||
// because of the I/O readiness notification.
|
||||
*runtime·netpolluser(pd) = 0;
|
||||
r = runtime·port_associate(portfd, PORT_SOURCE_FD, fd, 0, (uintptr)pd);
|
||||
runtime·netpollunlock(pd);
|
||||
return r;
|
||||
pd.user = 0
|
||||
r := port_associate(portfd, _PORT_SOURCE_FD, fd, 0, uintptr(unsafe.Pointer(pd)))
|
||||
unlock(&pd.lock)
|
||||
return r
|
||||
}
|
||||
|
||||
int32
|
||||
runtime·netpollclose(uintptr fd)
|
||||
{
|
||||
return runtime·port_dissociate(portfd, PORT_SOURCE_FD, fd);
|
||||
func netpollclose(fd uintptr) int32 {
|
||||
return port_dissociate(portfd, _PORT_SOURCE_FD, fd)
|
||||
}
|
||||
|
||||
// Updates the association with a new set of interested events. After
|
||||
// this call, port_getn will return one and only one event for that
|
||||
// particular descriptor, so this function needs to be called again.
|
||||
void
|
||||
runtime·netpollupdate(PollDesc* pd, uint32 set, uint32 clear)
|
||||
{
|
||||
uint32 *ep, old, events;
|
||||
uintptr fd = runtime·netpollfd(pd);
|
||||
ep = (uint32*)runtime·netpolluser(pd);
|
||||
func netpollupdate(pd *pollDesc, set, clear uint32) {
|
||||
if pd.closing {
|
||||
return
|
||||
}
|
||||
|
||||
if(runtime·netpollclosing(pd))
|
||||
return;
|
||||
old := pd.user
|
||||
events := (old & ^clear) | set
|
||||
if old == events {
|
||||
return
|
||||
}
|
||||
|
||||
old = *ep;
|
||||
events = (old & ~clear) | set;
|
||||
if(old == events)
|
||||
return;
|
||||
|
||||
if(events && runtime·port_associate(portfd, PORT_SOURCE_FD, fd, events, (uintptr)pd) != 0) {
|
||||
runtime·printf("netpollupdate: failed to associate (%d)\n", errno);
|
||||
runtime·throw("netpollupdate: failed to associate");
|
||||
}
|
||||
*ep = events;
|
||||
if events != 0 && port_associate(portfd, _PORT_SOURCE_FD, pd.fd, events, uintptr(unsafe.Pointer(pd))) != 0 {
|
||||
print("netpollupdate: failed to associate (", errno(), ")\n")
|
||||
gothrow("netpollupdate: failed to associate")
|
||||
}
|
||||
pd.user = events
|
||||
}
|
||||
|
||||
// subscribe the fd to the port such that port_getn will return one event.
|
||||
void
|
||||
runtime·netpollarm(PollDesc* pd, int32 mode)
|
||||
{
|
||||
runtime·netpolllock(pd);
|
||||
switch(mode) {
|
||||
func netpollarm(pd *pollDesc, mode int) {
|
||||
lock(&pd.lock)
|
||||
switch mode {
|
||||
case 'r':
|
||||
runtime·netpollupdate(pd, POLLIN, 0);
|
||||
break;
|
||||
netpollupdate(pd, _POLLIN, 0)
|
||||
case 'w':
|
||||
runtime·netpollupdate(pd, POLLOUT, 0);
|
||||
break;
|
||||
netpollupdate(pd, _POLLOUT, 0)
|
||||
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
|
||||
// returns list of goroutines that become runnable
|
||||
G*
|
||||
runtime·netpoll(bool block)
|
||||
{
|
||||
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) {
|
||||
zero.tv_sec = 0;
|
||||
zero.tv_nsec = 0;
|
||||
wait = &zero;
|
||||
func netpoll(block bool) (gp *g) {
|
||||
if portfd == -1 {
|
||||
return
|
||||
}
|
||||
|
||||
var wait *timespec
|
||||
var zero timespec
|
||||
if !block {
|
||||
wait = &zero
|
||||
}
|
||||
|
||||
var events [128]portevent
|
||||
retry:
|
||||
n = 1;
|
||||
if(runtime·port_getn(portfd, events, nelem(events), &n, wait) < 0) {
|
||||
if(errno != EINTR && errno != lasterr) {
|
||||
lasterr = errno;
|
||||
runtime·printf("runtime: port_getn on fd %d failed with %d\n", portfd, errno);
|
||||
var n uint32 = 1
|
||||
if port_getn(portfd, &events[0], uint32(len(events)), &n, wait) < 0 {
|
||||
if e := errno(); e != _EINTR && e != netpolllasterr {
|
||||
netpolllasterr = e
|
||||
print("runtime: port_getn on fd ", portfd, " failed with ", e, "\n")
|
||||
}
|
||||
goto retry;
|
||||
goto retry
|
||||
}
|
||||
|
||||
gp = nil;
|
||||
for(i = 0; i < n; i++) {
|
||||
ev = &events[i];
|
||||
gp = nil
|
||||
for i := 0; i < int(n); i++ {
|
||||
ev := &events[i]
|
||||
|
||||
if(ev->portev_events == 0)
|
||||
continue;
|
||||
pd = (PollDesc *)ev->portev_user;
|
||||
|
||||
mode = 0;
|
||||
clear = 0;
|
||||
if(ev->portev_events & (POLLIN|POLLHUP|POLLERR)) {
|
||||
mode += 'r';
|
||||
clear |= POLLIN;
|
||||
if ev.portev_events == 0 {
|
||||
continue
|
||||
}
|
||||
if(ev->portev_events & (POLLOUT|POLLHUP|POLLERR)) {
|
||||
mode += 'w';
|
||||
clear |= POLLOUT;
|
||||
pd := (*pollDesc)(unsafe.Pointer(ev.portev_user))
|
||||
|
||||
var mode, clear int32
|
||||
if (ev.portev_events & (_POLLIN | _POLLHUP | _POLLERR)) != 0 {
|
||||
mode += 'r'
|
||||
clear |= _POLLIN
|
||||
}
|
||||
if (ev.portev_events & (_POLLOUT | _POLLHUP | _POLLERR)) != 0 {
|
||||
mode += 'w'
|
||||
clear |= _POLLOUT
|
||||
}
|
||||
// To effect edge-triggered events, we need to be sure to
|
||||
// update our association with whatever events were not
|
||||
@ -248,17 +225,19 @@ retry:
|
||||
// for POLLIN|POLLOUT, and we get POLLIN, besides waking
|
||||
// the goroutine interested in POLLIN we have to not forget
|
||||
// about the one interested in POLLOUT.
|
||||
if(clear != 0) {
|
||||
runtime·netpolllock(pd);
|
||||
runtime·netpollupdate(pd, 0, clear);
|
||||
runtime·netpollunlock(pd);
|
||||
if clear != 0 {
|
||||
lock(&pd.lock)
|
||||
netpollupdate(pd, 0, uint32(clear))
|
||||
unlock(&pd.lock)
|
||||
}
|
||||
|
||||
if(mode)
|
||||
runtime·netpollready(&gp, pd, mode);
|
||||
if mode != 0 {
|
||||
netpollready((**g)(noescape(unsafe.Pointer(&gp))), pd, mode)
|
||||
}
|
||||
}
|
||||
|
||||
if(block && gp == nil)
|
||||
goto retry;
|
||||
return gp;
|
||||
if block && gp == nil {
|
||||
goto retry
|
||||
}
|
||||
return gp
|
||||
}
|
13
src/runtime/os2_solaris.go
Normal file
13
src/runtime/os2_solaris.go
Normal file
@ -0,0 +1,13 @@
|
||||
// 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
|
||||
)
|
493
src/runtime/os3_solaris.go
Normal file
493
src/runtime/os3_solaris.go
Normal file
@ -0,0 +1,493 @@
|
||||
// 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()
|
||||
}
|
@ -1,557 +0,0 @@
|
||||
// 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
|
||||
|
||||
import "unsafe"
|
||||
|
||||
func setitimer(mode int32, new, old unsafe.Pointer)
|
||||
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
|
||||
type libcFunc uintptr
|
||||
|
||||
var asmsysvicall6 libcFunc
|
||||
|
||||
//go:nosplit
|
||||
func sysvicall0(fn *libcFunc) uintptr {
|
||||
func sysvicall0(fn libcFunc) uintptr {
|
||||
libcall := &getg().m.libcall
|
||||
libcall.fn = uintptr(unsafe.Pointer(fn))
|
||||
libcall.fn = uintptr(fn)
|
||||
libcall.n = 0
|
||||
// TODO(rsc): Why is noescape necessary here and below?
|
||||
libcall.args = uintptr(noescape(unsafe.Pointer(&fn))) // it's unused but must be non-nil, otherwise crashes
|
||||
libcall.args = uintptr(fn) // it's unused but must be non-nil, otherwise crashes
|
||||
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
|
||||
return libcall.r1
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func sysvicall1(fn *libcFunc, a1 uintptr) uintptr {
|
||||
func sysvicall1(fn libcFunc, a1 uintptr) uintptr {
|
||||
libcall := &getg().m.libcall
|
||||
libcall.fn = uintptr(unsafe.Pointer(fn))
|
||||
libcall.fn = uintptr(fn)
|
||||
libcall.n = 1
|
||||
// TODO(rsc): Why is noescape necessary here and below?
|
||||
libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
|
||||
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
|
||||
return libcall.r1
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func sysvicall2(fn *libcFunc, a1, a2 uintptr) uintptr {
|
||||
func sysvicall2(fn libcFunc, a1, a2 uintptr) uintptr {
|
||||
libcall := &getg().m.libcall
|
||||
libcall.fn = uintptr(unsafe.Pointer(fn))
|
||||
libcall.fn = uintptr(fn)
|
||||
libcall.n = 2
|
||||
libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
|
||||
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
|
||||
@ -60,9 +42,9 @@ func sysvicall2(fn *libcFunc, a1, a2 uintptr) uintptr {
|
||||
}
|
||||
|
||||
//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.fn = uintptr(unsafe.Pointer(fn))
|
||||
libcall.fn = uintptr(fn)
|
||||
libcall.n = 3
|
||||
libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
|
||||
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
|
||||
@ -70,9 +52,9 @@ func sysvicall3(fn *libcFunc, a1, a2, a3 uintptr) uintptr {
|
||||
}
|
||||
|
||||
//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.fn = uintptr(unsafe.Pointer(fn))
|
||||
libcall.fn = uintptr(fn)
|
||||
libcall.n = 4
|
||||
libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
|
||||
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
|
||||
@ -80,9 +62,9 @@ func sysvicall4(fn *libcFunc, a1, a2, a3, a4 uintptr) uintptr {
|
||||
}
|
||||
|
||||
//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.fn = uintptr(unsafe.Pointer(fn))
|
||||
libcall.fn = uintptr(fn)
|
||||
libcall.n = 5
|
||||
libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
|
||||
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
|
||||
@ -90,9 +72,9 @@ func sysvicall5(fn *libcFunc, a1, a2, a3, a4, a5 uintptr) uintptr {
|
||||
}
|
||||
|
||||
//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.fn = uintptr(unsafe.Pointer(fn))
|
||||
libcall.fn = uintptr(fn)
|
||||
libcall.n = 6
|
||||
libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
|
||||
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
|
||||
|
@ -1,55 +0,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.
|
||||
|
||||
|
||||
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);
|
88
src/runtime/signal_solaris.go
Normal file
88
src/runtime/signal_solaris.go
Normal file
@ -0,0 +1,88 @@
|
||||
// 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"},
|
||||
}
|
46
src/runtime/signal_solaris_amd64.go
Normal file
46
src/runtime/signal_solaris_amd64.go
Normal file
@ -0,0 +1,46 @@
|
||||
// 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)
|
||||
}
|
@ -1,31 +0,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.
|
||||
|
||||
#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])
|
@ -1,97 +0,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 {
|
||||
func cgocallback(fn, frame unsafe.Pointer, framesize uintptr)
|
||||
func gogo(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
|
||||
|
||||
//go:noescape
|
||||
@ -105,22 +103,13 @@ func jmpdefer(fv *funcval, argp uintptr)
|
||||
func exit1(code int32)
|
||||
func asminit()
|
||||
func setg(gg *g)
|
||||
func exit(code int32)
|
||||
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 procyield(cycles uint32)
|
||||
func cgocallback_gofunc(fv *funcval, frame unsafe.Pointer, framesize uintptr)
|
||||
func goexit()
|
||||
|
||||
//go:noescape
|
||||
func write(fd uintptr, p unsafe.Pointer, n int32) int32
|
||||
|
||||
//go:noescape
|
||||
func cas(ptr *uint32, old, new uint32) bool
|
||||
|
||||
@ -195,9 +184,6 @@ func asmcgocall(fn, arg unsafe.Pointer)
|
||||
//go:noescape
|
||||
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.
|
||||
const _NoArgs = ^uintptr(0)
|
||||
|
||||
|
27
src/runtime/stubs2.go
Normal file
27
src/runtime/stubs2.go
Normal file
@ -0,0 +1,27 @@
|
||||
// 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 @@
|
||||
TEXT runtime·settls(SB),NOSPLIT,$8
|
||||
RET
|
||||
|
||||
// void libc·miniterrno(void *(*___errno)(void));
|
||||
// void libc_miniterrno(void *(*___errno)(void));
|
||||
//
|
||||
// Set the TLS errno pointer in M.
|
||||
//
|
||||
@ -41,7 +41,7 @@ TEXT runtime·nanotime1(SB),NOSPLIT,$0
|
||||
SUBQ $64, SP // 16 bytes will do, but who knows in the future?
|
||||
MOVQ $3, DI // CLOCK_REALTIME from <sys/time_impl.h>
|
||||
MOVQ SP, SI
|
||||
MOVQ libc·clock_gettime(SB), AX
|
||||
MOVQ libc_clock_gettime(SB), AX
|
||||
CALL AX
|
||||
MOVQ (SP), AX // tv_sec from struct timespec
|
||||
IMULQ $1000000000, AX // multiply into nanoseconds
|
||||
@ -54,7 +54,7 @@ TEXT runtime·nanotime1(SB),NOSPLIT,$0
|
||||
TEXT runtime·pipe1(SB),NOSPLIT,$0
|
||||
SUBQ $16, SP // 8 bytes will do, but stack has to be 16-byte alligned
|
||||
MOVQ SP, DI
|
||||
MOVQ libc·pipe(SB), AX
|
||||
MOVQ libc_pipe(SB), AX
|
||||
CALL AX
|
||||
MOVL 0(SP), AX
|
||||
MOVL 4(SP), DX
|
||||
@ -133,7 +133,7 @@ TEXT runtime·tstart_sysvicall(SB),NOSPLIT,$0
|
||||
MOVQ AX, (g_stack+stack_hi)(DX)
|
||||
SUBQ $(0x100000), AX // stack size
|
||||
MOVQ AX, (g_stack+stack_lo)(DX)
|
||||
ADDQ $const_StackGuard, AX
|
||||
ADDQ $const__StackGuard, AX
|
||||
MOVQ AX, g_stackguard0(DX)
|
||||
MOVQ AX, g_stackguard1(DX)
|
||||
|
||||
@ -321,13 +321,13 @@ usleep1_noswitch:
|
||||
|
||||
// Runs on OS stack. duration (in µs units) is in DI.
|
||||
TEXT runtime·usleep2(SB),NOSPLIT,$0
|
||||
MOVQ libc·usleep(SB), AX
|
||||
MOVQ libc_usleep(SB), AX
|
||||
CALL AX
|
||||
RET
|
||||
|
||||
// Runs on OS stack, called from runtime·osyield.
|
||||
TEXT runtime·osyield1(SB),NOSPLIT,$0
|
||||
MOVQ libc·sched_yield(SB), AX
|
||||
MOVQ libc_sched_yield(SB), AX
|
||||
CALL AX
|
||||
RET
|
||||
|
||||
|
47
src/runtime/syscall2_solaris.go
Normal file
47
src/runtime/syscall2_solaris.go
Normal file
@ -0,0 +1,47 @@
|
||||
// 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
|
@ -1,23 +0,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.
|
||||
|
||||
#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"
|
||||
var (
|
||||
libc_chdir,
|
||||
libc_chroot,
|
||||
libc_close,
|
||||
libc_dlopen,
|
||||
libc_dlclose,
|
||||
libc_dlsym,
|
||||
libc_execve,
|
||||
libc_exit,
|
||||
libc_fcntl,
|
||||
libc_forkx,
|
||||
libc_gethostname,
|
||||
@ -27,7 +25,6 @@ var (
|
||||
libc_setpgid,
|
||||
libc_syscall,
|
||||
libc_wait4,
|
||||
libc_write,
|
||||
pipe1 libcFunc
|
||||
)
|
||||
|
||||
@ -38,9 +35,9 @@ func syscall_sysvicall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err
|
||||
n: nargs,
|
||||
args: uintptr(unsafe.Pointer(&a1)),
|
||||
}
|
||||
entersyscallblock()
|
||||
entersyscallblock(0)
|
||||
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
|
||||
exitsyscall()
|
||||
exitsyscall(0)
|
||||
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
|
||||
//go:nosplit
|
||||
func syscall_chdir(path uintptr) (err uintptr) {
|
||||
call := libcall{
|
||||
fn: uintptr(unsafe.Pointer(&libc_chdir)),
|
||||
fn: uintptr(unsafe.Pointer(libc_chdir)),
|
||||
n: 1,
|
||||
args: uintptr(unsafe.Pointer(&path)),
|
||||
}
|
||||
@ -73,7 +70,7 @@ func syscall_chdir(path uintptr) (err uintptr) {
|
||||
//go:nosplit
|
||||
func syscall_chroot(path uintptr) (err uintptr) {
|
||||
call := libcall{
|
||||
fn: uintptr(unsafe.Pointer(&libc_chroot)),
|
||||
fn: uintptr(unsafe.Pointer(libc_chroot)),
|
||||
n: 1,
|
||||
args: uintptr(unsafe.Pointer(&path)),
|
||||
}
|
||||
@ -84,18 +81,18 @@ func syscall_chroot(path uintptr) (err uintptr) {
|
||||
// like close, but must not split stack, for forkx.
|
||||
//go:nosplit
|
||||
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) {
|
||||
call := libcall{
|
||||
fn: uintptr(unsafe.Pointer(&libc_dlopen)),
|
||||
fn: uintptr(unsafe.Pointer(libc_dlopen)),
|
||||
n: 2,
|
||||
args: uintptr(unsafe.Pointer(&name)),
|
||||
}
|
||||
entersyscallblock()
|
||||
entersyscallblock(0)
|
||||
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
|
||||
exitsyscall()
|
||||
exitsyscall(0)
|
||||
if call.r1 == 0 {
|
||||
return call.r1, call.err
|
||||
}
|
||||
@ -104,25 +101,25 @@ func syscall_dlopen(name *byte, mode uintptr) (handle uintptr, err uintptr) {
|
||||
|
||||
func syscall_dlclose(handle uintptr) (err uintptr) {
|
||||
call := libcall{
|
||||
fn: uintptr(unsafe.Pointer(&libc_dlclose)),
|
||||
fn: uintptr(unsafe.Pointer(libc_dlclose)),
|
||||
n: 1,
|
||||
args: uintptr(unsafe.Pointer(&handle)),
|
||||
}
|
||||
entersyscallblock()
|
||||
entersyscallblock(0)
|
||||
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
|
||||
exitsyscall()
|
||||
exitsyscall(0)
|
||||
return call.r1
|
||||
}
|
||||
|
||||
func syscall_dlsym(handle uintptr, name *byte) (proc uintptr, err uintptr) {
|
||||
call := libcall{
|
||||
fn: uintptr(unsafe.Pointer(&libc_dlsym)),
|
||||
fn: uintptr(unsafe.Pointer(libc_dlsym)),
|
||||
n: 2,
|
||||
args: uintptr(unsafe.Pointer(&handle)),
|
||||
}
|
||||
entersyscallblock()
|
||||
entersyscallblock(0)
|
||||
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
|
||||
exitsyscall()
|
||||
exitsyscall(0)
|
||||
if call.r1 == 0 {
|
||||
return call.r1, call.err
|
||||
}
|
||||
@ -132,7 +129,7 @@ func syscall_dlsym(handle uintptr, name *byte) (proc uintptr, err uintptr) {
|
||||
//go:nosplit
|
||||
func syscall_execve(path, argv, envp uintptr) (err uintptr) {
|
||||
call := libcall{
|
||||
fn: uintptr(unsafe.Pointer(&libc_execve)),
|
||||
fn: uintptr(unsafe.Pointer(libc_execve)),
|
||||
n: 3,
|
||||
args: uintptr(unsafe.Pointer(&path)),
|
||||
}
|
||||
@ -143,13 +140,13 @@ func syscall_execve(path, argv, envp uintptr) (err uintptr) {
|
||||
// like exit, but must not split stack, for forkx.
|
||||
//go:nosplit
|
||||
func syscall_exit(code uintptr) {
|
||||
sysvicall1(&libc_exit, code)
|
||||
sysvicall1(libc_exit, code)
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func syscall_fcntl(fd, cmd, arg uintptr) (val, err uintptr) {
|
||||
call := libcall{
|
||||
fn: uintptr(unsafe.Pointer(&libc_fcntl)),
|
||||
fn: uintptr(unsafe.Pointer(libc_fcntl)),
|
||||
n: 3,
|
||||
args: uintptr(unsafe.Pointer(&fd)),
|
||||
}
|
||||
@ -160,7 +157,7 @@ func syscall_fcntl(fd, cmd, arg uintptr) (val, err uintptr) {
|
||||
//go:nosplit
|
||||
func syscall_forkx(flags uintptr) (pid uintptr, err uintptr) {
|
||||
call := libcall{
|
||||
fn: uintptr(unsafe.Pointer(&libc_forkx)),
|
||||
fn: uintptr(unsafe.Pointer(libc_forkx)),
|
||||
n: 1,
|
||||
args: uintptr(unsafe.Pointer(&flags)),
|
||||
}
|
||||
@ -172,13 +169,13 @@ func syscall_gethostname() (name string, err uintptr) {
|
||||
cname := new([_MAXHOSTNAMELEN]byte)
|
||||
var args = [2]uintptr{uintptr(unsafe.Pointer(&cname[0])), _MAXHOSTNAMELEN}
|
||||
call := libcall{
|
||||
fn: uintptr(unsafe.Pointer(&libc_gethostname)),
|
||||
fn: uintptr(unsafe.Pointer(libc_gethostname)),
|
||||
n: 2,
|
||||
args: uintptr(unsafe.Pointer(&args[0])),
|
||||
}
|
||||
entersyscallblock()
|
||||
entersyscallblock(0)
|
||||
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
|
||||
exitsyscall()
|
||||
exitsyscall(0)
|
||||
if call.r1 != 0 {
|
||||
return "", call.err
|
||||
}
|
||||
@ -189,7 +186,7 @@ func syscall_gethostname() (name string, err uintptr) {
|
||||
//go:nosplit
|
||||
func syscall_ioctl(fd, req, arg uintptr) (err uintptr) {
|
||||
call := libcall{
|
||||
fn: uintptr(unsafe.Pointer(&libc_ioctl)),
|
||||
fn: uintptr(unsafe.Pointer(libc_ioctl)),
|
||||
n: 3,
|
||||
args: uintptr(unsafe.Pointer(&fd)),
|
||||
}
|
||||
@ -203,9 +200,9 @@ func syscall_pipe() (r, w, err uintptr) {
|
||||
n: 0,
|
||||
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))
|
||||
exitsyscall()
|
||||
exitsyscall(0)
|
||||
return call.r1, call.r2, call.err
|
||||
}
|
||||
|
||||
@ -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.
|
||||
func syscall_rawsyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
|
||||
call := libcall{
|
||||
fn: uintptr(unsafe.Pointer(&libc_syscall)),
|
||||
fn: uintptr(unsafe.Pointer(libc_syscall)),
|
||||
n: 4,
|
||||
args: uintptr(unsafe.Pointer(&trap)),
|
||||
}
|
||||
@ -228,7 +225,7 @@ func syscall_rawsyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
|
||||
//go:nosplit
|
||||
func syscall_setgid(gid uintptr) (err uintptr) {
|
||||
call := libcall{
|
||||
fn: uintptr(unsafe.Pointer(&libc_setgid)),
|
||||
fn: uintptr(unsafe.Pointer(libc_setgid)),
|
||||
n: 1,
|
||||
args: uintptr(unsafe.Pointer(&gid)),
|
||||
}
|
||||
@ -239,7 +236,7 @@ func syscall_setgid(gid uintptr) (err uintptr) {
|
||||
//go:nosplit
|
||||
func syscall_setgroups(ngid, gid uintptr) (err uintptr) {
|
||||
call := libcall{
|
||||
fn: uintptr(unsafe.Pointer(&libc_setgroups)),
|
||||
fn: uintptr(unsafe.Pointer(libc_setgroups)),
|
||||
n: 2,
|
||||
args: uintptr(unsafe.Pointer(&ngid)),
|
||||
}
|
||||
@ -250,9 +247,9 @@ func syscall_setgroups(ngid, gid uintptr) (err uintptr) {
|
||||
//go:nosplit
|
||||
func syscall_setsid() (pid, err uintptr) {
|
||||
call := libcall{
|
||||
fn: uintptr(unsafe.Pointer(&libc_setsid)),
|
||||
fn: uintptr(unsafe.Pointer(libc_setsid)),
|
||||
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))
|
||||
return call.r1, call.err
|
||||
@ -261,7 +258,7 @@ func syscall_setsid() (pid, err uintptr) {
|
||||
//go:nosplit
|
||||
func syscall_setuid(uid uintptr) (err uintptr) {
|
||||
call := libcall{
|
||||
fn: uintptr(unsafe.Pointer(&libc_setuid)),
|
||||
fn: uintptr(unsafe.Pointer(libc_setuid)),
|
||||
n: 1,
|
||||
args: uintptr(unsafe.Pointer(&uid)),
|
||||
}
|
||||
@ -272,7 +269,7 @@ func syscall_setuid(uid uintptr) (err uintptr) {
|
||||
//go:nosplit
|
||||
func syscall_setpgid(pid, pgid uintptr) (err uintptr) {
|
||||
call := libcall{
|
||||
fn: uintptr(unsafe.Pointer(&libc_setpgid)),
|
||||
fn: uintptr(unsafe.Pointer(libc_setpgid)),
|
||||
n: 2,
|
||||
args: uintptr(unsafe.Pointer(&pid)),
|
||||
}
|
||||
@ -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.
|
||||
func syscall_syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
|
||||
call := libcall{
|
||||
fn: uintptr(unsafe.Pointer(&libc_syscall)),
|
||||
fn: uintptr(unsafe.Pointer(libc_syscall)),
|
||||
n: 4,
|
||||
args: uintptr(unsafe.Pointer(&trap)),
|
||||
}
|
||||
entersyscallblock()
|
||||
entersyscallblock(0)
|
||||
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
|
||||
exitsyscall()
|
||||
exitsyscall(0)
|
||||
return call.r1, call.r2, call.err
|
||||
}
|
||||
|
||||
func syscall_wait4(pid uintptr, wstatus *uint32, options uintptr, rusage unsafe.Pointer) (wpid int, err uintptr) {
|
||||
call := libcall{
|
||||
fn: uintptr(unsafe.Pointer(&libc_wait4)),
|
||||
fn: uintptr(unsafe.Pointer(libc_wait4)),
|
||||
n: 4,
|
||||
args: uintptr(unsafe.Pointer(&pid)),
|
||||
}
|
||||
entersyscallblock()
|
||||
entersyscallblock(0)
|
||||
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
|
||||
exitsyscall()
|
||||
exitsyscall(0)
|
||||
return int(call.r1), call.err
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func syscall_write(fd, buf, nbyte uintptr) (n, err uintptr) {
|
||||
call := libcall{
|
||||
fn: uintptr(unsafe.Pointer(&libc_write)),
|
||||
fn: uintptr(unsafe.Pointer(libc_write)),
|
||||
n: 3,
|
||||
args: uintptr(unsafe.Pointer(&fd)),
|
||||
}
|
||||
|
@ -1,89 +0,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.
|
||||
|
||||
// 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
|
Loading…
x
Reference in New Issue
Block a user