src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

readv_unix.go (2581B)


      1 // Copyright 2026 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 darwin || linux || openbsd
      6 
      7 package unix
      8 
      9 import "unsafe"
     10 
     11 // minIovec is the size of the small initial allocation used by
     12 // Readv, Writev, etc.
     13 //
     14 // This small allocation gets stack allocated, which lets the
     15 // common use case of len(iovs) <= minIovec avoid more expensive
     16 // heap allocations.
     17 const minIovec = 8
     18 
     19 // appendBytes converts bs to Iovecs and appends them to vecs.
     20 func appendBytes(vecs []Iovec, bs [][]byte) []Iovec {
     21 	for _, b := range bs {
     22 		var v Iovec
     23 		v.SetLen(len(b))
     24 		if len(b) > 0 {
     25 			v.Base = &b[0]
     26 		} else {
     27 			v.Base = (*byte)(unsafe.Pointer(&_zero))
     28 		}
     29 		vecs = append(vecs, v)
     30 	}
     31 	return vecs
     32 }
     33 
     34 // writevRaceDetect tells the race detector that the program
     35 // has read the first n bytes stored in iovecs.
     36 func writevRaceDetect(iovecs []Iovec, n int) {
     37 	if !raceenabled {
     38 		return
     39 	}
     40 	for i := 0; n > 0 && i < len(iovecs); i++ {
     41 		m := min(int(iovecs[i].Len), n)
     42 		n -= m
     43 		if m > 0 {
     44 			raceReadRange(unsafe.Pointer(iovecs[i].Base), m)
     45 		}
     46 	}
     47 }
     48 
     49 // readvRaceDetect tells the race detector that the program
     50 // has written to the first n bytes stored in iovecs.
     51 func readvRaceDetect(iovecs []Iovec, n int, err error) {
     52 	if !raceenabled {
     53 		return
     54 	}
     55 	for i := 0; n > 0 && i < len(iovecs); i++ {
     56 		m := min(int(iovecs[i].Len), n)
     57 		n -= m
     58 		if m > 0 {
     59 			raceWriteRange(unsafe.Pointer(iovecs[i].Base), m)
     60 		}
     61 	}
     62 	if err == nil {
     63 		raceAcquire(unsafe.Pointer(&ioSync))
     64 	}
     65 }
     66 
     67 func Readv(fd int, iovs [][]byte) (n int, err error) {
     68 	iovecs := make([]Iovec, 0, minIovec)
     69 	iovecs = appendBytes(iovecs, iovs)
     70 	n, err = readv(fd, iovecs)
     71 	readvRaceDetect(iovecs, n, err)
     72 	return n, err
     73 }
     74 
     75 func Preadv(fd int, iovs [][]byte, offset int64) (n int, err error) {
     76 	iovecs := make([]Iovec, 0, minIovec)
     77 	iovecs = appendBytes(iovecs, iovs)
     78 	n, err = preadv(fd, iovecs, offset)
     79 	readvRaceDetect(iovecs, n, err)
     80 	return n, err
     81 }
     82 
     83 func Writev(fd int, iovs [][]byte) (n int, err error) {
     84 	iovecs := make([]Iovec, 0, minIovec)
     85 	iovecs = appendBytes(iovecs, iovs)
     86 	if raceenabled {
     87 		raceReleaseMerge(unsafe.Pointer(&ioSync))
     88 	}
     89 	n, err = writev(fd, iovecs)
     90 	writevRaceDetect(iovecs, n)
     91 	return n, err
     92 }
     93 
     94 func Pwritev(fd int, iovs [][]byte, offset int64) (n int, err error) {
     95 	iovecs := make([]Iovec, 0, minIovec)
     96 	iovecs = appendBytes(iovecs, iovs)
     97 	if raceenabled {
     98 		raceReleaseMerge(unsafe.Pointer(&ioSync))
     99 	}
    100 	n, err = pwritev(fd, iovecs, offset)
    101 	writevRaceDetect(iovecs, n)
    102 	return n, err
    103 }