github.com/cznic/memory@v0.0.0-20181122101858-44f9dcde99e8/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  // +build darwin dragonfly freebsd linux openbsd solaris netbsd
     6  
     7  // Modifications (c) 2017 The Memory Authors.
     8  
     9  package memory
    10  
    11  import (
    12  	"syscall"
    13  	"unsafe"
    14  )
    15  
    16  var pageSize = 1 << 20
    17  
    18  func unmap(addr uintptr, size int) error {
    19  	_, _, errno := syscall.Syscall(syscall.SYS_MUNMAP, addr, uintptr(size), 0)
    20  	if errno != 0 {
    21  		return errno
    22  	}
    23  
    24  	return nil
    25  }
    26  
    27  // pageSize aligned.
    28  func mmap(size int) (uintptr, int, error) {
    29  	size = roundup(size, osPageSize)
    30  	b, err := syscall.Mmap(-1, 0, size+pageSize, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED|syscall.MAP_ANON)
    31  	if err != nil {
    32  		return 0, 0, err
    33  	}
    34  
    35  	n := len(b)
    36  	p := uintptr(unsafe.Pointer(&b[0]))
    37  	if p&uintptr(osPageMask) != 0 {
    38  		panic("internal error")
    39  	}
    40  
    41  	mod := int(p) & pageMask
    42  	if mod != 0 {
    43  		m := pageSize - mod
    44  		if err := unmap(p, m); err != nil {
    45  			return 0, 0, err
    46  		}
    47  
    48  		b = b[m:]
    49  		n -= m
    50  		p += uintptr(m)
    51  	}
    52  
    53  	if p&uintptr(pageMask) != 0 {
    54  		panic("internal error")
    55  	}
    56  
    57  	if n-size != 0 {
    58  		if err := unmap(p+uintptr(size), n-size); err != nil {
    59  			return 0, 0, err
    60  		}
    61  	}
    62  
    63  	return p, size, nil
    64  }