modernc.org/memory@v1.8.0/mmap_unix.go (about)

     1  // Copyright 2011 Evan Shaw. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE-MMAP-GO file.
     4  
     5  //go:build darwin || dragonfly || freebsd || linux || (solaris && !illumos) || netbsd
     6  // +build darwin dragonfly freebsd linux solaris,!illumos netbsd
     7  
     8  // Modifications (c) 2017 The Memory Authors.
     9  
    10  package memory // import "modernc.org/memory"
    11  
    12  import (
    13  	"os"
    14  	"syscall"
    15  )
    16  
    17  const pageSizeLog = 20
    18  
    19  var (
    20  	osPageMask = osPageSize - 1
    21  	osPageSize = os.Getpagesize()
    22  )
    23  
    24  func unmap(addr uintptr, size int) error {
    25  	_, _, errno := syscall.Syscall(syscall.SYS_MUNMAP, addr, uintptr(size), 0)
    26  	if errno != 0 {
    27  		return errno
    28  	}
    29  
    30  	return nil
    31  }
    32  
    33  // pageSize aligned.
    34  func mmap(size int) (uintptr, int, error) {
    35  	size = roundup(size, osPageSize)
    36  
    37  	// The actual mmap syscall varies by architecture. mmapSyscall provides same
    38  	// functionality as the unexported funtion syscall.mmap and is declared in
    39  	// mmap_*_*.go and mmap_fallback.go. To add support for a new architecture,
    40  	// check function mmap in src/syscall/syscall_*_*.go or
    41  	// src/syscall/zsyscall_*_*.go in Go's source code.
    42  	p, err := mmapSyscall(0, uintptr(size+pageSize), syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_PRIVATE|syscall.MAP_ANON, -1, 0)
    43  	if err != nil {
    44  		return 0, 0, err
    45  	}
    46  
    47  	n := size + pageSize
    48  	if p&uintptr(osPageMask) != 0 {
    49  		panic("internal error")
    50  	}
    51  
    52  	mod := int(p) & pageMask
    53  	if mod != 0 {
    54  		m := pageSize - mod
    55  		if err := unmap(p, m); err != nil {
    56  			return 0, 0, err
    57  		}
    58  
    59  		n -= m
    60  		p += uintptr(m)
    61  	}
    62  
    63  	if p&uintptr(pageMask) != 0 {
    64  		panic("internal error")
    65  	}
    66  
    67  	if n-size != 0 {
    68  		if err := unmap(p+uintptr(size), n-size); err != nil {
    69  			return 0, 0, err
    70  		}
    71  	}
    72  
    73  	return p, size, nil
    74  }