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