github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/internal/platform/mmap_linux.go (about)

     1  package platform
     2  
     3  import (
     4  	"math/bits"
     5  	"os"
     6  	"sort"
     7  	"strconv"
     8  	"strings"
     9  	"syscall"
    10  )
    11  
    12  const (
    13  	// https://man7.org/linux/man-pages/man2/mmap.2.html
    14  	__MAP_HUGE_SHIFT = 26
    15  	__MAP_HUGETLB    = 0x40000
    16  )
    17  
    18  var hugePagesConfigs []hugePagesConfig
    19  
    20  type hugePagesConfig struct {
    21  	size int
    22  	flag int
    23  }
    24  
    25  func (hpc *hugePagesConfig) match(size int) bool {
    26  	return (size & (hpc.size - 1)) == 0
    27  }
    28  
    29  func init() {
    30  	dirents, err := os.ReadDir("/sys/kernel/mm/hugepages/")
    31  	if err != nil {
    32  		return
    33  	}
    34  
    35  	for _, dirent := range dirents {
    36  		name := dirent.Name()
    37  		if !strings.HasPrefix(name, "hugepages-") {
    38  			continue
    39  		}
    40  		if !strings.HasSuffix(name, "kB") {
    41  			continue
    42  		}
    43  		n, err := strconv.ParseUint(name[10:len(name)-2], 10, 64)
    44  		if err != nil {
    45  			continue
    46  		}
    47  		if bits.OnesCount64(n) != 1 {
    48  			continue
    49  		}
    50  		n *= 1024
    51  		hugePagesConfigs = append(hugePagesConfigs, hugePagesConfig{
    52  			size: int(n),
    53  			flag: int(bits.TrailingZeros64(n)<<__MAP_HUGE_SHIFT) | __MAP_HUGETLB,
    54  		})
    55  	}
    56  
    57  	sort.Slice(hugePagesConfigs, func(i, j int) bool {
    58  		return hugePagesConfigs[i].size > hugePagesConfigs[j].size
    59  	})
    60  }
    61  
    62  func mmapCodeSegment(size, prot int) ([]byte, error) {
    63  	flags := syscall.MAP_ANON | syscall.MAP_PRIVATE
    64  
    65  	for _, hugePagesConfig := range hugePagesConfigs {
    66  		if hugePagesConfig.match(size) {
    67  			b, err := syscall.Mmap(-1, 0, size, prot, flags|hugePagesConfig.flag)
    68  			if err != nil {
    69  				continue
    70  			}
    71  			return b, nil
    72  		}
    73  	}
    74  
    75  	return syscall.Mmap(-1, 0, size, prot, flags)
    76  }