summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cmd/dist/buildruntime.c11
-rw-r--r--src/pkg/runtime/arch_amd64.h4
-rw-r--r--src/pkg/runtime/asm_amd64.s11
-rw-r--r--src/pkg/runtime/cgocall.c2
-rw-r--r--src/pkg/runtime/defs_solaris.go156
-rw-r--r--src/pkg/runtime/defs_solaris_amd64.go48
-rw-r--r--src/pkg/runtime/defs_solaris_amd64.h254
-rw-r--r--src/pkg/runtime/env_posix.c2
-rw-r--r--src/pkg/runtime/lfstack.c14
-rw-r--r--src/pkg/runtime/lock_sema.c2
-rw-r--r--src/pkg/runtime/mem_solaris.c90
-rw-r--r--src/pkg/runtime/netpoll.goc14
-rw-r--r--src/pkg/runtime/os_solaris.c579
-rw-r--r--src/pkg/runtime/os_solaris.h51
-rw-r--r--src/pkg/runtime/os_windows.c10
-rw-r--r--src/pkg/runtime/proc.c4
-rw-r--r--src/pkg/runtime/rt0_solaris_amd64.s18
-rw-r--r--src/pkg/runtime/runtime.c1
-rw-r--r--src/pkg/runtime/runtime.h32
-rw-r--r--src/pkg/runtime/signal_amd64.c2
-rw-r--r--src/pkg/runtime/signal_solaris_amd64.h31
-rw-r--r--src/pkg/runtime/signal_unix.c2
-rw-r--r--src/pkg/runtime/signals_solaris.h94
-rw-r--r--src/pkg/runtime/sys_solaris_amd64.s267
-rw-r--r--src/pkg/runtime/sys_windows_386.s12
-rw-r--r--src/pkg/runtime/sys_windows_amd64.s10
-rw-r--r--src/pkg/runtime/syscall_solaris.goc374
-rw-r--r--src/pkg/runtime/syscall_windows.goc14
28 files changed, 2071 insertions, 38 deletions
diff --git a/src/cmd/dist/buildruntime.c b/src/cmd/dist/buildruntime.c
index e6e309d92..1babddaad 100644
--- a/src/cmd/dist/buildruntime.c
+++ b/src/cmd/dist/buildruntime.c
@@ -178,7 +178,7 @@ static struct {
"#define g(r) 0(GS)\n"
"#define m(r) 4(GS)\n"
},
-
+
{"amd64", "windows",
"#define get_tls(r) MOVQ 0x28(GS), r\n"
"#define g(r) 0(r)\n"
@@ -190,6 +190,11 @@ static struct {
"#define m(r) 8(GS)\n"
"#define procid(r) 16(GS)\n"
},
+ {"amd64", "solaris",
+ "#define get_tls(r) MOVQ 0(FS), r\n"
+ "#define g(r) -16(r)(FS*1)\n"
+ "#define m(r) -8(r)(FS*1)\n"
+ },
// The TLS accessors here are defined here to use initial exec model.
// If the linker is not outputting a shared library, it will reduce
// the TLS accessors to the local exec model, effectively removing
@@ -284,8 +289,8 @@ ok:
aggr = "p";
else if(streq(fields.p[1], "Gobuf"))
aggr = "gobuf";
- else if(streq(fields.p[1], "WinCall"))
- aggr = "wincall";
+ else if(streq(fields.p[1], "LibCall"))
+ aggr = "libcall";
else if(streq(fields.p[1], "WinCallbackContext"))
aggr = "cbctxt";
else if(streq(fields.p[1], "SEH"))
diff --git a/src/pkg/runtime/arch_amd64.h b/src/pkg/runtime/arch_amd64.h
index 2bddf0796..171839481 100644
--- a/src/pkg/runtime/arch_amd64.h
+++ b/src/pkg/runtime/arch_amd64.h
@@ -6,6 +6,10 @@ enum {
thechar = '6',
BigEndian = 0,
CacheLineSize = 64,
+#ifdef GOOS_solaris
+ RuntimeGogoBytes = 80,
+#else
RuntimeGogoBytes = 64,
+#endif
PCQuantum = 1
};
diff --git a/src/pkg/runtime/asm_amd64.s b/src/pkg/runtime/asm_amd64.s
index 2c2ffedd1..980bcd452 100644
--- a/src/pkg/runtime/asm_amd64.s
+++ b/src/pkg/runtime/asm_amd64.s
@@ -53,6 +53,9 @@ needtls:
// skip TLS setup on Plan 9
CMPL runtime·isplan9(SB), $1
JEQ ok
+ // skip TLS setup on Solaris
+ CMPL runtime·issolaris(SB), $1
+ JEQ ok
LEAQ runtime·tls0(SB), DI
CALL runtime·settls(SB)
@@ -614,10 +617,16 @@ TEXT runtime·asmcgocall(SB),NOSPLIT,$0-16
MOVQ m_g0(BP), SI
MOVQ g(CX), DI
CMPQ SI, DI
- JEQ 4(PC)
+ JEQ nosave
+ MOVQ m_gsignal(BP), SI
+ CMPQ SI, DI
+ JEQ nosave
+
+ MOVQ m_g0(BP), SI
CALL gosave<>(SB)
MOVQ SI, g(CX)
MOVQ (g_sched+gobuf_sp)(SI), SP
+nosave:
// Now on a scheduling stack (a pthread-created stack).
// Make sure we have enough room for 4 stack-backed fast-call
diff --git a/src/pkg/runtime/cgocall.c b/src/pkg/runtime/cgocall.c
index 2a04453fd..6b2ae59dd 100644
--- a/src/pkg/runtime/cgocall.c
+++ b/src/pkg/runtime/cgocall.c
@@ -104,7 +104,7 @@ runtime·cgocall(void (*fn)(void*), void *arg)
return;
}
- if(!runtime·iscgo && !Windows)
+ if(!runtime·iscgo && !Solaris && !Windows)
runtime·throw("cgocall unavailable");
if(fn == 0)
diff --git a/src/pkg/runtime/defs_solaris.go b/src/pkg/runtime/defs_solaris.go
new file mode 100644
index 000000000..8dcbb08b7
--- /dev/null
+++ b/src/pkg/runtime/defs_solaris.go
@@ -0,0 +1,156 @@
+// Copyright 2009 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 ignore
+
+/*
+Input to cgo.
+
+GOARCH=amd64 go tool cgo -cdefs defs_solaris.go >defs_solaris_amd64.h
+*/
+
+package runtime
+
+/*
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/select.h>
+#include <sys/siginfo.h>
+#include <sys/signal.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/ucontext.h>
+#include <sys/regset.h>
+#include <sys/unistd.h>
+#include <sys/fork.h>
+#include <sys/port.h>
+#include <semaphore.h>
+#include <errno.h>
+#include <signal.h>
+#include <pthread.h>
+#include <netdb.h>
+*/
+import "C"
+
+const (
+ EINTR = C.EINTR
+ EBADF = C.EBADF
+ EFAULT = C.EFAULT
+ EAGAIN = C.EAGAIN
+ ETIMEDOUT = C.ETIMEDOUT
+ EWOULDBLOCK = C.EWOULDBLOCK
+ EINPROGRESS = C.EINPROGRESS
+
+ PROT_NONE = C.PROT_NONE
+ PROT_READ = C.PROT_READ
+ PROT_WRITE = C.PROT_WRITE
+ PROT_EXEC = C.PROT_EXEC
+
+ MAP_ANON = C.MAP_ANON
+ MAP_PRIVATE = C.MAP_PRIVATE
+ MAP_FIXED = C.MAP_FIXED
+
+ MADV_FREE = C.MADV_FREE
+
+ SA_SIGINFO = C.SA_SIGINFO
+ SA_RESTART = C.SA_RESTART
+ SA_ONSTACK = C.SA_ONSTACK
+
+ SIGHUP = C.SIGHUP
+ SIGINT = C.SIGINT
+ SIGQUIT = C.SIGQUIT
+ SIGILL = C.SIGILL
+ SIGTRAP = C.SIGTRAP
+ SIGABRT = C.SIGABRT
+ SIGEMT = C.SIGEMT
+ SIGFPE = C.SIGFPE
+ SIGKILL = C.SIGKILL
+ SIGBUS = C.SIGBUS
+ SIGSEGV = C.SIGSEGV
+ SIGSYS = C.SIGSYS
+ SIGPIPE = C.SIGPIPE
+ SIGALRM = C.SIGALRM
+ SIGTERM = C.SIGTERM
+ SIGURG = C.SIGURG
+ SIGSTOP = C.SIGSTOP
+ SIGTSTP = C.SIGTSTP
+ SIGCONT = C.SIGCONT
+ SIGCHLD = C.SIGCHLD
+ SIGTTIN = C.SIGTTIN
+ SIGTTOU = C.SIGTTOU
+ SIGIO = C.SIGIO
+ SIGXCPU = C.SIGXCPU
+ SIGXFSZ = C.SIGXFSZ
+ SIGVTALRM = C.SIGVTALRM
+ SIGPROF = C.SIGPROF
+ SIGWINCH = C.SIGWINCH
+ SIGUSR1 = C.SIGUSR1
+ SIGUSR2 = C.SIGUSR2
+
+ FPE_INTDIV = C.FPE_INTDIV
+ FPE_INTOVF = C.FPE_INTOVF
+ FPE_FLTDIV = C.FPE_FLTDIV
+ FPE_FLTOVF = C.FPE_FLTOVF
+ FPE_FLTUND = C.FPE_FLTUND
+ FPE_FLTRES = C.FPE_FLTRES
+ FPE_FLTINV = C.FPE_FLTINV
+ FPE_FLTSUB = C.FPE_FLTSUB
+
+ BUS_ADRALN = C.BUS_ADRALN
+ BUS_ADRERR = C.BUS_ADRERR
+ BUS_OBJERR = C.BUS_OBJERR
+
+ SEGV_MAPERR = C.SEGV_MAPERR
+ SEGV_ACCERR = C.SEGV_ACCERR
+
+ ITIMER_REAL = C.ITIMER_REAL
+ ITIMER_VIRTUAL = C.ITIMER_VIRTUAL
+ ITIMER_PROF = C.ITIMER_PROF
+
+ _SC_NPROCESSORS_ONLN = C._SC_NPROCESSORS_ONLN
+
+ PTHREAD_CREATE_DETACHED = C.PTHREAD_CREATE_DETACHED
+
+ FORK_NOSIGCHLD = C.FORK_NOSIGCHLD
+ FORK_WAITPID = C.FORK_WAITPID
+
+ MAXHOSTNAMELEN = C.MAXHOSTNAMELEN
+
+ O_NONBLOCK = C.O_NONBLOCK
+ FD_CLOEXEC = C.FD_CLOEXEC
+ F_GETFL = C.F_GETFL
+ F_SETFL = C.F_SETFL
+ F_SETFD = C.F_SETFD
+
+ POLLIN = C.POLLIN
+ POLLOUT = C.POLLOUT
+ POLLHUP = C.POLLHUP
+ POLLERR = C.POLLERR
+
+ PORT_SOURCE_FD = C.PORT_SOURCE_FD
+)
+
+type SemT C.sem_t
+
+type Sigaltstack C.struct_sigaltstack
+type Sigset C.sigset_t
+type StackT C.stack_t
+
+type Siginfo C.siginfo_t
+type Sigaction C.struct_sigaction
+
+type Fpregset C.fpregset_t
+type Mcontext C.mcontext_t
+type Ucontext C.ucontext_t
+
+type Timespec C.struct_timespec
+type Timeval C.struct_timeval
+type Itimerval C.struct_itimerval
+
+type PortEvent C.port_event_t
+type Pthread C.pthread_t
+type PthreadAttr C.pthread_attr_t
+
+// depends on Timespec, must appear below
+type Stat C.struct_stat
diff --git a/src/pkg/runtime/defs_solaris_amd64.go b/src/pkg/runtime/defs_solaris_amd64.go
new file mode 100644
index 000000000..f0265de93
--- /dev/null
+++ b/src/pkg/runtime/defs_solaris_amd64.go
@@ -0,0 +1,48 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+/*
+Input to cgo.
+
+GOARCH=amd64 go tool cgo -cdefs defs_solaris.go defs_solaris_amd64.go >defs_solaris_amd64.h
+*/
+
+package runtime
+
+/*
+#include <sys/types.h>
+#include <sys/regset.h>
+*/
+import "C"
+
+const (
+ REG_RDI = C.REG_RDI
+ REG_RSI = C.REG_RSI
+ REG_RDX = C.REG_RDX
+ REG_RCX = C.REG_RCX
+ REG_R8 = C.REG_R8
+ REG_R9 = C.REG_R9
+ REG_R10 = C.REG_R10
+ REG_R11 = C.REG_R11
+ REG_R12 = C.REG_R12
+ REG_R13 = C.REG_R13
+ REG_R14 = C.REG_R14
+ REG_R15 = C.REG_R15
+ REG_RBP = C.REG_RBP
+ REG_RBX = C.REG_RBX
+ REG_RAX = C.REG_RAX
+ REG_GS = C.REG_GS
+ REG_FS = C.REG_FS
+ REG_ES = C.REG_ES
+ REG_DS = C.REG_DS
+ REG_TRAPNO = C.REG_TRAPNO
+ REG_ERR = C.REG_ERR
+ REG_RIP = C.REG_RIP
+ REG_CS = C.REG_CS
+ REG_RFLAGS = C.REG_RFL
+ REG_RSP = C.REG_RSP
+ REG_SS = C.REG_SS
+)
diff --git a/src/pkg/runtime/defs_solaris_amd64.h b/src/pkg/runtime/defs_solaris_amd64.h
new file mode 100644
index 000000000..799724fad
--- /dev/null
+++ b/src/pkg/runtime/defs_solaris_amd64.h
@@ -0,0 +1,254 @@
+// Created by cgo -cdefs - DO NOT EDIT
+// cgo -cdefs defs_solaris.go defs_solaris_amd64.go
+
+
+enum {
+ EINTR = 0x4,
+ EBADF = 0x9,
+ EFAULT = 0xe,
+ EAGAIN = 0xb,
+ ETIMEDOUT = 0x91,
+ EWOULDBLOCK = 0xb,
+ EINPROGRESS = 0x96,
+
+ PROT_NONE = 0x0,
+ PROT_READ = 0x1,
+ PROT_WRITE = 0x2,
+ PROT_EXEC = 0x4,
+
+ MAP_ANON = 0x100,
+ MAP_PRIVATE = 0x2,
+ MAP_FIXED = 0x10,
+
+ MADV_FREE = 0x5,
+
+ SA_SIGINFO = 0x8,
+ SA_RESTART = 0x4,
+ SA_ONSTACK = 0x1,
+
+ SIGHUP = 0x1,
+ SIGINT = 0x2,
+ SIGQUIT = 0x3,
+ SIGILL = 0x4,
+ SIGTRAP = 0x5,
+ SIGABRT = 0x6,
+ SIGEMT = 0x7,
+ SIGFPE = 0x8,
+ SIGKILL = 0x9,
+ SIGBUS = 0xa,
+ SIGSEGV = 0xb,
+ SIGSYS = 0xc,
+ SIGPIPE = 0xd,
+ SIGALRM = 0xe,
+ SIGTERM = 0xf,
+ SIGURG = 0x15,
+ SIGSTOP = 0x17,
+ SIGTSTP = 0x18,
+ SIGCONT = 0x19,
+ SIGCHLD = 0x12,
+ SIGTTIN = 0x1a,
+ SIGTTOU = 0x1b,
+ SIGIO = 0x16,
+ SIGXCPU = 0x1e,
+ SIGXFSZ = 0x1f,
+ SIGVTALRM = 0x1c,
+ SIGPROF = 0x1d,
+ SIGWINCH = 0x14,
+ SIGUSR1 = 0x10,
+ SIGUSR2 = 0x11,
+
+ FPE_INTDIV = 0x1,
+ FPE_INTOVF = 0x2,
+ FPE_FLTDIV = 0x3,
+ FPE_FLTOVF = 0x4,
+ FPE_FLTUND = 0x5,
+ FPE_FLTRES = 0x6,
+ FPE_FLTINV = 0x7,
+ FPE_FLTSUB = 0x8,
+
+ BUS_ADRALN = 0x1,
+ BUS_ADRERR = 0x2,
+ BUS_OBJERR = 0x3,
+
+ SEGV_MAPERR = 0x1,
+ SEGV_ACCERR = 0x2,
+
+ ITIMER_REAL = 0x0,
+ ITIMER_VIRTUAL = 0x1,
+ ITIMER_PROF = 0x2,
+
+ _SC_NPROCESSORS_ONLN = 0xf,
+
+ PTHREAD_CREATE_DETACHED = 0x40,
+
+ FORK_NOSIGCHLD = 0x1,
+ FORK_WAITPID = 0x2,
+
+ MAXHOSTNAMELEN = 0x100,
+
+ O_NONBLOCK = 0x80,
+ FD_CLOEXEC = 0x1,
+ F_GETFL = 0x3,
+ F_SETFL = 0x4,
+ F_SETFD = 0x2,
+
+ POLLIN = 0x1,
+ POLLOUT = 0x4,
+ POLLHUP = 0x10,
+ POLLERR = 0x8,
+
+ PORT_SOURCE_FD = 0x4,
+};
+
+typedef struct SemT SemT;
+typedef struct Sigaltstack Sigaltstack;
+typedef struct Sigset Sigset;
+typedef struct StackT StackT;
+typedef struct Siginfo Siginfo;
+typedef struct Sigaction Sigaction;
+typedef struct Fpregset Fpregset;
+typedef struct Mcontext Mcontext;
+typedef struct Ucontext Ucontext;
+typedef struct Timespec Timespec;
+typedef struct Timeval Timeval;
+typedef struct Itimerval Itimerval;
+typedef struct PortEvent PortEvent;
+typedef struct PthreadAttr PthreadAttr;
+typedef struct Stat Stat;
+
+#pragma pack on
+
+struct SemT {
+ uint32 sem_count;
+ uint16 sem_type;
+ uint16 sem_magic;
+ uint64 sem_pad1[3];
+ uint64 sem_pad2[2];
+};
+
+struct Sigaltstack {
+ byte *ss_sp;
+ uint64 ss_size;
+ int32 ss_flags;
+ byte Pad_cgo_0[4];
+};
+struct Sigset {
+ uint32 __sigbits[4];
+};
+struct StackT {
+ byte *ss_sp;
+ uint64 ss_size;
+ int32 ss_flags;
+ byte Pad_cgo_0[4];
+};
+
+struct Siginfo {
+ int32 si_signo;
+ int32 si_code;
+ int32 si_errno;
+ int32 si_pad;
+ byte __data[240];
+};
+struct Sigaction {
+ int32 sa_flags;
+ byte Pad_cgo_0[4];
+ byte _funcptr[8];
+ Sigset sa_mask;
+};
+
+struct Fpregset {
+ byte fp_reg_set[528];
+};
+struct Mcontext {
+ int64 gregs[28];
+ Fpregset fpregs;
+};
+struct Ucontext {
+ uint64 uc_flags;
+ Ucontext *uc_link;
+ Sigset uc_sigmask;
+ StackT uc_stack;
+ byte Pad_cgo_0[8];
+ Mcontext uc_mcontext;
+ int64 uc_filler[5];
+ byte Pad_cgo_1[8];
+};
+
+struct Timespec {
+ int64 tv_sec;
+ int64 tv_nsec;
+};
+struct Timeval {
+ int64 tv_sec;
+ int64 tv_usec;
+};
+struct Itimerval {
+ Timeval it_interval;
+ Timeval it_value;
+};
+
+struct PortEvent {
+ int32 portev_events;
+ uint16 portev_source;
+ uint16 portev_pad;
+ uint64 portev_object;
+ byte *portev_user;
+};
+typedef uint32 Pthread;
+struct PthreadAttr {
+ byte *__pthread_attrp;
+};
+
+struct Stat {
+ uint64 st_dev;
+ uint64 st_ino;
+ uint32 st_mode;
+ uint32 st_nlink;
+ uint32 st_uid;
+ uint32 st_gid;
+ uint64 st_rdev;
+ int64 st_size;
+ Timespec st_atim;
+ Timespec st_mtim;
+ Timespec st_ctim;
+ int32 st_blksize;
+ byte Pad_cgo_0[4];
+ int64 st_blocks;
+ int8 st_fstype[16];
+};
+
+
+#pragma pack off
+// Created by cgo -cdefs - DO NOT EDIT
+// cgo -cdefs defs_solaris.go defs_solaris_amd64.go
+
+
+enum {
+ REG_RDI = 0x8,
+ REG_RSI = 0x9,
+ REG_RDX = 0xc,
+ REG_RCX = 0xd,
+ REG_R8 = 0x7,
+ REG_R9 = 0x6,
+ REG_R10 = 0x5,
+ REG_R11 = 0x4,
+ REG_R12 = 0x3,
+ REG_R13 = 0x2,
+ REG_R14 = 0x1,
+ REG_R15 = 0x0,
+ REG_RBP = 0xa,
+ REG_RBX = 0xb,
+ REG_RAX = 0xe,
+ REG_GS = 0x17,
+ REG_FS = 0x16,
+ REG_ES = 0x18,
+ REG_DS = 0x19,
+ REG_TRAPNO = 0xf,
+ REG_ERR = 0x10,
+ REG_RIP = 0x11,
+ REG_CS = 0x12,
+ REG_RFLAGS = 0x13,
+ REG_RSP = 0x14,
+ REG_SS = 0x15,
+};
+
diff --git a/src/pkg/runtime/env_posix.c b/src/pkg/runtime/env_posix.c
index 00ce577d0..5847f8c8a 100644
--- a/src/pkg/runtime/env_posix.c
+++ b/src/pkg/runtime/env_posix.c
@@ -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 darwin dragonfly freebsd linux netbsd openbsd windows
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
#include "runtime.h"
diff --git a/src/pkg/runtime/lfstack.c b/src/pkg/runtime/lfstack.c
index 140384d3d..e94f360c2 100644
--- a/src/pkg/runtime/lfstack.c
+++ b/src/pkg/runtime/lfstack.c
@@ -17,6 +17,20 @@
#define PTR_MASK ((1ull<<PTR_BITS)-1)
#define CNT_MASK (0ull-1)
+#ifdef _64BIT
+#ifdef GOOS_solaris
+// SPARC64 and Solaris on AMD64 uses all 64 bits of virtual addresses.
+// Use low-order three bits as ABA counter.
+// http://docs.oracle.com/cd/E19120-01/open.solaris/816-5138/6mba6ua5p/index.html
+#undef PTR_BITS
+#undef CNT_MASK
+#undef PTR_MASK
+#define PTR_BITS 0
+#define CNT_MASK 7
+#define PTR_MASK ((0ull-1)<<3)
+#endif
+#endif
+
void
runtime·lfstackpush(uint64 *head, LFNode *node)
{
diff --git a/src/pkg/runtime/lock_sema.c b/src/pkg/runtime/lock_sema.c
index 3d58cc87f..f7156105f 100644
--- a/src/pkg/runtime/lock_sema.c
+++ b/src/pkg/runtime/lock_sema.c
@@ -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 darwin netbsd openbsd plan9 windows
+// +build darwin netbsd openbsd plan9 solaris windows
#include "runtime.h"
#include "stack.h"
diff --git a/src/pkg/runtime/mem_solaris.c b/src/pkg/runtime/mem_solaris.c
new file mode 100644
index 000000000..459fffad7
--- /dev/null
+++ b/src/pkg/runtime/mem_solaris.c
@@ -0,0 +1,90 @@
+// 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"
+
+enum
+{
+ ENOMEM = 12,
+};
+
+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·SysReserve(void *v, uintptr n)
+{
+ 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)
+ return v;
+
+ p = runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
+ if(p < (void*)4096)
+ return nil;
+ return p;
+}
+
+void
+runtime·SysMap(void *v, uintptr n, uint64 *stat)
+{
+ void *p;
+
+ runtime·xadd64(stat, n);
+
+ // On 64-bit, we don't actually have v reserved, so tread carefully.
+ if(sizeof(void*) == 8) {
+ 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");
+}
diff --git a/src/pkg/runtime/netpoll.goc b/src/pkg/runtime/netpoll.goc
index d27bef167..9b5176645 100644
--- a/src/pkg/runtime/netpoll.goc
+++ b/src/pkg/runtime/netpoll.goc
@@ -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 darwin dragonfly freebsd linux netbsd openbsd windows
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
package net
@@ -113,6 +113,12 @@ func runtime_pollWait(pd *PollDesc, mode int) (err int) {
runtime·lock(pd);
err = checkerr(pd, mode);
if(err == 0) {
+#ifdef GOOS_solaris
+ if(mode == 'r')
+ runtime·netpollarmread(pd->fd);
+ else if(mode == 'w')
+ runtime·netpollarmwrite(pd->fd);
+#endif
while(!netpollblock(pd, mode)) {
err = checkerr(pd, mode);
if(err != 0)
@@ -127,6 +133,12 @@ func runtime_pollWait(pd *PollDesc, mode int) (err int) {
func runtime_pollWaitCanceled(pd *PollDesc, mode int) {
runtime·lock(pd);
+#ifdef GOOS_solaris
+ if(mode == 'r')
+ runtime·netpollarmread(pd->fd);
+ else if(mode == 'w')
+ runtime·netpollarmwrite(pd->fd);
+#endif
// wait for ioready, ignore closing or timeouts.
while(!netpollblock(pd, mode))
;
diff --git a/src/pkg/runtime/os_solaris.c b/src/pkg/runtime/os_solaris.c
new file mode 100644
index 000000000..4e212f544
--- /dev/null
+++ b/src/pkg/runtime/os_solaris.c
@@ -0,0 +1,579 @@
+// 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 "../../cmd/ld/textflag.h"
+
+#pragma dynexport end _end
+#pragma dynexport etext _etext
+#pragma dynexport 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, };
+
+// Calling sysvcall on os stack.
+#pragma textflag NOSPLIT
+uintptr
+runtime·sysvicall6(uintptr fn, int32 count, ...)
+{
+ runtime·memclr((byte*)&m->scratch, sizeof(m->scratch));
+ m->libcall.fn = (void*)fn;
+ m->libcall.n = (uintptr)count;
+ for(;count; count--)
+ m->scratch.v[count - 1] = *((uintptr*)&count + count);
+ m->libcall.args = (uintptr*)&m->scratch.v[0];
+ runtime·asmcgocall(runtime·asmsysvicall6, &m->libcall);
+ return m->libcall.r1;
+}
+
+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;
+
+ 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");
+ if(runtime·pthread_attr_getstack(&attr, (void**)&mp->g0->stackbase, &mp->g0->stacksize) != 0)
+ runtime·throw("pthread_attr_getstack");
+ 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");
+ }
+}
+
+void
+runtime·get_random_data(byte **rnd, int32 *rnd_len)
+{
+ 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);
+}
+
+// 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*)m->gsignal->stackguard - StackGuard, 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);
+}
+
+void
+runtime·sigpanic(void)
+{
+ switch(g->sig) {
+ case SIGBUS:
+ if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000) {
+ if(g->sigpc == 0)
+ runtime·panicstring("call of nil func value");
+ runtime·panicstring("invalid memory address or nil pointer dereference");
+ }
+ runtime·printf("unexpected fault address %p\n", g->sigcode1);
+ runtime·throw("fault");
+ case SIGSEGV:
+ if((g->sigcode0 == 0 || g->sigcode0 == SEGV_MAPERR || g->sigcode0 == SEGV_ACCERR) && g->sigcode1 < 0x1000) {
+ if(g->sigpc == 0)
+ runtime·panicstring("call of nil func value");
+ runtime·panicstring("invalid memory address or nil pointer dereference");
+ }
+ runtime·printf("unexpected fault address %p\n", g->sigcode1);
+ runtime·throw("fault");
+ case SIGFPE:
+ switch(g->sigcode0) {
+ case FPE_INTDIV:
+ runtime·panicstring("integer divide by zero");
+ case FPE_INTOVF:
+ runtime·panicstring("integer overflow");
+ }
+ runtime·panicstring("floating point error");
+ }
+ runtime·panicstring(runtime·sigtab[g->sig].name);
+}
+
+uintptr
+runtime·memlimit(void)
+{
+ Rlimit rl;
+ extern byte text[], 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 = end - 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)
+{
+ Sigaction 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)
+{
+ Sigaction 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.
+ m->libcall.fn = (void*)libc·malloc;
+ m->libcall.n = 1;
+ runtime·memclr((byte*)&m->scratch, sizeof(m->scratch));
+ m->scratch.v[0] = (uintptr)sizeof(*sem);
+ m->libcall.args = (uintptr*)&m->scratch;
+ runtime·asmcgocall(runtime·asmsysvicall6, &m->libcall);
+ sem = (void*)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)
+{
+ if(ns >= 0) {
+ m->ts.tv_sec = ns / 1000000000LL;
+ m->ts.tv_nsec = ns % 1000000000LL;
+
+ m->libcall.fn = (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*)&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 = (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*)&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");
+}
+
+int32
+runtime·close(int32 fd)
+{
+ return runtime·sysvicall6(libc·close, 1, (uintptr)fd);
+}
+
+void
+runtime·exit(int32 r)
+{
+ runtime·sysvicall6(libc·exit, 1, (uintptr)r);
+}
+
+/* int32 */ void
+runtime·getcontext(Ucontext* context)
+{
+ runtime·sysvicall6(libc·getcontext, 1, (uintptr)context);
+}
+
+int32
+runtime·getrlimit(int32 res, Rlimit* rlp)
+{
+ return runtime·sysvicall6(libc·getrlimit, 2, (uintptr)res, (uintptr)rlp);
+}
+
+uint8*
+runtime·mmap(byte* addr, uintptr len, int32 prot, int32 flags, int32 fildes, uint32 off)
+{
+ return (uint8*)runtime·sysvicall6(libc·mmap, 6, (uintptr)addr, (uintptr)len, (uintptr)prot, (uintptr)flags, (uintptr)fildes, (uintptr)off);
+}
+
+void
+runtime·munmap(byte* addr, uintptr len)
+{
+ runtime·sysvicall6(libc·munmap, 2, (uintptr)addr, (uintptr)len);
+}
+
+extern int64 runtime·nanotime1(void);
+#pragma textflag NOSPLIT
+int64
+runtime·nanotime(void)
+{
+ return runtime·sysvicall6((uintptr)runtime·nanotime1, 0);
+}
+
+void
+time·now(int64 sec, int32 usec)
+{
+ int64 ns;
+
+ ns = runtime·nanotime();
+ sec = ns / 1000000000LL;
+ usec = ns - sec * 1000000000LL;
+ FLUSH(&sec);
+ FLUSH(&usec);
+}
+
+int32
+runtime·open(int8* path, int32 oflag, int32 mode)
+{
+ return runtime·sysvicall6(libc·open, 3, (uintptr)path, (uintptr)oflag, (uintptr)mode);
+}
+
+int32
+runtime·pthread_attr_destroy(PthreadAttr* attr)
+{
+ return runtime·sysvicall6(libc·pthread_attr_destroy, 1, (uintptr)attr);
+}
+
+int32
+runtime·pthread_attr_getstack(PthreadAttr* attr, void** addr, uint64* size)
+{
+ return runtime·sysvicall6(libc·pthread_attr_getstack, 3, (uintptr)attr, (uintptr)addr, (uintptr)size);
+}
+
+int32
+runtime·pthread_attr_init(PthreadAttr* attr)
+{
+ return runtime·sysvicall6(libc·pthread_attr_init, 1, (uintptr)attr);
+}
+
+int32
+runtime·pthread_attr_setdetachstate(PthreadAttr* attr, int32 state)
+{
+ return runtime·sysvicall6(libc·pthread_attr_setdetachstate, 2, (uintptr)attr, (uintptr)state);
+}
+
+int32
+runtime·pthread_attr_setstack(PthreadAttr* attr, void* addr, uint64 size)
+{
+ return runtime·sysvicall6(libc·pthread_attr_setstack, 3, (uintptr)attr, (uintptr)addr, (uintptr)size);
+}
+
+int32
+runtime·pthread_create(Pthread* thread, PthreadAttr* attr, void(*fn)(void), void *arg)
+{
+ return runtime·sysvicall6(libc·pthread_create, 4, (uintptr)thread, (uintptr)attr, (uintptr)fn, (uintptr)arg);
+}
+
+/* int32 */ void
+runtime·raise(int32 sig)
+{
+ runtime·sysvicall6(libc·raise, 1, (uintptr)sig);
+}
+
+int32
+runtime·read(int32 fd, void* buf, int32 nbyte)
+{
+ return runtime·sysvicall6(libc·read, 3, (uintptr)fd, (uintptr)buf, (uintptr)nbyte);
+}
+
+#pragma textflag NOSPLIT
+int32
+runtime·sem_init(SemT* sem, int32 pshared, uint32 value)
+{
+ return runtime·sysvicall6(libc·sem_init, 3, (uintptr)sem, (uintptr)pshared, (uintptr)value);
+}
+
+#pragma textflag NOSPLIT
+int32
+runtime·sem_post(SemT* sem)
+{
+ return runtime·sysvicall6(libc·sem_post, 1, (uintptr)sem);
+}
+
+#pragma textflag NOSPLIT
+int32
+runtime·sem_reltimedwait_np(SemT* sem, Timespec* timeout)
+{
+ return runtime·sysvicall6(libc·sem_reltimedwait_np, 2, (uintptr)sem, (uintptr)timeout);
+}
+
+#pragma textflag NOSPLIT
+int32
+runtime·sem_wait(SemT* sem)
+{
+ return runtime·sysvicall6(libc·sem_wait, 1, (uintptr)sem);
+}
+
+/* int32 */ void
+runtime·setitimer(int32 which, Itimerval* value, Itimerval* ovalue)
+{
+ runtime·sysvicall6(libc·setitimer, 3, (uintptr)which, (uintptr)value, (uintptr)ovalue);
+}
+
+/* int32 */ void
+runtime·sigaction(int32 sig, struct Sigaction* act, struct Sigaction* oact)
+{
+ runtime·sysvicall6(libc·sigaction, 3, (uintptr)sig, (uintptr)act, (uintptr)oact);
+}
+
+/* int32 */ void
+runtime·sigaltstack(Sigaltstack* ss, Sigaltstack* oss)
+{
+ runtime·sysvicall6(libc·sigaltstack, 2, (uintptr)ss, (uintptr)oss);
+}
+
+/* int32 */ void
+runtime·sigprocmask(int32 how, Sigset* set, Sigset* oset)
+{
+ runtime·sysvicall6(libc·sigprocmask, 3, (uintptr)how, (uintptr)set, (uintptr)oset);
+}
+
+int64
+runtime·sysconf(int32 name)
+{
+ return runtime·sysvicall6(libc·sysconf, 1, (uintptr)name);
+}
+
+void
+runtime·usleep(uint32 us)
+{
+ runtime·sysvicall6(libc·usleep, 1, (uintptr)us);
+}
+
+int32
+runtime·write(int32 fd, void* buf, int32 nbyte)
+{
+ return runtime·sysvicall6(libc·write, 3, (uintptr)fd, (uintptr)buf, (uintptr)nbyte);
+}
+
+void
+runtime·osyield(void)
+{
+ runtime·sysvicall6(libc·sched_yield, 0);
+}
diff --git a/src/pkg/runtime/os_solaris.h b/src/pkg/runtime/os_solaris.h
new file mode 100644
index 000000000..47c712b6a
--- /dev/null
+++ b/src/pkg/runtime/os_solaris.h
@@ -0,0 +1,51 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#define SS_DISABLE 2
+
+#define SIG_BLOCK 1
+#define SIG_UNBLOCK 2
+#define SIG_SETMASK 3
+
+typedef uintptr kevent_udata;
+
+struct sigaction;
+
+void runtime·sigpanic(void);
+
+void runtime·setitimer(int32, Itimerval*, Itimerval*);
+void runtime·sigaction(int32, struct Sigaction*, struct Sigaction*);
+void runtime·sigaltstack(Sigaltstack*, Sigaltstack*);
+void runtime·sigprocmask(int32, Sigset*, Sigset*);
+void runtime·unblocksignals(void);
+int32 runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
+
+#define NSIG 73 /* number of signals in runtime·SigTab array */
+#define SI_USER 0
+
+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);
+
+#define _UC_SIGMASK 0x01
+#define _UC_CPU 0x04
+
+#define RLIMIT_AS 10
+typedef struct Rlimit Rlimit;
+struct Rlimit {
+ int64 rlim_cur;
+ int64 rlim_max;
+};
+int32 runtime·getrlimit(int32, Rlimit*);
+
+// Call a library function with SysV conventions,
+// and switch to os stack during the call.
+#pragma varargck countpos runtime·sysvicall6 2
+#pragma varargck type runtime·sysvicall6 uintptr
+#pragma varargck type runtime·sysvicall6 int32
+void runtime·asmsysvicall6(void *c);
+uintptr runtime·sysvicall6(uintptr fn, int32 count, ...);
+
+void runtime·miniterrno(void *fn);
diff --git a/src/pkg/runtime/os_windows.c b/src/pkg/runtime/os_windows.c
index c3e296aa6..bcbc55e4d 100644
--- a/src/pkg/runtime/os_windows.c
+++ b/src/pkg/runtime/os_windows.c
@@ -285,11 +285,11 @@ time·now(int64 sec, int32 usec)
void *
runtime·stdcall(void *fn, int32 count, ...)
{
- m->wincall.fn = fn;
- m->wincall.n = count;
- m->wincall.args = (uintptr*)&count + 1;
- runtime·asmcgocall(runtime·asmstdcall, &m->wincall);
- return (void*)m->wincall.r1;
+ m->libcall.fn = fn;
+ m->libcall.n = count;
+ m->libcall.args = (uintptr*)&count + 1;
+ runtime·asmcgocall(runtime·asmstdcall, &m->libcall);
+ return (void*)m->libcall.r1;
}
extern void runtime·usleep1(uint32);
diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c
index 064e8cb24..29b6a7c76 100644
--- a/src/pkg/runtime/proc.c
+++ b/src/pkg/runtime/proc.c
@@ -653,9 +653,9 @@ runtime·allocm(P *p)
mp = runtime·cnew(mtype);
mcommoninit(mp);
- // In case of cgo, pthread_create will make us a stack.
+ // In case of cgo or Solaris, pthread_create will make us a stack.
// Windows will layout sched stack on OS stack.
- if(runtime·iscgo || Windows)
+ if(runtime·iscgo || Solaris || Windows)
mp->g0 = runtime·malg(-1);
else
mp->g0 = runtime·malg(8192);
diff --git a/src/pkg/runtime/rt0_solaris_amd64.s b/src/pkg/runtime/rt0_solaris_amd64.s
new file mode 100644
index 000000000..32fc8333f
--- /dev/null
+++ b/src/pkg/runtime/rt0_solaris_amd64.s
@@ -0,0 +1,18 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "../../cmd/ld/textflag.h"
+
+TEXT _rt0_amd64_solaris(SB),NOSPLIT,$-8
+ LEAQ 8(SP), SI // argv
+ MOVQ 0(SP), DI // argc
+ MOVQ $main(SB), AX
+ JMP AX
+
+TEXT main(SB),NOSPLIT,$-8
+ MOVQ $_rt0_go(SB), AX
+ JMP AX
+
+DATA runtime·issolaris(SB)/4, $1
+GLOBL runtime·issolaris(SB), $4
diff --git a/src/pkg/runtime/runtime.c b/src/pkg/runtime/runtime.c
index 9a8eb0e34..6065714a6 100644
--- a/src/pkg/runtime/runtime.c
+++ b/src/pkg/runtime/runtime.c
@@ -87,6 +87,7 @@ runtime·args(int32 c, uint8 **v)
}
int32 runtime·isplan9;
+int32 runtime·issolaris;
int32 runtime·iswindows;
// Information about what cpu features are available.
diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h
index 43ab84c80..194593840 100644
--- a/src/pkg/runtime/runtime.h
+++ b/src/pkg/runtime/runtime.h
@@ -76,7 +76,7 @@ typedef struct Hmap Hmap;
typedef struct Hchan Hchan;
typedef struct Complex64 Complex64;
typedef struct Complex128 Complex128;
-typedef struct WinCall WinCall;
+typedef struct LibCall LibCall;
typedef struct SEH SEH;
typedef struct WinCallbackContext WinCallbackContext;
typedef struct Timers Timers;
@@ -224,7 +224,7 @@ struct GCStats
uint64 nsleep;
};
-struct WinCall
+struct LibCall
{
void (*fn)(void*);
uintptr n; // number of parameters
@@ -351,7 +351,22 @@ struct M
#ifdef GOOS_windows
void* thread; // thread handle
- WinCall wincall;
+ // these are here because they are too large to be on the stack
+ // of low-level NOSPLIT functions.
+ LibCall libcall;
+#endif
+#ifdef GOOS_solaris
+ int32* perrno; // pointer to TLS errno
+ // these are here because they are too large to be on the stack
+ // of low-level NOSPLIT functions.
+ LibCall libcall;
+ struct {
+ int64 tv_sec;
+ int64 tv_nsec;
+ } ts;
+ struct {
+ uintptr v[6];
+ } scratch;
#endif
#ifdef GOOS_plan9
int8* notesig;
@@ -467,6 +482,15 @@ enum {
Windows = 0
};
#endif
+#ifdef GOOS_solaris
+enum {
+ Solaris = 1
+};
+#else
+enum {
+ Solaris = 0
+};
+#endif
struct Timers
{
@@ -865,6 +889,8 @@ int32 runtime·netpollopen(uintptr, PollDesc*);
int32 runtime·netpollclose(uintptr);
void runtime·netpollready(G**, PollDesc*, int32);
uintptr runtime·netpollfd(PollDesc*);
+void runtime·netpollarmread(uintptr fd);
+void runtime·netpollarmwrite(uintptr fd);
void runtime·crash(void);
void runtime·parsedebugvars(void);
void _rt0_go(void);
diff --git a/src/pkg/runtime/signal_amd64.c b/src/pkg/runtime/signal_amd64.c
index f0cbb1f8c..6f3c785a4 100644
--- a/src/pkg/runtime/signal_amd64.c
+++ b/src/pkg/runtime/signal_amd64.c
@@ -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 darwin dragonfly freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
diff --git a/src/pkg/runtime/signal_solaris_amd64.h b/src/pkg/runtime/signal_solaris_amd64.h
new file mode 100644
index 000000000..df54a7d14
--- /dev/null
+++ b/src/pkg/runtime/signal_solaris_amd64.h
@@ -0,0 +1,31 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#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])
diff --git a/src/pkg/runtime/signal_unix.c b/src/pkg/runtime/signal_unix.c
index edbf1d275..246a1eb25 100644
--- a/src/pkg/runtime/signal_unix.c
+++ b/src/pkg/runtime/signal_unix.c
@@ -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 darwin dragonfly freebsd linux openbsd netbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
diff --git a/src/pkg/runtime/signals_solaris.h b/src/pkg/runtime/signals_solaris.h
new file mode 100644
index 000000000..75304644a
--- /dev/null
+++ b/src/pkg/runtime/signals_solaris.h
@@ -0,0 +1,94 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#define N SigNotify
+#define K SigKill
+#define T SigThrow
+#define P SigPanic
+#define D SigDefault
+
+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
diff --git a/src/pkg/runtime/sys_solaris_amd64.s b/src/pkg/runtime/sys_solaris_amd64.s
new file mode 100644
index 000000000..ffe2df43f
--- /dev/null
+++ b/src/pkg/runtime/sys_solaris_amd64.s
@@ -0,0 +1,267 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+//
+// System calls and other sys.stuff for AMD64, SunOS
+// /usr/include/sys/syscall.h for syscall numbers.
+//
+
+#include "zasm_GOOS_GOARCH.h"
+#include "../../cmd/ld/textflag.h"
+
+// This is needed by asm_amd64.s
+TEXT runtime·settls(SB),NOSPLIT,$8
+ RET
+
+// void libc·miniterrno(void *(*___errno)(void));
+//
+// Set the TLS errno pointer in M.
+//
+// Called using runtime·asmcgocall from os_solaris.c:/minit.
+TEXT runtime·miniterrno(SB),NOSPLIT,$0
+ // asmcgocall will put first argument into DI.
+ CALL DI // SysV ABI so returns in AX
+ get_tls(CX)
+ MOVQ m(CX), BX
+ MOVQ AX, m_perrno(BX)
+ RET
+
+// int64 runtime·nanotime1(void);
+//
+// clock_gettime(3c) wrapper because Timespec is too large for
+// runtime·nanotime stack.
+//
+// Called using runtime·sysvicall6 from os_solaris.c:/nanotime.
+TEXT runtime·nanotime1(SB),NOSPLIT,$0
+ // need space for the timespec argument.
+ 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
+ CALL AX
+ MOVQ (SP), AX // tv_sec from struct timespec
+ IMULQ $1000000000, AX // multiply into nanoseconds
+ ADDQ 8(SP), AX // tv_nsec, offset should be stable.
+ ADDQ $64, SP
+ RET
+
+// pipe(3c) wrapper that returns fds in AX, DX.
+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
+ CALL AX
+ MOVL 0(SP), AX
+ MOVL 4(SP), DX
+ ADDQ $16, SP
+ RET
+
+// Call a library function with SysV calling conventions.
+// The called function can take a maximum of 6 INTEGER class arguments,
+// see
+// Michael Matz, Jan Hubicka, Andreas Jaeger, and Mark Mitchell
+// System V Application Binary Interface
+// AMD64 Architecture Processor Supplement
+// section 3.2.3.
+//
+// Called by runtime·asmcgocall or runtime·cgocall.
+TEXT runtime·asmsysvicall6(SB),NOSPLIT,$0
+ // asmcgocall will put first argument into DI.
+ PUSHQ DI // save for later
+ MOVQ libcall_fn(DI), AX
+ MOVQ libcall_args(DI), R11
+ MOVQ libcall_n(DI), R10
+
+ get_tls(CX)
+ MOVQ m(CX), BX
+ MOVQ m_perrno(BX), DX
+ CMPQ DX, $0
+ JEQ skiperrno1
+ MOVL $0, 0(DX)
+
+skiperrno1:
+ CMPQ R11, $0
+ JEQ skipargs
+ // Load 6 args into correspondent registers.
+ MOVQ 0(R11), DI
+ MOVQ 8(R11), SI
+ MOVQ 16(R11), DX
+ MOVQ 24(R11), CX
+ MOVQ 32(R11), R8
+ MOVQ 40(R11), R9
+skipargs:
+
+ // Call SysV function
+ CALL AX
+
+ // Return result
+ POPQ DI
+ MOVQ AX, libcall_r1(DI)
+ MOVQ DX, libcall_r2(DI)
+
+ get_tls(CX)
+ MOVQ m(CX), BX
+ MOVQ m_perrno(BX), AX
+ CMPQ AX, $0
+ JEQ skiperrno2
+ MOVL 0(AX), AX
+ MOVQ AX, libcall_err(DI)
+
+skiperrno2:
+ RET
+
+// uint32 tstart_sysvicall(M *newm);
+TEXT runtime·tstart_sysvicall(SB),NOSPLIT,$0
+ // DI contains first arg newm
+ MOVQ m_g0(DI), DX // g
+
+ // Make TLS entries point at g and m.
+ get_tls(BX)
+ MOVQ DX, g(BX)
+ MOVQ DI, m(BX)
+
+ // Layout new m scheduler stack on os stack.
+ MOVQ SP, AX
+ MOVQ AX, g_stackbase(DX)
+ SUBQ $(0x100000), AX // stack size
+ MOVQ AX, g_stackguard(DX)
+ MOVQ AX, g_stackguard0(DX)
+
+ // Someday the convention will be D is always cleared.
+ CLD
+
+ CALL runtime·stackcheck(SB) // clobbers AX,CX
+ CALL runtime·mstart(SB)
+
+ XORL AX, AX // return 0 == success
+ RET
+
+// Careful, this is called by __sighndlr, a libc function. We must preserve
+// registers as per AMD 64 ABI.
+TEXT runtime·sigtramp(SB),NOSPLIT,$0
+ // Note that we are executing on altsigstack here, so we have
+ // more stack available than NOSPLIT would have us believe.
+ // To defeat the linker, we make our own stack frame with
+ // more space:
+ SUBQ $184, SP
+
+ // save registers
+ MOVQ BX, 32(SP)
+ MOVQ BP, 40(SP)
+ MOVQ R12, 48(SP)
+ MOVQ R13, 56(SP)
+ MOVQ R14, 64(SP)
+ MOVQ R15, 72(SP)
+
+ get_tls(BX)
+ // check that m exists
+ MOVQ m(BX), BP
+ CMPQ BP, $0
+ JNE allgood
+ MOVQ DI, 0(SP)
+ MOVQ $runtime·badsignal(SB), AX
+ CALL AX
+ RET
+
+allgood:
+ // save g
+ MOVQ g(BX), R10
+ MOVQ R10, 80(SP)
+
+ // Save m->libcall and m->scratch. We need to do this because we
+ // might get interrupted by a signal in runtime·asmcgocall.
+
+ // save m->libcall
+ LEAQ m_libcall(BP), R11
+ MOVQ libcall_fn(R11), R10
+ MOVQ R10, 88(SP)
+ MOVQ libcall_args(R11), R10
+ MOVQ R10, 96(SP)
+ MOVQ libcall_n(R11), R10
+ MOVQ R10, 104(SP)
+ MOVQ libcall_r1(R11), R10
+ MOVQ R10, 168(SP)
+ MOVQ libcall_r2(R11), R10
+ MOVQ R10, 176(SP)
+
+ // save m->scratch
+ LEAQ m_scratch(BP), R11
+ MOVQ 0(R11), R10
+ MOVQ R10, 112(SP)
+ MOVQ 8(R11), R10
+ MOVQ R10, 120(SP)
+ MOVQ 16(R11), R10
+ MOVQ R10, 128(SP)
+ MOVQ 24(R11), R10
+ MOVQ R10, 136(SP)
+ MOVQ 32(R11), R10
+ MOVQ R10, 144(SP)
+ MOVQ 40(R11), R10
+ MOVQ R10, 152(SP)
+
+ // save errno, it might be EINTR; stuff we do here might reset it.
+ MOVQ m_perrno(BP), R10
+ MOVL 0(R10), R10
+ MOVQ R10, 160(SP)
+
+ MOVQ g(BX), R10
+ // g = m->gsignal
+ MOVQ m_gsignal(BP), BP
+ MOVQ BP, g(BX)
+
+ // prepare call
+ MOVQ DI, 0(SP)
+ MOVQ SI, 8(SP)
+ MOVQ DX, 16(SP)
+ MOVQ R10, 24(SP)
+ CALL runtime·sighandler(SB)
+
+ get_tls(BX)
+ MOVQ m(BX), BP
+ // restore libcall
+ LEAQ m_libcall(BP), R11
+ MOVQ 88(SP), R10
+ MOVQ R10, libcall_fn(R11)
+ MOVQ 96(SP), R10
+ MOVQ R10, libcall_args(R11)
+ MOVQ 104(SP), R10
+ MOVQ R10, libcall_n(R11)
+ MOVQ 168(SP), R10
+ MOVQ R10, libcall_r1(R11)
+ MOVQ 176(SP), R10
+ MOVQ R10, libcall_r2(R11)
+
+ // restore scratch
+ LEAQ m_scratch(BP), R11
+ MOVQ 112(SP), R10
+ MOVQ R10, 0(R11)
+ MOVQ 120(SP), R10
+ MOVQ R10, 8(R11)
+ MOVQ 128(SP), R10
+ MOVQ R10, 16(R11)
+ MOVQ 136(SP), R10
+ MOVQ R10, 24(R11)
+ MOVQ 144(SP), R10
+ MOVQ R10, 32(R11)
+ MOVQ 152(SP), R10
+ MOVQ R10, 40(R11)
+
+ // restore errno
+ MOVQ m_perrno(BP), R11
+ MOVQ 160(SP), R10
+ MOVL R10, 0(R11)
+
+ // restore g
+ MOVQ 80(SP), R10
+ MOVQ R10, g(BX)
+
+ // restore registers
+ MOVQ 32(SP), BX
+ MOVQ 40(SP), BP
+ MOVQ 48(SP), R12
+ MOVQ 56(SP), R13
+ MOVQ 64(SP), R14
+ MOVQ 72(SP), R15
+
+ ADDQ $184, SP
+ RET
diff --git a/src/pkg/runtime/sys_windows_386.s b/src/pkg/runtime/sys_windows_386.s
index 20753638e..49742c3e0 100644
--- a/src/pkg/runtime/sys_windows_386.s
+++ b/src/pkg/runtime/sys_windows_386.s
@@ -14,28 +14,28 @@ TEXT runtime·asmstdcall(SB),NOSPLIT,$0
// Copy args to the stack.
MOVL SP, BP
- MOVL wincall_n(BX), CX // words
+ MOVL libcall_n(BX), CX // words
MOVL CX, AX
SALL $2, AX
SUBL AX, SP // room for args
MOVL SP, DI
- MOVL wincall_args(BX), SI
+ MOVL libcall_args(BX), SI
CLD
REP; MOVSL
// Call stdcall or cdecl function.
// DI SI BP BX are preserved, SP is not
- CALL wincall_fn(BX)
+ CALL libcall_fn(BX)
MOVL BP, SP
// Return result.
MOVL c+0(FP), BX
- MOVL AX, wincall_r1(BX)
- MOVL DX, wincall_r2(BX)
+ MOVL AX, libcall_r1(BX)
+ MOVL DX, libcall_r2(BX)
// GetLastError().
MOVL 0x34(FS), AX
- MOVL AX, wincall_err(BX)
+ MOVL AX, libcall_err(BX)
RET
diff --git a/src/pkg/runtime/sys_windows_amd64.s b/src/pkg/runtime/sys_windows_amd64.s
index 8c4caf867..cdfde3c61 100644
--- a/src/pkg/runtime/sys_windows_amd64.s
+++ b/src/pkg/runtime/sys_windows_amd64.s
@@ -13,9 +13,9 @@
TEXT runtime·asmstdcall(SB),NOSPLIT,$0
// asmcgocall will put first argument into CX.
PUSHQ CX // save for later
- MOVQ wincall_fn(CX), AX
- MOVQ wincall_args(CX), SI
- MOVQ wincall_n(CX), CX
+ MOVQ libcall_fn(CX), AX
+ MOVQ libcall_args(CX), SI
+ MOVQ libcall_n(CX), CX
// SetLastError(0).
MOVQ 0x30(GS), DI
@@ -52,12 +52,12 @@ loadregs:
// Return result.
POPQ CX
- MOVQ AX, wincall_r1(CX)
+ MOVQ AX, libcall_r1(CX)
// GetLastError().
MOVQ 0x30(GS), DI
MOVL 0x68(DI), AX
- MOVQ AX, wincall_err(CX)
+ MOVQ AX, libcall_err(CX)
RET
diff --git a/src/pkg/runtime/syscall_solaris.goc b/src/pkg/runtime/syscall_solaris.goc
new file mode 100644
index 000000000..5fe3aa3eb
--- /dev/null
+++ b/src/pkg/runtime/syscall_solaris.goc
@@ -0,0 +1,374 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+#include "cgocall.h"
+#include "../../cmd/ld/textflag.h"
+
+#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"
+extern uintptr libc·chdir;
+extern uintptr libc·chroot;
+extern uintptr libc·close;
+extern uintptr libc·dlclose;
+extern uintptr libc·dlopen;
+extern uintptr libc·dlsym;
+extern uintptr libc·execve;
+extern uintptr libc·exit;
+extern uintptr libc·fcntl;
+extern uintptr libc·gethostname;
+extern uintptr libc·ioctl;
+extern uintptr libc·pipe;
+extern uintptr libc·setgid;
+extern uintptr libc·setgroups;
+extern uintptr libc·setsid;
+extern uintptr libc·setuid;
+extern uintptr libc·setpgid;
+extern uintptr libc·syscall;
+extern uintptr libc·forkx;
+extern uintptr libc·wait4;
+extern uintptr libc·write;
+
+func Sysvicall6(func uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr) (r1 uintptr, r2 uintptr, err uintptr)
+{
+ LibCall c;
+
+ USED(a2);
+ USED(a3);
+ USED(a4);
+ USED(a5);
+ USED(a6);
+ c.fn = (void*)func;
+ c.n = nargs;
+ c.args = (void*)&a1;
+ runtime·cgocall(runtime·asmsysvicall6, &c);
+ err = c.err;
+ r1 = c.r1;
+ r2 = c.r2;
+}
+
+#pragma textflag NOSPLIT
+func RawSysvicall6(func uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr) (r1 uintptr, r2 uintptr, err uintptr)
+{
+ LibCall c;
+
+ USED(a2);
+ USED(a3);
+ USED(a4);
+ USED(a5);
+ USED(a6);
+ c.fn = (void*)func;
+ c.n = nargs;
+ c.args = (void*)&a1;
+ runtime·asmcgocall(runtime·asmsysvicall6, &c);
+ err = c.err;
+ r1 = c.r1;
+ r2 = c.r2;
+}
+
+#pragma textflag NOSPLIT
+func chdir(path uintptr) (err uintptr) {
+ LibCall c;
+
+ c.fn = (void*)libc·chdir;
+ c.n = 1;
+ c.args = (void*)&path;
+ runtime·asmcgocall(runtime·asmsysvicall6, &c);
+ err = c.err;
+}
+
+#pragma textflag NOSPLIT
+func chroot1(path uintptr) (err uintptr) {
+ LibCall c;
+
+ c.fn = (void*)libc·chroot;
+ c.n = 1;
+ c.args = (void*)&path;
+ runtime·asmcgocall(runtime·asmsysvicall6, &c);
+ err = c.err;
+}
+
+#pragma textflag NOSPLIT
+func close(fd uintptr) (err uintptr) {
+ LibCall c;
+
+ c.fn = (void*)libc·close;
+ c.n = 1;
+ c.args = (void*)&fd;
+ runtime·asmcgocall(runtime·asmsysvicall6, &c);
+ err = c.err;
+}
+
+func dlclose(handle uintptr) (err uintptr) {
+ LibCall c;
+
+ USED(handle);
+ c.fn = (void*)libc·dlclose;
+ c.n = 1;
+ c.args = (void*)&handle;
+ runtime·cgocall(runtime·asmsysvicall6, &c);
+ err = c.r1;
+}
+
+func dlopen(name *uint8, mode uintptr) (handle uintptr, err uintptr) {
+ LibCall c;
+
+ USED(mode);
+ c.fn = (void*)libc·dlopen;
+ c.n = 2;
+ c.args = (void*)&name;
+ runtime·cgocall(runtime·asmsysvicall6, &c);
+ handle = c.r1;
+ if(handle == 0)
+ err = c.err;
+ else
+ err = 0;
+}
+
+func dlsym(handle uintptr, name *uint8) (proc uintptr, err uintptr) {
+ LibCall c;
+
+ USED(name);
+ c.fn = (void*)libc·dlsym;
+ c.n = 2;
+ c.args = &handle;
+ runtime·cgocall(runtime·asmsysvicall6, &c);
+ proc = c.r1;
+ if(proc == 0)
+ err = c.err;
+ else
+ err = 0;
+}
+
+#pragma textflag NOSPLIT
+func execve(path uintptr, argv uintptr, envp uintptr) (err uintptr) {
+ LibCall c;
+
+ USED(argv);
+ USED(envp);
+ c.fn = (void*)libc·execve;
+ c.n = 3;
+ c.args = (void*)&path;
+ runtime·cgocall(runtime·asmsysvicall6, &c);
+ err = c.err;
+}
+
+#pragma textflag NOSPLIT
+func exit(code uintptr) {
+ LibCall c;
+
+ c.fn = (void*)libc·exit;
+ c.n = 1;
+ c.args = (void*)&code;
+ runtime·asmcgocall(runtime·asmsysvicall6, &c);
+}
+
+#pragma textflag NOSPLIT
+func fcntl1(fd uintptr, cmd uintptr, arg uintptr) (val uintptr, err uintptr) {
+ LibCall c;
+
+ USED(cmd);
+ USED(arg);
+ c.fn = (void*)libc·fcntl;
+ c.n = 3;
+ c.args = (void*)&fd;
+ runtime·cgocall(runtime·asmsysvicall6, &c);
+ err = c.err;
+ val = c.r1;
+}
+
+func gethostname() (name String, err uintptr) {
+ struct { uintptr v[2]; } args;
+ uint8 cname[MAXHOSTNAMELEN];
+ LibCall c;
+
+ c.fn = (void*)libc·gethostname;
+ c.n = 2;
+ args.v[0] = (uintptr)&cname[0];
+ args.v[1] = MAXHOSTNAMELEN;
+ c.args = (void*)&args;
+ runtime·cgocall(runtime·asmsysvicall6, &c);
+ err = c.err;
+ if(c.r1) {
+ name = runtime·emptystring;
+ return;
+ }
+ cname[MAXHOSTNAMELEN - 1] = 0;
+ name = runtime·gostring(cname);
+}
+
+#pragma textflag NOSPLIT
+func ioctl(fd uintptr, req uintptr, arg uintptr) (err uintptr) {
+ LibCall c;
+
+ USED(req);
+ USED(arg);
+ c.fn = (void*)libc·ioctl;
+ c.n = 3;
+ c.args = (void*)&fd;
+ runtime·cgocall(runtime·asmsysvicall6, &c);
+ err = c.err;
+}
+
+func wait4(pid uintptr, wstatus *uint32, options uintptr, rusage *void) (wpid int, err uintptr) {
+ LibCall c;
+
+ USED(wstatus);
+ USED(options);
+ USED(rusage);
+ c.fn = (void*)libc·wait4;
+ c.n = 4;
+ c.args = (void*)&pid;
+ runtime·cgocall(runtime·asmsysvicall6, &c);
+ err = c.err;
+ wpid = c.r1;
+}
+
+#pragma textflag NOSPLIT
+func setgid(gid uintptr) (err uintptr) {
+ LibCall c;
+
+ c.fn = (void*)libc·setgid;
+ c.n = 1;
+ c.args = (void*)&gid;
+ runtime·asmcgocall(runtime·asmsysvicall6, &c);
+ err = c.err;
+}
+
+#pragma textflag NOSPLIT
+func setgroups1(ngid uintptr, gid uintptr) (err uintptr) {
+ LibCall c;
+
+ USED(gid);
+ c.fn = (void*)libc·setgroups;
+ c.n = 2;
+ c.args = (void*)&ngid;
+ runtime·asmcgocall(runtime·asmsysvicall6, &c);
+ err = c.err;
+}
+
+#pragma textflag NOSPLIT
+func setsid() (pid uintptr, err uintptr) {
+ LibCall c;
+
+ c.fn = (void*)libc·setsid;
+ c.n = 0;
+ c.args = (void*)0;
+ runtime·asmcgocall(runtime·asmsysvicall6, &c);
+ err = c.err;
+ pid = c.r1;
+}
+
+#pragma textflag NOSPLIT
+func setuid(uid uintptr) (err uintptr) {
+ LibCall c;
+
+ c.fn = (void*)libc·setuid;
+ c.n = 1;
+ c.args = (void*)&uid;
+ runtime·asmcgocall(runtime·asmsysvicall6, &c);
+ err = c.err;
+}
+
+#pragma textflag NOSPLIT
+func setpgid(pid uintptr, pgid uintptr) (err uintptr) {
+ LibCall c;
+
+ USED(pgid);
+ c.fn = (void*)libc·setpgid;
+ c.n = 2;
+ c.args = (void*)&pid;
+ runtime·asmcgocall(runtime·asmsysvicall6, &c);
+ err = c.err;
+}
+
+#pragma textflag NOSPLIT
+func forkx(flags uintptr) (pid uintptr, err uintptr) {
+ LibCall c;
+
+ c.fn = (void*)libc·forkx;
+ c.n = 1;
+ c.args = (void*)&flags;
+ runtime·asmcgocall(runtime·asmsysvicall6, &c);
+ err = c.err;
+ pid = c.r1;
+}
+
+void runtime·pipe1(void);
+
+func pipe() (r uintptr, w uintptr, err uintptr) {
+ LibCall c;
+
+ c.fn = (void*)runtime·pipe1;
+ c.n = 0;
+ c.args = (void*)0;
+ runtime·cgocall(runtime·asmsysvicall6, &c);
+ err = c.err;
+ r = c.r1;
+ w = c.r2;
+}
+
+#pragma textflag NOSPLIT
+func write1(fd uintptr, buf uintptr, nbyte uintptr) (n uintptr, err uintptr) {
+ LibCall c;
+
+ USED(buf);
+ USED(nbyte);
+ c.fn = (void*)libc·write;
+ c.n = 3;
+ c.args = (void*)fd;
+ runtime·cgocall(runtime·asmsysvicall6, &c);
+ err = c.err;
+ n = c.r1;
+}
+
+func Syscall(trap uintptr, a1 uintptr, a2 uintptr, a3 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
+ LibCall c;
+
+ USED(a1);
+ USED(a2);
+ USED(a3);
+ c.fn = (void*)libc·syscall;
+ c.n = 4;
+ c.args = &trap;
+ runtime·cgocall(runtime·asmsysvicall6, &c);
+ err = c.err;
+ r1 = c.r1;
+ r2 = c.r2;
+}
+
+func RawSyscall(trap uintptr, a1 uintptr, a2 uintptr, a3 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
+ LibCall c;
+
+ USED(a1);
+ USED(a2);
+ USED(a3);
+ c.fn = (void*)libc·syscall;
+ c.n = 4;
+ c.args = &trap;
+ runtime·asmcgocall(runtime·asmsysvicall6, &c);
+ err = c.err;
+ r1 = c.r1;
+ r2 = c.r2;
+}
diff --git a/src/pkg/runtime/syscall_windows.goc b/src/pkg/runtime/syscall_windows.goc
index 781ec908d..528245363 100644
--- a/src/pkg/runtime/syscall_windows.goc
+++ b/src/pkg/runtime/syscall_windows.goc
@@ -8,7 +8,7 @@ package syscall
#include "cgocall.h"
func loadlibrary(filename *uint16) (handle uintptr, err uintptr) {
- WinCall c;
+ LibCall c;
c.fn = runtime·LoadLibrary;
c.n = 1;
@@ -22,7 +22,7 @@ func loadlibrary(filename *uint16) (handle uintptr, err uintptr) {
}
func getprocaddress(handle uintptr, procname *uint8) (proc uintptr, err uintptr) {
- WinCall c;
+ LibCall c;
USED(procname);
c.fn = runtime·GetProcAddress;
@@ -45,7 +45,7 @@ func NewCallbackCDecl(fn Eface) (code uintptr) {
}
func Syscall(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
- WinCall c;
+ LibCall c;
USED(a2);
USED(a3);
@@ -59,7 +59,7 @@ func Syscall(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr) (r1
}
func Syscall6(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
- WinCall c;
+ LibCall c;
USED(a2);
USED(a3);
@@ -76,7 +76,7 @@ func Syscall6(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4
}
func Syscall9(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr, a7 uintptr, a8 uintptr, a9 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
- WinCall c;
+ LibCall c;
USED(a2);
USED(a3);
@@ -96,7 +96,7 @@ func Syscall9(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4
}
func Syscall12(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr, a7 uintptr, a8 uintptr, a9 uintptr, a10 uintptr, a11 uintptr, a12 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
- WinCall c;
+ LibCall c;
USED(a2);
USED(a3);
@@ -119,7 +119,7 @@ func Syscall12(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4
}
func Syscall15(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr, a7 uintptr, a8 uintptr, a9 uintptr, a10 uintptr, a11 uintptr, a12 uintptr, a13 uintptr, a14 uintptr, a15 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
- WinCall c;
+ LibCall c;
USED(a2);
USED(a3);