1/*
2 * Copyright 2013-present Facebook, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <folly/concurrency/CacheLocality.h>
18
19#include <folly/portability/GTest.h>
20
21#include <glog/logging.h>
22#include <memory>
23#include <thread>
24#include <unordered_map>
25
26using namespace folly;
27
28/// This is the relevant nodes from a production box's sysfs tree. If you
29/// think this map is ugly you should see the version of this test that
30/// used a real directory tree. To reduce the chance of testing error
31/// I haven't tried to remove the common prefix
32static std::unordered_map<std::string, std::string> fakeSysfsTree = {
33 {"/sys/devices/system/cpu/cpu0/cache/index0/shared_cpu_list", "0,17"},
34 {"/sys/devices/system/cpu/cpu0/cache/index0/type", "Data"},
35 {"/sys/devices/system/cpu/cpu0/cache/index1/shared_cpu_list", "0,17"},
36 {"/sys/devices/system/cpu/cpu0/cache/index1/type", "Instruction"},
37 {"/sys/devices/system/cpu/cpu0/cache/index2/shared_cpu_list", "0,17"},
38 {"/sys/devices/system/cpu/cpu0/cache/index2/type", "Unified"},
39 {"/sys/devices/system/cpu/cpu0/cache/index3/shared_cpu_list", "0-8,17-23"},
40 {"/sys/devices/system/cpu/cpu0/cache/index3/type", "Unified"},
41 {"/sys/devices/system/cpu/cpu1/cache/index0/shared_cpu_list", "1,18"},
42 {"/sys/devices/system/cpu/cpu1/cache/index0/type", "Data"},
43 {"/sys/devices/system/cpu/cpu1/cache/index1/shared_cpu_list", "1,18"},
44 {"/sys/devices/system/cpu/cpu1/cache/index1/type", "Instruction"},
45 {"/sys/devices/system/cpu/cpu1/cache/index2/shared_cpu_list", "1,18"},
46 {"/sys/devices/system/cpu/cpu1/cache/index2/type", "Unified"},
47 {"/sys/devices/system/cpu/cpu1/cache/index3/shared_cpu_list", "0-8,17-23"},
48 {"/sys/devices/system/cpu/cpu1/cache/index3/type", "Unified"},
49 {"/sys/devices/system/cpu/cpu2/cache/index0/shared_cpu_list", "2,19"},
50 {"/sys/devices/system/cpu/cpu2/cache/index0/type", "Data"},
51 {"/sys/devices/system/cpu/cpu2/cache/index1/shared_cpu_list", "2,19"},
52 {"/sys/devices/system/cpu/cpu2/cache/index1/type", "Instruction"},
53 {"/sys/devices/system/cpu/cpu2/cache/index2/shared_cpu_list", "2,19"},
54 {"/sys/devices/system/cpu/cpu2/cache/index2/type", "Unified"},
55 {"/sys/devices/system/cpu/cpu2/cache/index3/shared_cpu_list", "0-8,17-23"},
56 {"/sys/devices/system/cpu/cpu2/cache/index3/type", "Unified"},
57 {"/sys/devices/system/cpu/cpu3/cache/index0/shared_cpu_list", "3,20"},
58 {"/sys/devices/system/cpu/cpu3/cache/index0/type", "Data"},
59 {"/sys/devices/system/cpu/cpu3/cache/index1/shared_cpu_list", "3,20"},
60 {"/sys/devices/system/cpu/cpu3/cache/index1/type", "Instruction"},
61 {"/sys/devices/system/cpu/cpu3/cache/index2/shared_cpu_list", "3,20"},
62 {"/sys/devices/system/cpu/cpu3/cache/index2/type", "Unified"},
63 {"/sys/devices/system/cpu/cpu3/cache/index3/shared_cpu_list", "0-8,17-23"},
64 {"/sys/devices/system/cpu/cpu3/cache/index3/type", "Unified"},
65 {"/sys/devices/system/cpu/cpu4/cache/index0/shared_cpu_list", "4,21"},
66 {"/sys/devices/system/cpu/cpu4/cache/index0/type", "Data"},
67 {"/sys/devices/system/cpu/cpu4/cache/index1/shared_cpu_list", "4,21"},
68 {"/sys/devices/system/cpu/cpu4/cache/index1/type", "Instruction"},
69 {"/sys/devices/system/cpu/cpu4/cache/index2/shared_cpu_list", "4,21"},
70 {"/sys/devices/system/cpu/cpu4/cache/index2/type", "Unified"},
71 {"/sys/devices/system/cpu/cpu4/cache/index3/shared_cpu_list", "0-8,17-23"},
72 {"/sys/devices/system/cpu/cpu4/cache/index3/type", "Unified"},
73 {"/sys/devices/system/cpu/cpu5/cache/index0/shared_cpu_list", "5-6"},
74 {"/sys/devices/system/cpu/cpu5/cache/index0/type", "Data"},
75 {"/sys/devices/system/cpu/cpu5/cache/index1/shared_cpu_list", "5-6"},
76 {"/sys/devices/system/cpu/cpu5/cache/index1/type", "Instruction"},
77 {"/sys/devices/system/cpu/cpu5/cache/index2/shared_cpu_list", "5-6"},
78 {"/sys/devices/system/cpu/cpu5/cache/index2/type", "Unified"},
79 {"/sys/devices/system/cpu/cpu5/cache/index3/shared_cpu_list", "0-8,17-23"},
80 {"/sys/devices/system/cpu/cpu5/cache/index3/type", "Unified"},
81 {"/sys/devices/system/cpu/cpu6/cache/index0/shared_cpu_list", "5-6"},
82 {"/sys/devices/system/cpu/cpu6/cache/index0/type", "Data"},
83 {"/sys/devices/system/cpu/cpu6/cache/index1/shared_cpu_list", "5-6"},
84 {"/sys/devices/system/cpu/cpu6/cache/index1/type", "Instruction"},
85 {"/sys/devices/system/cpu/cpu6/cache/index2/shared_cpu_list", "5-6"},
86 {"/sys/devices/system/cpu/cpu6/cache/index2/type", "Unified"},
87 {"/sys/devices/system/cpu/cpu6/cache/index3/shared_cpu_list", "0-8,17-23"},
88 {"/sys/devices/system/cpu/cpu6/cache/index3/type", "Unified"},
89 {"/sys/devices/system/cpu/cpu7/cache/index0/shared_cpu_list", "7,22"},
90 {"/sys/devices/system/cpu/cpu7/cache/index0/type", "Data"},
91 {"/sys/devices/system/cpu/cpu7/cache/index1/shared_cpu_list", "7,22"},
92 {"/sys/devices/system/cpu/cpu7/cache/index1/type", "Instruction"},
93 {"/sys/devices/system/cpu/cpu7/cache/index2/shared_cpu_list", "7,22"},
94 {"/sys/devices/system/cpu/cpu7/cache/index2/type", "Unified"},
95 {"/sys/devices/system/cpu/cpu7/cache/index3/shared_cpu_list", "0-8,17-23"},
96 {"/sys/devices/system/cpu/cpu7/cache/index3/type", "Unified"},
97 {"/sys/devices/system/cpu/cpu8/cache/index0/shared_cpu_list", "8,23"},
98 {"/sys/devices/system/cpu/cpu8/cache/index0/type", "Data"},
99 {"/sys/devices/system/cpu/cpu8/cache/index1/shared_cpu_list", "8,23"},
100 {"/sys/devices/system/cpu/cpu8/cache/index1/type", "Instruction"},
101 {"/sys/devices/system/cpu/cpu8/cache/index2/shared_cpu_list", "8,23"},
102 {"/sys/devices/system/cpu/cpu8/cache/index2/type", "Unified"},
103 {"/sys/devices/system/cpu/cpu8/cache/index3/shared_cpu_list", "0-8,17-23"},
104 {"/sys/devices/system/cpu/cpu8/cache/index3/type", "Unified"},
105 {"/sys/devices/system/cpu/cpu9/cache/index0/shared_cpu_list", "9,24"},
106 {"/sys/devices/system/cpu/cpu9/cache/index0/type", "Data"},
107 {"/sys/devices/system/cpu/cpu9/cache/index1/shared_cpu_list", "9,24"},
108 {"/sys/devices/system/cpu/cpu9/cache/index1/type", "Instruction"},
109 {"/sys/devices/system/cpu/cpu9/cache/index2/shared_cpu_list", "9,24"},
110 {"/sys/devices/system/cpu/cpu9/cache/index2/type", "Unified"},
111 {"/sys/devices/system/cpu/cpu9/cache/index3/shared_cpu_list", "9-16,24-31"},
112 {"/sys/devices/system/cpu/cpu9/cache/index3/type", "Unified"},
113 {"/sys/devices/system/cpu/cpu10/cache/index0/shared_cpu_list", "10,25"},
114 {"/sys/devices/system/cpu/cpu10/cache/index0/type", "Data"},
115 {"/sys/devices/system/cpu/cpu10/cache/index1/shared_cpu_list", "10,25"},
116 {"/sys/devices/system/cpu/cpu10/cache/index1/type", "Instruction"},
117 {"/sys/devices/system/cpu/cpu10/cache/index2/shared_cpu_list", "10,25"},
118 {"/sys/devices/system/cpu/cpu10/cache/index2/type", "Unified"},
119 {"/sys/devices/system/cpu/cpu10/cache/index3/shared_cpu_list",
120 "9-16,24-31"},
121 {"/sys/devices/system/cpu/cpu10/cache/index3/type", "Unified"},
122 {"/sys/devices/system/cpu/cpu11/cache/index0/shared_cpu_list", "11,26"},
123 {"/sys/devices/system/cpu/cpu11/cache/index0/type", "Data"},
124 {"/sys/devices/system/cpu/cpu11/cache/index1/shared_cpu_list", "11,26"},
125 {"/sys/devices/system/cpu/cpu11/cache/index1/type", "Instruction"},
126 {"/sys/devices/system/cpu/cpu11/cache/index2/shared_cpu_list", "11,26"},
127 {"/sys/devices/system/cpu/cpu11/cache/index2/type", "Unified"},
128 {"/sys/devices/system/cpu/cpu11/cache/index3/shared_cpu_list",
129 "9-16,24-31"},
130 {"/sys/devices/system/cpu/cpu11/cache/index3/type", "Unified"},
131 {"/sys/devices/system/cpu/cpu12/cache/index0/shared_cpu_list", "12,27"},
132 {"/sys/devices/system/cpu/cpu12/cache/index0/type", "Data"},
133 {"/sys/devices/system/cpu/cpu12/cache/index1/shared_cpu_list", "12,27"},
134 {"/sys/devices/system/cpu/cpu12/cache/index1/type", "Instruction"},
135 {"/sys/devices/system/cpu/cpu12/cache/index2/shared_cpu_list", "12,27"},
136 {"/sys/devices/system/cpu/cpu12/cache/index2/type", "Unified"},
137 {"/sys/devices/system/cpu/cpu12/cache/index3/shared_cpu_list",
138 "9-16,24-31"},
139 {"/sys/devices/system/cpu/cpu12/cache/index3/type", "Unified"},
140 {"/sys/devices/system/cpu/cpu13/cache/index0/shared_cpu_list", "13,28"},
141 {"/sys/devices/system/cpu/cpu13/cache/index0/type", "Data"},
142 {"/sys/devices/system/cpu/cpu13/cache/index1/shared_cpu_list", "13,28"},
143 {"/sys/devices/system/cpu/cpu13/cache/index1/type", "Instruction"},
144 {"/sys/devices/system/cpu/cpu13/cache/index2/shared_cpu_list", "13,28"},
145 {"/sys/devices/system/cpu/cpu13/cache/index2/type", "Unified"},
146 {"/sys/devices/system/cpu/cpu13/cache/index3/shared_cpu_list",
147 "9-16,24-31"},
148 {"/sys/devices/system/cpu/cpu13/cache/index3/type", "Unified"},
149 {"/sys/devices/system/cpu/cpu14/cache/index0/shared_cpu_list", "14,29"},
150 {"/sys/devices/system/cpu/cpu14/cache/index0/type", "Data"},
151 {"/sys/devices/system/cpu/cpu14/cache/index1/shared_cpu_list", "14,29"},
152 {"/sys/devices/system/cpu/cpu14/cache/index1/type", "Instruction"},
153 {"/sys/devices/system/cpu/cpu14/cache/index2/shared_cpu_list", "14,29"},
154 {"/sys/devices/system/cpu/cpu14/cache/index2/type", "Unified"},
155 {"/sys/devices/system/cpu/cpu14/cache/index3/shared_cpu_list",
156 "9-16,24-31"},
157 {"/sys/devices/system/cpu/cpu14/cache/index3/type", "Unified"},
158 {"/sys/devices/system/cpu/cpu15/cache/index0/shared_cpu_list", "15,30"},
159 {"/sys/devices/system/cpu/cpu15/cache/index0/type", "Data"},
160 {"/sys/devices/system/cpu/cpu15/cache/index1/shared_cpu_list", "15,30"},
161 {"/sys/devices/system/cpu/cpu15/cache/index1/type", "Instruction"},
162 {"/sys/devices/system/cpu/cpu15/cache/index2/shared_cpu_list", "15,30"},
163 {"/sys/devices/system/cpu/cpu15/cache/index2/type", "Unified"},
164 {"/sys/devices/system/cpu/cpu15/cache/index3/shared_cpu_list",
165 "9-16,24-31"},
166 {"/sys/devices/system/cpu/cpu15/cache/index3/type", "Unified"},
167 {"/sys/devices/system/cpu/cpu16/cache/index0/shared_cpu_list", "16,31"},
168 {"/sys/devices/system/cpu/cpu16/cache/index0/type", "Data"},
169 {"/sys/devices/system/cpu/cpu16/cache/index1/shared_cpu_list", "16,31"},
170 {"/sys/devices/system/cpu/cpu16/cache/index1/type", "Instruction"},
171 {"/sys/devices/system/cpu/cpu16/cache/index2/shared_cpu_list", "16,31"},
172 {"/sys/devices/system/cpu/cpu16/cache/index2/type", "Unified"},
173 {"/sys/devices/system/cpu/cpu16/cache/index3/shared_cpu_list",
174 "9-16,24-31"},
175 {"/sys/devices/system/cpu/cpu16/cache/index3/type", "Unified"},
176 {"/sys/devices/system/cpu/cpu17/cache/index0/shared_cpu_list", "0,17"},
177 {"/sys/devices/system/cpu/cpu17/cache/index0/type", "Data"},
178 {"/sys/devices/system/cpu/cpu17/cache/index1/shared_cpu_list", "0,17"},
179 {"/sys/devices/system/cpu/cpu17/cache/index1/type", "Instruction"},
180 {"/sys/devices/system/cpu/cpu17/cache/index2/shared_cpu_list", "0,17"},
181 {"/sys/devices/system/cpu/cpu17/cache/index2/type", "Unified"},
182 {"/sys/devices/system/cpu/cpu17/cache/index3/shared_cpu_list", "0-8,17-23"},
183 {"/sys/devices/system/cpu/cpu17/cache/index3/type", "Unified"},
184 {"/sys/devices/system/cpu/cpu18/cache/index0/shared_cpu_list", "1,18"},
185 {"/sys/devices/system/cpu/cpu18/cache/index0/type", "Data"},
186 {"/sys/devices/system/cpu/cpu18/cache/index1/shared_cpu_list", "1,18"},
187 {"/sys/devices/system/cpu/cpu18/cache/index1/type", "Instruction"},
188 {"/sys/devices/system/cpu/cpu18/cache/index2/shared_cpu_list", "1,18"},
189 {"/sys/devices/system/cpu/cpu18/cache/index2/type", "Unified"},
190 {"/sys/devices/system/cpu/cpu18/cache/index3/shared_cpu_list", "0-8,17-23"},
191 {"/sys/devices/system/cpu/cpu18/cache/index3/type", "Unified"},
192 {"/sys/devices/system/cpu/cpu19/cache/index0/shared_cpu_list", "2,19"},
193 {"/sys/devices/system/cpu/cpu19/cache/index0/type", "Data"},
194 {"/sys/devices/system/cpu/cpu19/cache/index1/shared_cpu_list", "2,19"},
195 {"/sys/devices/system/cpu/cpu19/cache/index1/type", "Instruction"},
196 {"/sys/devices/system/cpu/cpu19/cache/index2/shared_cpu_list", "2,19"},
197 {"/sys/devices/system/cpu/cpu19/cache/index2/type", "Unified"},
198 {"/sys/devices/system/cpu/cpu19/cache/index3/shared_cpu_list", "0-8,17-23"},
199 {"/sys/devices/system/cpu/cpu19/cache/index3/type", "Unified"},
200 {"/sys/devices/system/cpu/cpu20/cache/index0/shared_cpu_list", "3,20"},
201 {"/sys/devices/system/cpu/cpu20/cache/index0/type", "Data"},
202 {"/sys/devices/system/cpu/cpu20/cache/index1/shared_cpu_list", "3,20"},
203 {"/sys/devices/system/cpu/cpu20/cache/index1/type", "Instruction"},
204 {"/sys/devices/system/cpu/cpu20/cache/index2/shared_cpu_list", "3,20"},
205 {"/sys/devices/system/cpu/cpu20/cache/index2/type", "Unified"},
206 {"/sys/devices/system/cpu/cpu20/cache/index3/shared_cpu_list", "0-8,17-23"},
207 {"/sys/devices/system/cpu/cpu20/cache/index3/type", "Unified"},
208 {"/sys/devices/system/cpu/cpu21/cache/index0/shared_cpu_list", "4,21"},
209 {"/sys/devices/system/cpu/cpu21/cache/index0/type", "Data"},
210 {"/sys/devices/system/cpu/cpu21/cache/index1/shared_cpu_list", "4,21"},
211 {"/sys/devices/system/cpu/cpu21/cache/index1/type", "Instruction"},
212 {"/sys/devices/system/cpu/cpu21/cache/index2/shared_cpu_list", "4,21"},
213 {"/sys/devices/system/cpu/cpu21/cache/index2/type", "Unified"},
214 {"/sys/devices/system/cpu/cpu21/cache/index3/shared_cpu_list", "0-8,17-23"},
215 {"/sys/devices/system/cpu/cpu21/cache/index3/type", "Unified"},
216 {"/sys/devices/system/cpu/cpu22/cache/index0/shared_cpu_list", "7,22"},
217 {"/sys/devices/system/cpu/cpu22/cache/index0/type", "Data"},
218 {"/sys/devices/system/cpu/cpu22/cache/index1/shared_cpu_list", "7,22"},
219 {"/sys/devices/system/cpu/cpu22/cache/index1/type", "Instruction"},
220 {"/sys/devices/system/cpu/cpu22/cache/index2/shared_cpu_list", "7,22"},
221 {"/sys/devices/system/cpu/cpu22/cache/index2/type", "Unified"},
222 {"/sys/devices/system/cpu/cpu22/cache/index3/shared_cpu_list", "0-8,17-23"},
223 {"/sys/devices/system/cpu/cpu22/cache/index3/type", "Unified"},
224 {"/sys/devices/system/cpu/cpu23/cache/index0/shared_cpu_list", "8,23"},
225 {"/sys/devices/system/cpu/cpu23/cache/index0/type", "Data"},
226 {"/sys/devices/system/cpu/cpu23/cache/index1/shared_cpu_list", "8,23"},
227 {"/sys/devices/system/cpu/cpu23/cache/index1/type", "Instruction"},
228 {"/sys/devices/system/cpu/cpu23/cache/index2/shared_cpu_list", "8,23"},
229 {"/sys/devices/system/cpu/cpu23/cache/index2/type", "Unified"},
230 {"/sys/devices/system/cpu/cpu23/cache/index3/shared_cpu_list", "0-8,17-23"},
231 {"/sys/devices/system/cpu/cpu23/cache/index3/type", "Unified"},
232 {"/sys/devices/system/cpu/cpu24/cache/index0/shared_cpu_list", "9,24"},
233 {"/sys/devices/system/cpu/cpu24/cache/index0/type", "Data"},
234 {"/sys/devices/system/cpu/cpu24/cache/index1/shared_cpu_list", "9,24"},
235 {"/sys/devices/system/cpu/cpu24/cache/index1/type", "Instruction"},
236 {"/sys/devices/system/cpu/cpu24/cache/index2/shared_cpu_list", "9,24"},
237 {"/sys/devices/system/cpu/cpu24/cache/index2/type", "Unified"},
238 {"/sys/devices/system/cpu/cpu24/cache/index3/shared_cpu_list",
239 "9-16,24-31"},
240 {"/sys/devices/system/cpu/cpu24/cache/index3/type", "Unified"},
241 {"/sys/devices/system/cpu/cpu25/cache/index0/shared_cpu_list", "10,25"},
242 {"/sys/devices/system/cpu/cpu25/cache/index0/type", "Data"},
243 {"/sys/devices/system/cpu/cpu25/cache/index1/shared_cpu_list", "10,25"},
244 {"/sys/devices/system/cpu/cpu25/cache/index1/type", "Instruction"},
245 {"/sys/devices/system/cpu/cpu25/cache/index2/shared_cpu_list", "10,25"},
246 {"/sys/devices/system/cpu/cpu25/cache/index2/type", "Unified"},
247 {"/sys/devices/system/cpu/cpu25/cache/index3/shared_cpu_list",
248 "9-16,24-31"},
249 {"/sys/devices/system/cpu/cpu25/cache/index3/type", "Unified"},
250 {"/sys/devices/system/cpu/cpu26/cache/index0/shared_cpu_list", "11,26"},
251 {"/sys/devices/system/cpu/cpu26/cache/index0/type", "Data"},
252 {"/sys/devices/system/cpu/cpu26/cache/index1/shared_cpu_list", "11,26"},
253 {"/sys/devices/system/cpu/cpu26/cache/index1/type", "Instruction"},
254 {"/sys/devices/system/cpu/cpu26/cache/index2/shared_cpu_list", "11,26"},
255 {"/sys/devices/system/cpu/cpu26/cache/index2/type", "Unified"},
256 {"/sys/devices/system/cpu/cpu26/cache/index3/shared_cpu_list",
257 "9-16,24-31"},
258 {"/sys/devices/system/cpu/cpu26/cache/index3/type", "Unified"},
259 {"/sys/devices/system/cpu/cpu27/cache/index0/shared_cpu_list", "12,27"},
260 {"/sys/devices/system/cpu/cpu27/cache/index0/type", "Data"},
261 {"/sys/devices/system/cpu/cpu27/cache/index1/shared_cpu_list", "12,27"},
262 {"/sys/devices/system/cpu/cpu27/cache/index1/type", "Instruction"},
263 {"/sys/devices/system/cpu/cpu27/cache/index2/shared_cpu_list", "12,27"},
264 {"/sys/devices/system/cpu/cpu27/cache/index2/type", "Unified"},
265 {"/sys/devices/system/cpu/cpu27/cache/index3/shared_cpu_list",
266 "9-16,24-31"},
267 {"/sys/devices/system/cpu/cpu27/cache/index3/type", "Unified"},
268 {"/sys/devices/system/cpu/cpu28/cache/index0/shared_cpu_list", "13,28"},
269 {"/sys/devices/system/cpu/cpu28/cache/index0/type", "Data"},
270 {"/sys/devices/system/cpu/cpu28/cache/index1/shared_cpu_list", "13,28"},
271 {"/sys/devices/system/cpu/cpu28/cache/index1/type", "Instruction"},
272 {"/sys/devices/system/cpu/cpu28/cache/index2/shared_cpu_list", "13,28"},
273 {"/sys/devices/system/cpu/cpu28/cache/index2/type", "Unified"},
274 {"/sys/devices/system/cpu/cpu28/cache/index3/shared_cpu_list",
275 "9-16,24-31"},
276 {"/sys/devices/system/cpu/cpu28/cache/index3/type", "Unified"},
277 {"/sys/devices/system/cpu/cpu29/cache/index0/shared_cpu_list", "14,29"},
278 {"/sys/devices/system/cpu/cpu29/cache/index0/type", "Data"},
279 {"/sys/devices/system/cpu/cpu29/cache/index1/shared_cpu_list", "14,29"},
280 {"/sys/devices/system/cpu/cpu29/cache/index1/type", "Instruction"},
281 {"/sys/devices/system/cpu/cpu29/cache/index2/shared_cpu_list", "14,29"},
282 {"/sys/devices/system/cpu/cpu29/cache/index2/type", "Unified"},
283 {"/sys/devices/system/cpu/cpu29/cache/index3/shared_cpu_list",
284 "9-16,24-31"},
285 {"/sys/devices/system/cpu/cpu29/cache/index3/type", "Unified"},
286 {"/sys/devices/system/cpu/cpu30/cache/index0/shared_cpu_list", "15,30"},
287 {"/sys/devices/system/cpu/cpu30/cache/index0/type", "Data"},
288 {"/sys/devices/system/cpu/cpu30/cache/index1/shared_cpu_list", "15,30"},
289 {"/sys/devices/system/cpu/cpu30/cache/index1/type", "Instruction"},
290 {"/sys/devices/system/cpu/cpu30/cache/index2/shared_cpu_list", "15,30"},
291 {"/sys/devices/system/cpu/cpu30/cache/index2/type", "Unified"},
292 {"/sys/devices/system/cpu/cpu30/cache/index3/shared_cpu_list",
293 "9-16,24-31"},
294 {"/sys/devices/system/cpu/cpu30/cache/index3/type", "Unified"},
295 {"/sys/devices/system/cpu/cpu31/cache/index0/shared_cpu_list", "16,31"},
296 {"/sys/devices/system/cpu/cpu31/cache/index0/type", "Data"},
297 {"/sys/devices/system/cpu/cpu31/cache/index1/shared_cpu_list", "16,31"},
298 {"/sys/devices/system/cpu/cpu31/cache/index1/type", "Instruction"},
299 {"/sys/devices/system/cpu/cpu31/cache/index2/shared_cpu_list", "16,31"},
300 {"/sys/devices/system/cpu/cpu31/cache/index2/type", "Unified"},
301 {"/sys/devices/system/cpu/cpu31/cache/index3/shared_cpu_list",
302 "9-16,24-31"},
303 {"/sys/devices/system/cpu/cpu31/cache/index3/type", "Unified"}};
304
305/// This is the expected CacheLocality structure for fakeSysfsTree
306static const CacheLocality nonUniformExampleLocality = {
307 32,
308 {16, 16, 2},
309 {0, 2, 4, 6, 8, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28,
310 30, 1, 3, 5, 7, 9, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}};
311
312TEST(CacheLocality, FakeSysfs) {
313 auto parsed = CacheLocality::readFromSysfsTree([](std::string name) {
314 auto iter = fakeSysfsTree.find(name);
315 return iter == fakeSysfsTree.end() ? std::string() : iter->second;
316 });
317
318 auto& expected = nonUniformExampleLocality;
319 EXPECT_EQ(expected.numCpus, parsed.numCpus);
320 EXPECT_EQ(expected.numCachesByLevel, parsed.numCachesByLevel);
321 EXPECT_EQ(expected.localityIndexByCpu, parsed.localityIndexByCpu);
322}
323
324#if FOLLY_HAVE_LINUX_VDSO
325TEST(Getcpu, VdsoGetcpu) {
326 unsigned cpu;
327 Getcpu::resolveVdsoFunc()(&cpu, nullptr, nullptr);
328
329 EXPECT_TRUE(cpu < CPU_SETSIZE);
330}
331#endif
332
333#ifdef FOLLY_TLS
334TEST(ThreadId, SimpleTls) {
335 unsigned cpu = 0;
336 auto rv = folly::FallbackGetcpu<SequentialThreadId<std::atomic>>::getcpu(
337 &cpu, nullptr, nullptr);
338 EXPECT_EQ(rv, 0);
339 EXPECT_TRUE(cpu > 0);
340 unsigned again;
341 folly::FallbackGetcpu<SequentialThreadId<std::atomic>>::getcpu(
342 &again, nullptr, nullptr);
343 EXPECT_EQ(cpu, again);
344}
345#endif
346
347TEST(ThreadId, SimplePthread) {
348 unsigned cpu = 0;
349 auto rv =
350 folly::FallbackGetcpu<HashingThreadId>::getcpu(&cpu, nullptr, nullptr);
351 EXPECT_EQ(rv, 0);
352 EXPECT_TRUE(cpu > 0);
353 unsigned again;
354 folly::FallbackGetcpu<HashingThreadId>::getcpu(&again, nullptr, nullptr);
355 EXPECT_EQ(cpu, again);
356}
357
358#ifdef FOLLY_TLS
359static FOLLY_TLS unsigned testingCpu = 0;
360
361static int testingGetcpu(unsigned* cpu, unsigned* node, void* /* unused */) {
362 if (cpu != nullptr) {
363 *cpu = testingCpu;
364 }
365 if (node != nullptr) {
366 *node = testingCpu;
367 }
368 return 0;
369}
370#endif
371
372TEST(AccessSpreader, Simple) {
373 for (size_t s = 1; s < 200; ++s) {
374 EXPECT_LT(AccessSpreader<>::current(s), s);
375 }
376}
377
378TEST(AccessSpreader, SimpleCached) {
379 for (size_t s = 1; s < 200; ++s) {
380 EXPECT_LT(AccessSpreader<>::cachedCurrent(s), s);
381 }
382}
383
384TEST(AccessSpreader, ConcurrentAccessCached) {
385 std::vector<std::thread> threads;
386 for (size_t i = 0; i < 4; ++i) {
387 threads.emplace_back([]() {
388 for (size_t s : {16, 32, 64}) {
389 for (size_t j = 1; j < 200; ++j) {
390 EXPECT_LT(AccessSpreader<>::cachedCurrent(s), s);
391 EXPECT_LT(AccessSpreader<>::cachedCurrent(s), s);
392 }
393 std::this_thread::yield();
394 }
395 });
396 }
397 for (auto& thread : threads) {
398 thread.join();
399 }
400}
401
402#ifdef FOLLY_TLS
403#define DECLARE_SPREADER_TAG(tag, locality, func) \
404 namespace { \
405 template <typename dummy> \
406 struct tag {}; \
407 } \
408 namespace folly { \
409 template <> \
410 const CacheLocality& CacheLocality::system<tag>() { \
411 static auto* inst = new CacheLocality(locality); \
412 return *inst; \
413 } \
414 template <> \
415 Getcpu::Func AccessSpreader<tag>::pickGetcpuFunc() { \
416 return func; \
417 } \
418 template struct AccessSpreader<tag>; \
419 }
420
421DECLARE_SPREADER_TAG(ManualTag, CacheLocality::uniform(16), testingGetcpu)
422
423TEST(AccessSpreader, Wrapping) {
424 // this test won't pass unless locality.numCpus divides kMaxCpus
425 auto numCpus = CacheLocality::system<ManualTag>().numCpus;
426 EXPECT_EQ(0, 128 % numCpus);
427 for (size_t s = 1; s < 200; ++s) {
428 for (size_t c = 0; c < 400; ++c) {
429 testingCpu = c;
430 auto observed = AccessSpreader<ManualTag>::current(s);
431 testingCpu = c % numCpus;
432 auto expected = AccessSpreader<ManualTag>::current(s);
433 EXPECT_EQ(expected, observed)
434 << "numCpus=" << numCpus << ", s=" << s << ", c=" << c;
435 }
436 }
437}
438
439TEST(CoreRawAllocator, Basic) {
440 CoreRawAllocator<32> alloc;
441 auto a = alloc.get(0);
442 auto res = a->allocate(8);
443 memset(res, 0, 8);
444 a->deallocate(res);
445 res = a->allocate(8);
446 EXPECT_TRUE((intptr_t)res % 8 == 0); // check alignment
447 memset(res, 0, 8);
448 a->deallocate(res);
449 res = a->allocate(12);
450 EXPECT_TRUE((intptr_t)res % 16 == 0); // check alignment
451 memset(res, 0, 12);
452 a->deallocate(res);
453 res = a->allocate(257);
454 memset(res, 0, 257);
455 a->deallocate(res);
456
457 std::vector<void*> mems;
458 for (int i = 0; i < 10000; i++) {
459 mems.push_back(a->allocate(1));
460 }
461 for (auto& mem : mems) {
462 a->deallocate(mem);
463 }
464 mems.clear();
465}
466
467#endif
468