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//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris 6// +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris 7 8package syscall 9 10import ( 11 "internal/race" 12 "internal/unsafeheader" 13 "runtime" 14 "sync" 15 "unsafe" 16) 17 18var ( 19 Stdin = 0 20 Stdout = 1 21 Stderr = 2 22) 23 24const ( 25 darwin64Bit = (runtime.GOOS == "darwin" || runtime.GOOS == "ios") && sizeofPtr == 8 26 netbsd32Bit = runtime.GOOS == "netbsd" && sizeofPtr == 4 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 // Use unsafe to turn addr into a []byte. 61 var b []byte 62 hdr := (*unsafeheader.Slice)(unsafe.Pointer(&b)) 63 hdr.Data = unsafe.Pointer(addr) 64 hdr.Cap = length 65 hdr.Len = length 66 67 // Register mapping in m and return it. 68 p := &b[cap(b)-1] 69 m.Lock() 70 defer m.Unlock() 71 m.active[p] = b 72 return b, nil 73} 74 75func (m *mmapper) Munmap(data []byte) (err error) { 76 if len(data) == 0 || len(data) != cap(data) { 77 return EINVAL 78 } 79 80 // Find the base of the mapping. 81 p := &data[cap(data)-1] 82 m.Lock() 83 defer m.Unlock() 84 b := m.active[p] 85 if b == nil || &b[0] != &data[0] { 86 return EINVAL 87 } 88 89 // Unmap the memory and update m. 90 if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != nil { 91 return errno 92 } 93 delete(m.active, p) 94 return nil 95} 96 97var mapper = &mmapper{ 98 active: make(map[*byte][]byte), 99 mmap: mmap, 100 munmap: munmap, 101} 102 103func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { 104 return mapper.Mmap(fd, offset, length, prot, flags) 105} 106 107func Munmap(b []byte) (err error) { 108 return mapper.Munmap(b) 109} 110 111// Do the interface allocations only once for common 112// Errno values. 113var ( 114 errEAGAIN error = EAGAIN 115 errEINVAL error = EINVAL 116 errENOENT error = ENOENT 117) 118 119// errnoErr returns common boxed Errno values, to prevent 120// allocations at runtime. 121func errnoErr(e Errno) error { 122 switch e { 123 case 0: 124 return nil 125 case EAGAIN: 126 return errEAGAIN 127 case EINVAL: 128 return errEINVAL 129 case ENOENT: 130 return errENOENT 131 } 132 return e 133} 134 135// A Signal is a number describing a process signal. 136// It implements the os.Signal interface. 137type Signal int 138 139func (s Signal) Signal() {} 140 141func Signame(s Signal) string 142 143func (s Signal) String() string { 144 return Signame(s) 145} 146 147func Read(fd int, p []byte) (n int, err error) { 148 n, err = read(fd, p) 149 if race.Enabled { 150 if n > 0 { 151 race.WriteRange(unsafe.Pointer(&p[0]), n) 152 } 153 if err == nil { 154 race.Acquire(unsafe.Pointer(&ioSync)) 155 } 156 } 157 if msanenabled && n > 0 { 158 msanWrite(unsafe.Pointer(&p[0]), n) 159 } 160 return 161} 162 163func Write(fd int, p []byte) (n int, err error) { 164 if race.Enabled { 165 race.ReleaseMerge(unsafe.Pointer(&ioSync)) 166 } 167 if faketime && (fd == 1 || fd == 2) { 168 n = faketimeWrite(fd, p) 169 if n < 0 { 170 n, err = 0, errnoErr(Errno(-n)) 171 } 172 } else { 173 n, err = write(fd, p) 174 } 175 if race.Enabled && n > 0 { 176 race.ReadRange(unsafe.Pointer(&p[0]), n) 177 } 178 if msanenabled && n > 0 { 179 msanRead(unsafe.Pointer(&p[0]), n) 180 } 181 return 182} 183 184var ioSync int64 185