1 /* Huge Page support. Linux implementation.
2 Copyright (C) 2021-2023 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 __close_nocancel (fd
);
66 if (s
== sizeof (mode_always
) - 1)
68 if (strcmp (str
, mode_always
) == 0)
69 return malloc_thp_mode_always
;
70 else if (strcmp (str
, mode_madvise
) == 0)
71 return malloc_thp_mode_madvise
;
72 else if (strcmp (str
, mode_never
) == 0)
73 return malloc_thp_mode_never
;
75 return malloc_thp_mode_not_supported
;
79 malloc_default_hugepage_size (void)
81 int fd
= __open64_nocancel ("/proc/meminfo", O_RDONLY
);
91 ssize_t r
= __pread64_nocancel (fd
, buf
, sizeof (buf
) - 1, off
);
96 /* If the tag is not found, read the last line again. */
97 const char *s
= strstr (buf
, "Hugepagesize:");
100 char *nl
= strrchr (buf
, '\n');
103 off
+= (nl
+ 1) - buf
;
107 /* The default huge page size is in the form:
108 Hugepagesize: NUMBER kB */
109 s
+= sizeof ("Hugepagesize: ") - 1;
110 for (int i
= 0; (s
[i
] >= '0' && s
[i
] <= '9') || s
[i
] == ' '; i
++)
115 hpsize
+= s
[i
] - '0';
121 __close_nocancel (fd
);
127 hugepage_flags (size_t pagesize
)
129 return MAP_HUGETLB
| (__builtin_ctzll (pagesize
) << MAP_HUGE_SHIFT
);
133 __malloc_hugepage_config (size_t requested
, size_t *pagesize
, int *flags
)
140 *pagesize
= malloc_default_hugepage_size ();
142 *flags
= hugepage_flags (*pagesize
);
146 /* Each entry represents a supported huge page in the form of:
147 hugepages-<size>kB. */
148 int dirfd
= __open64_nocancel ("/sys/kernel/mm/hugepages",
149 O_RDONLY
| O_DIRECTORY
, 0);
157 # define __getdents64 getdents64
159 ssize_t ret
= __getdents64 (dirfd
, buffer
, sizeof (buffer
));
166 char *begin
= buffer
, *end
= buffer
+ ret
;
169 unsigned short int d_reclen
;
170 memcpy (&d_reclen
, begin
+ offsetof (struct dirent64
, d_reclen
),
172 const char *dname
= begin
+ offsetof (struct dirent64
, d_name
);
176 || strncmp (dname
, "hugepages-", sizeof ("hugepages-") - 1) != 0)
180 const char *sizestr
= dname
+ sizeof ("hugepages-") - 1;
181 for (int i
= 0; sizestr
[i
] >= '0' && sizestr
[i
] <= '9'; i
++)
184 hpsize
+= sizestr
[i
] - '0';
188 if (hpsize
== requested
)
191 *flags
= hugepage_flags (*pagesize
);
200 __close_nocancel (dirfd
);