modernc.org/memory@v1.6.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 || openbsd || (solaris && !illumos) || netbsd
     6  // +build darwin dragonfly freebsd linux openbsd 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  	// The actual mmap syscall varies by architecture. mmapSyscall provides same
    37  	// functionality as the unexported funtion syscall.mmap and is declared in
    38  	// mmap_*_*.go and mmap_fallback.go. To add support for a new architecture,
    39  	// check function mmap in src/syscall/syscall_*_*.go or
    40  	// src/syscall/zsyscall_*_*.go in Go's source code.
    41  	p, err := mmapSyscall(0, uintptr(size+pageSize), syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_PRIVATE|syscall.MAP_ANON, -1, 0)
    42  	if err != nil {
    43  		return 0, 0, err
    44  	}
    45  
    46  	n := size + pageSize
    47  	if p&uintptr(osPageMask) != 0 {
    48  		panic("internal error")
    49  	}
    50  
    51  	mod := int(p) & pageMask
    52  	if mod != 0 {
    53  		m := pageSize - mod
    54  		if err := unmap(p, m); err != nil {
    55  			return 0, 0, err
    56  		}
    57  
    58  		n -= m
    59  		p += uintptr(m)
    60  	}
    61  
    62  	if p&uintptr(pageMask) != 0 {
    63  		panic("internal error")
    64  	}
    65  
    66  	if n-size != 0 {
    67  		if err := unmap(p+uintptr(size), n-size); err != nil {
    68  			return 0, 0, err
    69  		}
    70  	}
    71  
    72  	return p, size, nil
    73  }