1package platform
2
3import (
4 "math/bits"
5 "os"
6 "sort"
7 "strconv"
8 "strings"
9 "syscall"
10)
11
12const (
13 // https://man7.org/linux/man-pages/man2/mmap.2.html
14 __MAP_HUGE_SHIFT = 26
15 __MAP_HUGETLB = 0x40000
16)
17
18var hugePagesConfigs []hugePagesConfig
19
20type hugePagesConfig struct {
21 size int
22 flag int
23}
24
25func (hpc *hugePagesConfig) match(size int) bool {
26 return (size & (hpc.size - 1)) == 0
27}
28
29func 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
62func 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}