Move CacheLocality out of detail/ and into concurrency/
[folly.git] / folly / concurrency / test / CacheLocalityTest.cpp
1 /*
2  * Copyright 2017 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 <memory>
22 #include <thread>
23 #include <type_traits>
24 #include <unordered_map>
25 #include <glog/logging.h>
26
27 using namespace folly;
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 = folly::FallbackGetcpu<SequentialThreadId<std::atomic>>::getcpu(
367       &cpu, nullptr, nullptr);
368   EXPECT_EQ(rv, 0);
369   EXPECT_TRUE(cpu > 0);
370   unsigned again;
371   folly::FallbackGetcpu<SequentialThreadId<std::atomic>>::getcpu(
372       &again, nullptr, nullptr);
373   EXPECT_EQ(cpu, again);
374 }
375 #endif
376
377 TEST(ThreadId, SimplePthread) {
378   unsigned cpu = 0;
379   auto rv =
380       folly::FallbackGetcpu<HashingThreadId>::getcpu(&cpu, nullptr, nullptr);
381   EXPECT_EQ(rv, 0);
382   EXPECT_TRUE(cpu > 0);
383   unsigned again;
384   folly::FallbackGetcpu<HashingThreadId>::getcpu(&again, nullptr, nullptr);
385   EXPECT_EQ(cpu, again);
386 }
387
388 #ifdef FOLLY_TLS
389 static FOLLY_TLS unsigned testingCpu = 0;
390
391 static int testingGetcpu(unsigned* cpu, unsigned* node, void* /* unused */) {
392   if (cpu != nullptr) {
393     *cpu = testingCpu;
394   }
395   if (node != nullptr) {
396     *node = testingCpu;
397   }
398   return 0;
399 }
400 #endif
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 #ifdef FOLLY_TLS
409 #define DECLARE_SPREADER_TAG(tag, locality, func)      \
410   namespace {                                          \
411   template <typename dummy>                            \
412   struct tag {};                                       \
413   }                                                    \
414   namespace folly {                                    \
415   template <>                                          \
416   const CacheLocality& CacheLocality::system<tag>() {  \
417     static auto* inst = new CacheLocality(locality);   \
418     return *inst;                                      \
419   }                                                    \
420   template <>                                          \
421   Getcpu::Func AccessSpreader<tag>::pickGetcpuFunc() { \
422     return func;                                       \
423   }                                                    \
424   }
425
426 DECLARE_SPREADER_TAG(ManualTag, CacheLocality::uniform(16), testingGetcpu)
427
428 TEST(AccessSpreader, Wrapping) {
429   // this test won't pass unless locality.numCpus divides kMaxCpus
430   auto numCpus = CacheLocality::system<ManualTag>().numCpus;
431   EXPECT_EQ(0, 128 % numCpus);
432   for (size_t s = 1; s < 200; ++s) {
433     for (size_t c = 0; c < 400; ++c) {
434       testingCpu = c;
435       auto observed = AccessSpreader<ManualTag>::current(s);
436       testingCpu = c % numCpus;
437       auto expected = AccessSpreader<ManualTag>::current(s);
438       EXPECT_EQ(expected, observed) << "numCpus=" << numCpus << ", s=" << s
439                                     << ", c=" << c;
440     }
441   }
442 }
443
444 TEST(CoreAllocator, Basic) {
445   CoreAllocator<32> alloc;
446   auto a = alloc.get(0);
447   auto res = a->allocate(8);
448   memset(res, 0, 8);
449   a->deallocate(res);
450   res = a->allocate(8);
451   EXPECT_TRUE((intptr_t)res % 8 == 0); // check alignment
452   memset(res, 0, 8);
453   a->deallocate(res);
454   res = a->allocate(12);
455   EXPECT_TRUE((intptr_t)res % 16 == 0); // check alignment
456   memset(res, 0, 12);
457   a->deallocate(res);
458   res = a->allocate(257);
459   memset(res, 0, 257);
460   a->deallocate(res);
461
462   std::vector<void*> mems;
463   for (int i = 0; i < 10000; i++) {
464     mems.push_back(a->allocate(1));
465   }
466   for (auto& mem : mems) {
467     a->deallocate(mem);
468   }
469   mems.clear();
470 }
471
472 #endif