1 /* Huge Page support. Linux implementation.
2 Copyright (C) 2021-2024 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public License as
7 published by the Free Software Foundation; either version 2.1 of the
8 License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If
17 not, see <https://www.gnu.org/licenses/>. */
21 #include <malloc-hugepages.h>
22 #include <not-cancel.h>
26 __malloc_default_thp_pagesize (void)
28 int fd
= __open64_nocancel (
29 "/sys/kernel/mm/transparent_hugepage/hpage_pmd_size", O_RDONLY
);
33 char str
[INT_BUFSIZE_BOUND (unsigned long int)];
34 ssize_t s
= __read_nocancel (fd
, str
, sizeof (str
));
35 __close_nocancel (fd
);
39 unsigned long int r
= 0;
40 for (ssize_t i
= 0; i
< s
; i
++)
50 enum malloc_thp_mode_t
51 __malloc_thp_mode (void)
53 int fd
= __open64_nocancel ("/sys/kernel/mm/transparent_hugepage/enabled",
56 return malloc_thp_mode_not_supported
;
58 static const char mode_always
[] = "[always] madvise never\n";
59 static const char mode_madvise
[] = "always [madvise] never\n";
60 static const char mode_never
[] = "always madvise [never]\n";
62 char str
[sizeof(mode_always
)];
63 ssize_t s
= __read_nocancel (fd
, str
, sizeof (str
));
64 if (s
>= sizeof str
|| s
< 0)
65 return malloc_thp_mode_not_supported
;
67 __close_nocancel (fd
);
69 if (s
== sizeof (mode_always
) - 1)
71 if (strcmp (str
, mode_always
) == 0)
72 return malloc_thp_mode_always
;
73 else if (strcmp (str
, mode_madvise
) == 0)
74 return malloc_thp_mode_madvise
;
75 else if (strcmp (str
, mode_never
) == 0)
76 return malloc_thp_mode_never
;
78 return malloc_thp_mode_not_supported
;
82 malloc_default_hugepage_size (void)
84 int fd
= __open64_nocancel ("/proc/meminfo", O_RDONLY
);
94 ssize_t r
= __pread64_nocancel (fd
, buf
, sizeof (buf
) - 1, off
);
99 /* If the tag is not found, read the last line again. */
100 const char *s
= strstr (buf
, "Hugepagesize:");
103 char *nl
= strrchr (buf
, '\n');
106 off
+= (nl
+ 1) - buf
;
110 /* The default huge page size is in the form:
111 Hugepagesize: NUMBER kB */
112 s
+= sizeof ("Hugepagesize: ") - 1;
113 for (int i
= 0; (s
[i
] >= '0' && s
[i
] <= '9') || s
[i
] == ' '; i
++)
118 hpsize
+= s
[i
] - '0';
124 __close_nocancel (fd
);
130 hugepage_flags (size_t pagesize
)
132 return MAP_HUGETLB
| (__builtin_ctzll (pagesize
) << MAP_HUGE_SHIFT
);
136 __malloc_hugepage_config (size_t requested
, size_t *pagesize
, int *flags
)
143 *pagesize
= malloc_default_hugepage_size ();
145 *flags
= hugepage_flags (*pagesize
);
149 /* Each entry represents a supported huge page in the form of:
150 hugepages-<size>kB. */
151 int dirfd
= __open64_nocancel ("/sys/kernel/mm/hugepages",
152 O_RDONLY
| O_DIRECTORY
, 0);
160 # define __getdents64 getdents64
162 ssize_t ret
= __getdents64 (dirfd
, buffer
, sizeof (buffer
));
169 char *begin
= buffer
, *end
= buffer
+ ret
;
172 unsigned short int d_reclen
;
173 memcpy (&d_reclen
, begin
+ offsetof (struct dirent64
, d_reclen
),
175 const char *dname
= begin
+ offsetof (struct dirent64
, d_name
);
179 || strncmp (dname
, "hugepages-", sizeof ("hugepages-") - 1) != 0)
183 const char *sizestr
= dname
+ sizeof ("hugepages-") - 1;
184 for (int i
= 0; sizestr
[i
] >= '0' && sizestr
[i
] <= '9'; i
++)
187 hpsize
+= sizestr
[i
] - '0';
191 if (hpsize
== requested
)
194 *flags
= hugepage_flags (*pagesize
);
203 __close_nocancel (dirfd
);