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