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