modernc.org/memory@v1.8.0/mmap_openbsd.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  // Modifications (c) 2024 The Memory Authors.
     6  // Copyright 2024 The Memory Authors. All rights reserved.
     7  // Use of this source code is governed by a BSD-style
     8  // license that can be found in the LICENSE file.
     9  
    10  //go:build openbsd && (386 || amd64 || arm64)
    11  
    12  package memory
    13  
    14  import (
    15  	"fmt"
    16  	"os"
    17  	"sync"
    18  	"unsafe"
    19  
    20  	"golang.org/x/sys/unix"
    21  )
    22  
    23  // track what can be unmapped
    24  var allocmap map[uintptr][]byte
    25  var m sync.Mutex
    26  
    27  const pageSizeLog = 20
    28  
    29  var (
    30  	osPageMask = osPageSize - 1
    31  	osPageSize = os.Getpagesize()
    32  )
    33  
    34  func init() {
    35  	allocmap = make(map[uintptr][]byte)
    36  }
    37  
    38  func unmap(addr uintptr, size int) error {
    39  	if trace {
    40  		fmt.Fprintf(os.Stderr, "unmap %#x\n", addr)
    41  	}
    42  
    43  	a, ok := allocmap[addr]
    44  	if !ok {
    45  		if trace {
    46  			fmt.Fprintf(os.Stderr, "unmap %#x: not found\n", addr)
    47  		}
    48  		// panic("unmap called on unknown mapping")
    49  		return nil
    50  	}
    51  
    52  	if err := unix.Munmap(a); err != nil {
    53  		if trace {
    54  			fmt.Fprintf(os.Stderr, "unmap: %s\n", err.Error())
    55  		}
    56  		// panic(err.Error())
    57  		return err
    58  	}
    59  
    60  	m.Lock()
    61  	delete(allocmap, addr)
    62  	m.Unlock()
    63  
    64  	return nil
    65  }
    66  
    67  func mmap(size int) (uintptr, int, error) {
    68  	roundsize := roundup(size, osPageSize) + pageSize
    69  
    70  	b, err := unix.Mmap(-1, 0, roundsize, unix.PROT_READ|unix.PROT_WRITE, unix.MAP_PRIVATE|unix.MAP_ANON)
    71  	if err != nil {
    72  		return 0, 0, err
    73  	}
    74  
    75  	p := uintptr(unsafe.Pointer(&b[0]))
    76  
    77  	if trace {
    78  		fmt.Fprintf(os.Stderr, "mmap actual @%#x size: %#x\n", p, roundsize)
    79  	}
    80  
    81  	// waste all the space until the next page
    82  	r := (p + uintptr(pageSize)) &^ uintptr(pageMask)
    83  	nsize := (roundsize) - int((r - p))
    84  	if nsize < size {
    85  		panic("didn't allocate enough to meet initial request!")
    86  	}
    87  
    88  	if trace {
    89  		fmt.Fprintf(os.Stderr, "mmap page-rounded @%#x size: %#x\n", r, nsize)
    90  	}
    91  
    92  	m.Lock()
    93  	allocmap[r] = b
    94  	m.Unlock()
    95  
    96  	return r, nsize, nil
    97  }