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