1 /** @file
2
3 @section license License
4
5 Licensed to the Apache Software Foundation (ASF) under one
6 or more contributor license agreements. See the NOTICE file
7 distributed with this work for additional information
8 regarding copyright ownership. The ASF licenses this file
9 to you under the Apache License, Version 2.0 (the
10 "License"); you may not use this file except in compliance
11 with the License. You may obtain a copy of the License at
12
13 http://www.apache.org/licenses/LICENSE-2.0
14
15 Unless required by applicable law or agreed to in writing, software
16 distributed under the License is distributed on an "AS IS" BASIS,
17 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 See the License for the specific language governing permissions and
19 limitations under the License.
20 */
21
22 #include <cstdio>
23 #include <sys/mman.h>
24 #include "tscore/Diags.h"
25 #include "tscore/ink_align.h"
26
27 #define DEBUG_TAG "hugepages"
28
29 #ifdef MAP_HUGETLB
30 #define MEMINFO_PATH "/proc/meminfo"
31 #define LINE_SIZE 256
32 #define TOKEN "Hugepagesize:"
33 #define TOKEN_SIZE (strlen(TOKEN))
34
35 static int hugepage_size = -1;
36 static bool hugepage_enabled;
37 #endif
38
39 size_t
ats_hugepage_size()40 ats_hugepage_size()
41 {
42 #ifdef MAP_HUGETLB
43 return hugepage_size;
44 #else
45 Debug(DEBUG_TAG, "MAP_HUGETLB not defined");
46 return 0;
47 #endif
48 }
49
50 bool
ats_hugepage_enabled()51 ats_hugepage_enabled()
52 {
53 #ifdef MAP_HUGETLB
54 return hugepage_enabled;
55 #else
56 return false;
57 #endif
58 }
59
60 void
ats_hugepage_init(int enabled)61 ats_hugepage_init(int enabled)
62 {
63 #ifdef MAP_HUGETLB
64 FILE *fp;
65 char line[LINE_SIZE];
66 char *p, *ep;
67
68 hugepage_size = 0;
69
70 if (!enabled) {
71 Debug(DEBUG_TAG "_init", "hugepages not enabled");
72 return;
73 }
74
75 fp = fopen(MEMINFO_PATH, "r");
76
77 if (fp == nullptr) {
78 Debug(DEBUG_TAG "_init", "Cannot open file %s", MEMINFO_PATH);
79 return;
80 }
81
82 while (fgets(line, sizeof(line), fp)) {
83 if (strncmp(line, TOKEN, TOKEN_SIZE) == 0) {
84 p = line + TOKEN_SIZE;
85 while (*p == ' ') {
86 p++;
87 }
88 hugepage_size = strtol(p, &ep, 10);
89 // What other values can this be?
90 if (strncmp(ep, " kB", 4)) {
91 hugepage_size *= 1024;
92 }
93 break;
94 }
95 }
96
97 fclose(fp);
98
99 if (hugepage_size) {
100 hugepage_enabled = true;
101 }
102
103 Debug(DEBUG_TAG "_init", "Hugepage size = %d", hugepage_size);
104 #else
105 Debug(DEBUG_TAG "_init", "MAP_HUGETLB not defined");
106 #endif
107 }
108
109 void *
ats_alloc_hugepage(size_t s)110 ats_alloc_hugepage(size_t s)
111 {
112 #ifdef MAP_HUGETLB
113 size_t size;
114 void *mem;
115
116 size = INK_ALIGN(s, ats_hugepage_size());
117
118 mem = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0);
119
120 if (mem == MAP_FAILED) {
121 Debug(DEBUG_TAG, "Could not allocate hugepages size = %zu", size);
122 return nullptr;
123 }
124
125 Debug(DEBUG_TAG, "Request/Allocation (%zu/%zu) {%p}", s, size, mem);
126 return mem;
127 #else
128 (void)s;
129 Debug(DEBUG_TAG, "MAP_HUGETLB not defined");
130 return nullptr;
131 #endif
132 }
133
134 bool
ats_free_hugepage(void * ptr,size_t s)135 ats_free_hugepage(void *ptr, size_t s)
136 {
137 #ifdef MAP_HUGETLB
138 size_t size;
139
140 size = INK_ALIGN(s, ats_hugepage_size());
141 return (munmap(ptr, size) == 0);
142 #else
143 (void)ptr;
144 (void)s;
145 Debug(DEBUG_TAG, "MAP_HUGETLB not defined");
146 return false;
147 #endif
148 }
149