123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- // Copyright 2009 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- //go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
- package syscall
- import (
- "internal/race"
- "internal/unsafeheader"
- "runtime"
- "sync"
- "unsafe"
- )
- var (
- Stdin = 0
- Stdout = 1
- Stderr = 2
- )
- const (
- darwin64Bit = (runtime.GOOS == "darwin" || runtime.GOOS == "ios") && sizeofPtr == 8
- netbsd32Bit = runtime.GOOS == "netbsd" && sizeofPtr == 4
- )
- // clen returns the index of the first NULL byte in n or len(n) if n contains no NULL byte.
- func clen(n []byte) int {
- for i := 0; i < len(n); i++ {
- if n[i] == 0 {
- return i
- }
- }
- return len(n)
- }
- // Mmap manager, for use by operating system-specific implementations.
- // Gccgo only has one implementation but we do this to correspond to gc.
- type mmapper struct {
- sync.Mutex
- active map[*byte][]byte // active mappings; key is last byte in mapping
- mmap func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, error)
- munmap func(addr uintptr, length uintptr) error
- }
- func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
- if length <= 0 {
- return nil, EINVAL
- }
- // Map the requested memory.
- addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset)
- if errno != nil {
- return nil, errno
- }
- // Use unsafe to turn addr into a []byte.
- var b []byte
- hdr := (*unsafeheader.Slice)(unsafe.Pointer(&b))
- hdr.Data = unsafe.Pointer(addr)
- hdr.Cap = length
- hdr.Len = length
- // Register mapping in m and return it.
- p := &b[cap(b)-1]
- m.Lock()
- defer m.Unlock()
- m.active[p] = b
- return b, nil
- }
- func (m *mmapper) Munmap(data []byte) (err error) {
- if len(data) == 0 || len(data) != cap(data) {
- return EINVAL
- }
- // Find the base of the mapping.
- p := &data[cap(data)-1]
- m.Lock()
- defer m.Unlock()
- b := m.active[p]
- if b == nil || &b[0] != &data[0] {
- return EINVAL
- }
- // Unmap the memory and update m.
- if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != nil {
- return errno
- }
- delete(m.active, p)
- return nil
- }
- var mapper = &mmapper{
- active: make(map[*byte][]byte),
- mmap: mmap,
- munmap: munmap,
- }
- func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
- return mapper.Mmap(fd, offset, length, prot, flags)
- }
- func Munmap(b []byte) (err error) {
- return mapper.Munmap(b)
- }
- // Do the interface allocations only once for common
- // Errno values.
- var (
- errEAGAIN error = EAGAIN
- errEINVAL error = EINVAL
- errENOENT error = ENOENT
- )
- // errnoErr returns common boxed Errno values, to prevent
- // allocations at runtime.
- func errnoErr(e Errno) error {
- switch e {
- case 0:
- return nil
- case EAGAIN:
- return errEAGAIN
- case EINVAL:
- return errEINVAL
- case ENOENT:
- return errENOENT
- }
- return e
- }
- // A Signal is a number describing a process signal.
- // It implements the os.Signal interface.
- type Signal int
- func (s Signal) Signal() {}
- func Signame(s Signal) string
- func (s Signal) String() string {
- return Signame(s)
- }
- func Read(fd int, p []byte) (n int, err error) {
- n, err = read(fd, p)
- if race.Enabled {
- if n > 0 {
- race.WriteRange(unsafe.Pointer(&p[0]), n)
- }
- if err == nil {
- race.Acquire(unsafe.Pointer(&ioSync))
- }
- }
- if msanenabled && n > 0 {
- msanWrite(unsafe.Pointer(&p[0]), n)
- }
- if asanenabled && n > 0 {
- asanWrite(unsafe.Pointer(&p[0]), n)
- }
- return
- }
- func Write(fd int, p []byte) (n int, err error) {
- if race.Enabled {
- race.ReleaseMerge(unsafe.Pointer(&ioSync))
- }
- if faketime && (fd == 1 || fd == 2) {
- n = faketimeWrite(fd, p)
- if n < 0 {
- n, err = 0, errnoErr(Errno(-n))
- }
- } else {
- n, err = write(fd, p)
- }
- if race.Enabled && n > 0 {
- race.ReadRange(unsafe.Pointer(&p[0]), n)
- }
- if msanenabled && n > 0 {
- msanRead(unsafe.Pointer(&p[0]), n)
- }
- if asanenabled && n > 0 {
- asanRead(unsafe.Pointer(&p[0]), n)
- }
- return
- }
- var ioSync int64
|