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 aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
6
7package syscall
8
9import (
10	"internal/race"
11	"runtime"
12	"sync"
13	"unsafe"
14)
15
16var (
17	Stdin  = 0
18	Stdout = 1
19	Stderr = 2
20)
21
22const (
23	darwin64Bit    = runtime.GOOS == "darwin" && sizeofPtr == 8
24	dragonfly64Bit = runtime.GOOS == "dragonfly" && sizeofPtr == 8
25	netbsd32Bit    = runtime.GOOS == "netbsd" && sizeofPtr == 4
26	solaris64Bit   = runtime.GOOS == "solaris" && sizeofPtr == 8
27)
28
29// clen returns the index of the first NULL byte in n or len(n) if n contains no NULL byte.
30func clen(n []byte) int {
31	for i := 0; i < len(n); i++ {
32		if n[i] == 0 {
33			return i
34		}
35	}
36	return len(n)
37}
38
39// Mmap manager, for use by operating system-specific implementations.
40// Gccgo only has one implementation but we do this to correspond to gc.
41
42type mmapper struct {
43	sync.Mutex
44	active map[*byte][]byte // active mappings; key is last byte in mapping
45	mmap   func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, error)
46	munmap func(addr uintptr, length uintptr) error
47}
48
49func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
50	if length <= 0 {
51		return nil, EINVAL
52	}
53
54	// Map the requested memory.
55	addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset)
56	if errno != nil {
57		return nil, errno
58	}
59
60	// Slice memory layout
61	var sl = struct {
62		addr uintptr
63		len  int
64		cap  int
65	}{addr, length, length}
66
67	// Use unsafe to turn sl into a []byte.
68	b := *(*[]byte)(unsafe.Pointer(&sl))
69
70	// Register mapping in m and return it.
71	p := &b[cap(b)-1]
72	m.Lock()
73	defer m.Unlock()
74	m.active[p] = b
75	return b, nil
76}
77
78func (m *mmapper) Munmap(data []byte) (err error) {
79	if len(data) == 0 || len(data) != cap(data) {
80		return EINVAL
81	}
82
83	// Find the base of the mapping.
84	p := &data[cap(data)-1]
85	m.Lock()
86	defer m.Unlock()
87	b := m.active[p]
88	if b == nil || &b[0] != &data[0] {
89		return EINVAL
90	}
91
92	// Unmap the memory and update m.
93	if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != nil {
94		return errno
95	}
96	delete(m.active, p)
97	return nil
98}
99
100var mapper = &mmapper{
101	active: make(map[*byte][]byte),
102	mmap:   mmap,
103	munmap: munmap,
104}
105
106func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
107	return mapper.Mmap(fd, offset, length, prot, flags)
108}
109
110func Munmap(b []byte) (err error) {
111	return mapper.Munmap(b)
112}
113
114// Do the interface allocations only once for common
115// Errno values.
116var (
117	errEAGAIN error = EAGAIN
118	errEINVAL error = EINVAL
119	errENOENT error = ENOENT
120)
121
122// errnoErr returns common boxed Errno values, to prevent
123// allocations at runtime.
124func errnoErr(e Errno) error {
125	switch e {
126	case 0:
127		return nil
128	case EAGAIN:
129		return errEAGAIN
130	case EINVAL:
131		return errEINVAL
132	case ENOENT:
133		return errENOENT
134	}
135	return e
136}
137
138// A Signal is a number describing a process signal.
139// It implements the os.Signal interface.
140type Signal int
141
142func (s Signal) Signal() {}
143
144func Signame(s Signal) string
145
146func (s Signal) String() string {
147	return Signame(s)
148}
149
150func Read(fd int, p []byte) (n int, err error) {
151	n, err = read(fd, p)
152	if race.Enabled {
153		if n > 0 {
154			race.WriteRange(unsafe.Pointer(&p[0]), n)
155		}
156		if err == nil {
157			race.Acquire(unsafe.Pointer(&ioSync))
158		}
159	}
160	if msanenabled && n > 0 {
161		msanWrite(unsafe.Pointer(&p[0]), n)
162	}
163	return
164}
165
166func Write(fd int, p []byte) (n int, err error) {
167	if race.Enabled {
168		race.ReleaseMerge(unsafe.Pointer(&ioSync))
169	}
170	n, err = write(fd, p)
171	if race.Enabled && n > 0 {
172		race.ReadRange(unsafe.Pointer(&p[0]), n)
173	}
174	if msanenabled && n > 0 {
175		msanRead(unsafe.Pointer(&p[0]), n)
176	}
177	return
178}
179
180var ioSync int64
181