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