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