OSDN Git Service

syscall: Fix errno handling in syscall.Syscall and friends.
[pf3gnuchains/gcc-fork.git] / libgo / go / syscall / syscall_unix.go
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // +build darwin freebsd linux netbsd openbsd
6
7 package syscall
8
9 import (
10         "runtime"
11         "sync"
12         "unsafe"
13 )
14
15 var (
16         Stdin  = 0
17         Stdout = 1
18         Stderr = 2
19 )
20
21 //extern syscall
22 func c_syscall32(trap int32, a1, a2, a3, a4, a5, a6 int32) int32
23
24 //extern syscall
25 func c_syscall64(trap int64, a1, a2, a3, a4, a5, a6 int64) int64
26
27 const darwinAMD64 = runtime.GOOS == "darwin" && runtime.GOARCH == "amd64"
28
29 // Do a system call.  We look at the size of uintptr to see how to pass
30 // the arguments, so that we don't pass a 64-bit value when the function
31 // expects a 32-bit one.
32 func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) {
33         Entersyscall()
34         SetErrno(0)
35         var r uintptr
36         if unsafe.Sizeof(r) == 4 {
37                 r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3), 0, 0, 0)
38                 r = uintptr(r1)
39         } else {
40                 r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3), 0, 0, 0)
41                 r = uintptr(r1)
42         }
43         err = GetErrno()
44         Exitsyscall()
45         return r, 0, err
46 }
47
48 func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) {
49         Entersyscall()
50         SetErrno(0)
51         var r uintptr
52         if unsafe.Sizeof(r) == 4 {
53                 r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3),
54                         int32(a4), int32(a5), int32(a6))
55                 r = uintptr(r1)
56         } else {
57                 r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3),
58                         int64(a4), int64(a5), int64(a6))
59                 r = uintptr(r1)
60         }
61         err = GetErrno()
62         Exitsyscall()
63         return r, 0, err
64 }
65
66 func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) {
67         var r uintptr
68         SetErrno(0)
69         if unsafe.Sizeof(r) == 4 {
70                 r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3), 0, 0, 0)
71                 r = uintptr(r1)
72         } else {
73                 r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3), 0, 0, 0)
74                 r = uintptr(r1)
75         }
76         err = GetErrno()
77         return r, 0, err
78 }
79
80 func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) {
81         var r uintptr
82         SetErrno(0)
83         if unsafe.Sizeof(r) == 4 {
84                 r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3),
85                         int32(a4), int32(a5), int32(a6))
86                 r = uintptr(r1)
87         } else {
88                 r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3),
89                         int64(a4), int64(a5), int64(a6))
90                 r = uintptr(r1)
91         }
92         err = GetErrno()
93         return r, 0, err
94 }
95
96 // Mmap manager, for use by operating system-specific implementations.
97 // Gccgo only has one implementation but we do this to correspond to gc.
98
99 type mmapper struct {
100         sync.Mutex
101         active map[*byte][]byte // active mappings; key is last byte in mapping
102         mmap   func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, error)
103         munmap func(addr uintptr, length uintptr) error
104 }
105
106 func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
107         if length <= 0 {
108                 return nil, EINVAL
109         }
110
111         // Map the requested memory.
112         addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset)
113         if errno != nil {
114                 return nil, errno
115         }
116
117         // Slice memory layout
118         var sl = struct {
119                 addr uintptr
120                 len  int
121                 cap  int
122         }{addr, length, length}
123
124         // Use unsafe to turn sl into a []byte.
125         b := *(*[]byte)(unsafe.Pointer(&sl))
126
127         // Register mapping in m and return it.
128         p := &b[cap(b)-1]
129         m.Lock()
130         defer m.Unlock()
131         m.active[p] = b
132         return b, nil
133 }
134
135 func (m *mmapper) Munmap(data []byte) (err error) {
136         if len(data) == 0 || len(data) != cap(data) {
137                 return EINVAL
138         }
139
140         // Find the base of the mapping.
141         p := &data[cap(data)-1]
142         m.Lock()
143         defer m.Unlock()
144         b := m.active[p]
145         if b == nil || &b[0] != &data[0] {
146                 return EINVAL
147         }
148
149         // Unmap the memory and update m.
150         if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != nil {
151                 return errno
152         }
153         m.active[p] = nil, false
154         return nil
155 }
156
157 var mapper = &mmapper{
158         active: make(map[*byte][]byte),
159         mmap:   mmap,
160         munmap: munmap,
161 }
162
163 func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
164         return mapper.Mmap(fd, offset, length, prot, flags)
165 }
166
167 func Munmap(b []byte) (err error) {
168         return mapper.Munmap(b)
169 }
170
171 // A Signal is a number describing a process signal.
172 // It implements the os.Signal interface.
173 type Signal int
174
175 func (s Signal) Signal() {}
176
177 func Signame(s Signal) string
178
179 func (s Signal) String() string {
180         return Signame(s)
181 }