Align.h 4.5 KB

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