Source file src/cmd/internal/bio/buf_mmap.go

     1  // Copyright 2019 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 || dragonfly || freebsd || linux || netbsd || openbsd
     6  // +build darwin dragonfly freebsd linux netbsd openbsd
     7  
     8  package bio
     9  
    10  import (
    11  	"runtime"
    12  	"sync/atomic"
    13  	"syscall"
    14  )
    15  
    16  // mmapLimit is the maximum number of mmaped regions to create before
    17  // falling back to reading into a heap-allocated slice. This exists
    18  // because some operating systems place a limit on the number of
    19  // distinct mapped regions per process. As of this writing:
    20  //
    21  //  Darwin    unlimited
    22  //  DragonFly   1000000 (vm.max_proc_mmap)
    23  //  FreeBSD   unlimited
    24  //  Linux         65530 (vm.max_map_count) // TODO: query /proc/sys/vm/max_map_count?
    25  //  NetBSD    unlimited
    26  //  OpenBSD   unlimited
    27  var mmapLimit int32 = 1<<31 - 1
    28  
    29  func init() {
    30  	// Linux is the only practically concerning OS.
    31  	if runtime.GOOS == "linux" {
    32  		mmapLimit = 30000
    33  	}
    34  }
    35  
    36  func (r *Reader) sliceOS(length uint64) ([]byte, bool) {
    37  	// For small slices, don't bother with the overhead of a
    38  	// mapping, especially since we have no way to unmap it.
    39  	const threshold = 16 << 10
    40  	if length < threshold {
    41  		return nil, false
    42  	}
    43  
    44  	// Have we reached the mmap limit?
    45  	if atomic.AddInt32(&mmapLimit, -1) < 0 {
    46  		atomic.AddInt32(&mmapLimit, 1)
    47  		return nil, false
    48  	}
    49  
    50  	// Page-align the offset.
    51  	off := r.Offset()
    52  	align := syscall.Getpagesize()
    53  	aoff := off &^ int64(align-1)
    54  
    55  	data, err := syscall.Mmap(int(r.f.Fd()), aoff, int(length+uint64(off-aoff)), syscall.PROT_READ, syscall.MAP_SHARED|syscall.MAP_FILE)
    56  	if err != nil {
    57  		return nil, false
    58  	}
    59  
    60  	data = data[off-aoff:]
    61  	r.MustSeek(int64(length), 1)
    62  	return data, true
    63  }
    64  

View as plain text