summaryrefslogtreecommitdiff
path: root/vendor/github.com/tetratelabs/wazero/internal/platform/mmap_linux.go
blob: 55906e827e8bec23905fbfd2c220677c3f325a4e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package platform

import (
	"math/bits"
	"os"
	"sort"
	"strconv"
	"strings"
	"syscall"
)

const (
	// https://man7.org/linux/man-pages/man2/mmap.2.html
	__MAP_HUGE_SHIFT = 26
	__MAP_HUGETLB    = 0x40000
)

var hugePagesConfigs []hugePagesConfig

type hugePagesConfig struct {
	size int
	flag int
}

func (hpc *hugePagesConfig) match(size int) bool {
	return (size & (hpc.size - 1)) == 0
}

func init() {
	dirents, err := os.ReadDir("/sys/kernel/mm/hugepages/")
	if err != nil {
		return
	}

	for _, dirent := range dirents {
		name := dirent.Name()
		if !strings.HasPrefix(name, "hugepages-") {
			continue
		}
		if !strings.HasSuffix(name, "kB") {
			continue
		}
		n, err := strconv.ParseUint(name[10:len(name)-2], 10, 64)
		if err != nil {
			continue
		}
		if bits.OnesCount64(n) != 1 {
			continue
		}
		n *= 1024
		hugePagesConfigs = append(hugePagesConfigs, hugePagesConfig{
			size: int(n),
			flag: int(bits.TrailingZeros64(n)<<__MAP_HUGE_SHIFT) | __MAP_HUGETLB,
		})
	}

	sort.Slice(hugePagesConfigs, func(i, j int) bool {
		return hugePagesConfigs[i].size > hugePagesConfigs[j].size
	})
}

func mmapCodeSegment(size, prot int) ([]byte, error) {
	flags := syscall.MAP_ANON | syscall.MAP_PRIVATE

	for _, hugePagesConfig := range hugePagesConfigs {
		if hugePagesConfig.match(size) {
			b, err := syscall.Mmap(-1, 0, size, prot, flags|hugePagesConfig.flag)
			if err != nil {
				continue
			}
			return b, nil
		}
	}

	return syscall.Mmap(-1, 0, size, prot, flags)
}