1/*
2 * Copyright 2011-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#pragma once
18
19#include <cstddef>
20
21#include <folly/Portability.h>
22
23namespace folly {
24
25namespace detail {
26
27// Implemented this way because of a bug in Clang for ARMv7, which gives the
28// wrong result for `alignof` a `union` with a field of each scalar type.
29constexpr size_t max_align_(std::size_t a) {
30 return a;
31}
32template <typename... Es>
33constexpr std::size_t max_align_(std::size_t a, std::size_t e, Es... es) {
34 return !(a < e) ? a : max_align_(e, es...);
35}
36template <typename... Ts>
37struct max_align_t_ {
38 static constexpr std::size_t value = max_align_(0u, alignof(Ts)...);
39};
40using max_align_v_ = max_align_t_<
41 long double,
42 double,
43 float,
44 long long int,
45 long int,
46 int,
47 short int,
48 bool,
49 char,
50 char16_t,
51 char32_t,
52 wchar_t,
53 void*,
54 std::max_align_t>;
55
56} // namespace detail
57
58// max_align_v is the alignment of max_align_t.
59//
60// max_align_t is a type which is aligned at least as strictly as the
61// most-aligned basic type (see the specification of std::max_align_t). This
62// implementation exists because 32-bit iOS platforms have a broken
63// std::max_align_t (see below).
64//
65// You should refer to this as `::folly::max_align_t` in portable code, even if
66// you have `using namespace folly;` because C11 defines a global namespace
67// `max_align_t` type.
68//
69// To be certain, we consider every non-void fundamental type specified by the
70// standard. On most platforms `long double` would be enough, but iOS 32-bit
71// has an 8-byte aligned `double` and `long long int` and a 4-byte aligned
72// `long double`.
73//
74// So far we've covered locals and other non-allocated storage, but we also need
75// confidence that allocated storage from `malloc`, `new`, etc will also be
76// suitable for objects with this alignment requirement.
77//
78// Apple document that their implementation of malloc will issue 16-byte
79// granularity chunks for small allocations (large allocations are page-size
80// granularity and page-aligned). We think that allocated storage will be
81// suitable for these objects based on the following assumptions:
82//
83// 1. 16-byte granularity also means 16-byte aligned.
84// 2. `new` and other allocators follow the `malloc` rules.
85//
86// We also have some anecdotal evidence: we don't see lots of misaligned-storage
87// crashes on 32-bit iOS apps that use `double`.
88//
89// Apple's allocation reference: http://bit.ly/malloc-small
90constexpr std::size_t max_align_v = detail::max_align_v_::value;
91struct alignas(max_align_v) max_align_t {};
92
93// Memory locations within the same cache line are subject to destructive
94// interference, also known as false sharing, which is when concurrent
95// accesses to these different memory locations from different cores, where at
96// least one of the concurrent accesses is or involves a store operation,
97// induce contention and harm performance.
98//
99// Microbenchmarks indicate that pairs of cache lines also see destructive
100// interference under heavy use of atomic operations, as observed for atomic
101// increment on Sandy Bridge.
102//
103// We assume a cache line size of 64, so we use a cache line pair size of 128
104// to avoid destructive interference.
105//
106// mimic: std::hardware_destructive_interference_size, C++17
107constexpr std::size_t hardware_destructive_interference_size =
108 kIsArchArm ? 64 : 128;
109static_assert(hardware_destructive_interference_size >= max_align_v, "math?");
110
111// Memory locations within the same cache line are subject to constructive
112// interference, also known as true sharing, which is when accesses to some
113// memory locations induce all memory locations within the same cache line to
114// be cached, benefiting subsequent accesses to different memory locations
115// within the same cache line and heping performance.
116//
117// mimic: std::hardware_constructive_interference_size, C++17
118constexpr std::size_t hardware_constructive_interference_size = 64;
119static_assert(hardware_constructive_interference_size >= max_align_v, "math?");
120
121} // namespace folly
122