]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: add support for GOOS=solaris
authorAram Hăvărneanu <aram@mgk.ro>
Fri, 17 Jan 2014 04:58:10 +0000 (17:58 +1300)
committerJoel Sing <jsing@google.com>
Fri, 17 Jan 2014 04:58:10 +0000 (17:58 +1300)
R=alex.brainman, dave, jsing, gobot, rsc
CC=golang-codereviews
https://golang.org/cl/35990043

28 files changed:
src/cmd/dist/buildruntime.c
src/pkg/runtime/arch_amd64.h
src/pkg/runtime/asm_amd64.s
src/pkg/runtime/cgocall.c
src/pkg/runtime/defs_solaris.go [new file with mode: 0644]
src/pkg/runtime/defs_solaris_amd64.go [new file with mode: 0644]
src/pkg/runtime/defs_solaris_amd64.h [new file with mode: 0644]
src/pkg/runtime/env_posix.c
src/pkg/runtime/lfstack.c
src/pkg/runtime/lock_sema.c
src/pkg/runtime/mem_solaris.c [new file with mode: 0644]
src/pkg/runtime/netpoll.goc
src/pkg/runtime/os_solaris.c [new file with mode: 0644]
src/pkg/runtime/os_solaris.h [new file with mode: 0644]
src/pkg/runtime/os_windows.c
src/pkg/runtime/proc.c
src/pkg/runtime/rt0_solaris_amd64.s [new file with mode: 0644]
src/pkg/runtime/runtime.c
src/pkg/runtime/runtime.h
src/pkg/runtime/signal_amd64.c
src/pkg/runtime/signal_solaris_amd64.h [new file with mode: 0644]
src/pkg/runtime/signal_unix.c
src/pkg/runtime/signals_solaris.h [new file with mode: 0644]
src/pkg/runtime/sys_solaris_amd64.s [new file with mode: 0644]
src/pkg/runtime/sys_windows_386.s
src/pkg/runtime/sys_windows_amd64.s
src/pkg/runtime/syscall_solaris.goc [new file with mode: 0644]
src/pkg/runtime/syscall_windows.goc

index e6e309d92a4b059227474099da55855aeb0e1071..1babddaad5a72090f072089437edeae9c8f3b8ba 100644 (file)
@@ -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"))
index 2bddf0796723251c9ba4553944e197e651b70348..171839481bc00b42f4fa82c15e12866a882b073e 100644 (file)
@@ -6,6 +6,10 @@ enum {
        thechar = '6',
        BigEndian = 0,
        CacheLineSize = 64,
+#ifdef GOOS_solaris
+       RuntimeGogoBytes = 80,
+#else
        RuntimeGogoBytes = 64,
+#endif
        PCQuantum = 1
 };
index 2c2ffedd1e21b3f7b6238802791c6da1deba6359..980bcd4520cbf1f7477ac03c17485cf2ba4e32bf 100644 (file)
@@ -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
index 2a04453fdca6d5f02099193dd6e3c0765da5e2b9..6b2ae59ddc5214bb35078cc275d5770b48e12b3f 100644 (file)
@@ -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 (file)
index 0000000..8dcbb08
--- /dev/null
@@ -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 (file)
index 0000000..f0265de
--- /dev/null
@@ -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 (file)
index 0000000..799724f
--- /dev/null
@@ -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,
+};
+
index 00ce577d00fa9130dbda090d5d788492c5a7285f..5847f8c8a8b27dc2b6a0d1747681ce0cff37632a 100644 (file)
@@ -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"
 
index 140384d3dc91469058f70378bb8fa0adac70bee5..e94f360c24477dc52007e4aa316aaf685fcc0803 100644 (file)
 #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)
 {
index 3d58cc87f10f103f7cbe6140f7dc9af4a6aa1bc3..f7156105f97e73ecf6742d2e09d35251e5987abe 100644 (file)
@@ -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 (file)
index 0000000..459fffa
--- /dev/null
@@ -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");
+}
index d27bef167e9fe6d60987f73458a3e983f592217b..9b5176645a7349ccb1da5927822ee93433375a84 100644 (file)
@@ -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 (file)
index 0000000..4e212f5
--- /dev/null
@@ -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 (file)
index 0000000..47c712b
--- /dev/null
@@ -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);
index c3e296aa670a116fc171f22dce6f091c53f5ebbf..bcbc55e4d2440fdeb308922005b79dbb57198a7a 100644 (file)
@@ -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);
index 064e8cb24893071ea2c864997bb5f48763048fad..29b6a7c763984f1a93443efadf5c8d16509c1ee9 100644 (file)
@@ -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 (file)
index 0000000..32fc833
--- /dev/null
@@ -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
index 9a8eb0e3402be4c12172787d3157e852066e7151..6065714a6e3b81658680d78eccfd6a182cb06381 100644 (file)
@@ -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.
index 43ab84c807d1117b07936697e0d4361dfacf8d0b..1945938402941325dd483ad46972bdfbbc4b1df7 100644 (file)
@@ -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);
index f0cbb1f8cf6b26cb4c8f455b5e60321bfe6d727d..6f3c785a45e9259b3ffb4ccdc8d9eff2eb4041a4 100644 (file)
@@ -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 (file)
index 0000000..df54a7d
--- /dev/null
@@ -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])
index edbf1d2751511538cdd09b965695b413457add66..246a1eb2589840e7fa9fb59a9df0e5ffe323fdff 100644 (file)
@@ -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 (file)
index 0000000..7530464
--- /dev/null
@@ -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 (file)
index 0000000..ffe2df4
--- /dev/null
@@ -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
index 20753638e2940734321bc63c3f731558c4af64b3..49742c3e04461aeb5fad6bee71fdbb8067a54c47 100644 (file)
@@ -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
 
index 8c4caf86716b50a2c1a7503642ebc912efd34302..cdfde3c61a54a5e058444a98a00ec611c8bcaf30 100644 (file)
@@ -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 (file)
index 0000000..5fe3aa3
--- /dev/null
@@ -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;
+}
index 781ec908d0644f64b358f23f53edb53e95cff8b9..528245363eeab941449605891360d565336447c2 100644 (file)
@@ -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);