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