From 6c595f008a6ba9da89bd88ff61f76f3cdf867e59 Mon Sep 17 00:00:00 2001 From: Peter Dillinger Date: Mon, 16 Mar 2020 19:04:23 -0700 Subject: [PATCH] Update folly/lang/Align.h (backport to C++11) (#6534) Summary: For s390x support, some updates in newer version of Align.h are needed. Upgrading just that file as best we can, with one addition to Portability.h and tweaking new code in Align.h to use C++11 only (no non-trivial constexpr functions). Pull Request resolved: https://github.com/facebook/rocksdb/pull/6534 Test Plan: CI, further work in PR https://github.com/facebook/rocksdb/issues/6168 Differential Revision: D20445942 Pulled By: pdillinger fbshipit-source-id: 0cef3c367463c71f3123d12cdf287c573af5e342 --- third-party/folly/folly/Portability.h | 8 ++ third-party/folly/folly/lang/Align.h | 109 ++++++++++++++++++++++++-- 2 files changed, 111 insertions(+), 6 deletions(-) diff --git a/third-party/folly/folly/Portability.h b/third-party/folly/folly/Portability.h index 61c05ff22..93a4e41a5 100644 --- a/third-party/folly/folly/Portability.h +++ b/third-party/folly/folly/Portability.h @@ -82,3 +82,11 @@ constexpr bool kIsSanitizeThread = true; constexpr bool kIsSanitizeThread = false; #endif } // namespace folly + +namespace folly { +#if defined(__linux__) && !FOLLY_MOBILE +constexpr auto kIsLinux = true; +#else +constexpr auto kIsLinux = false; +#endif +} // namespace folly diff --git a/third-party/folly/folly/lang/Align.h b/third-party/folly/folly/lang/Align.h index 5257e2f6f..fd00b14ff 100644 --- a/third-party/folly/folly/lang/Align.h +++ b/third-party/folly/folly/lang/Align.h @@ -1,14 +1,101 @@ -// Copyright (c) 2011-present, Facebook, Inc. All rights reserved. -// This source code is licensed under both the GPLv2 (found in the -// COPYING file in the root directory) and Apache 2.0 License -// (found in the LICENSE.Apache file in the root directory). +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #pragma once +#include #include +#include +#include + namespace folly { +// has_extended_alignment +// +// True if it may be presumed that the platform has static extended alignment; +// false if it may not be so presumed, even when the platform might actually +// have it. Static extended alignment refers to extended alignment of objects +// with automatic, static, or thread storage. Whether the there is support for +// dynamic extended alignment is a property of the allocator which is used for +// each given dynamic allocation. +// +// Currently, very heuristical - only non-mobile 64-bit linux gets the extended +// alignment treatment. Theoretically, this could be tuned better. +constexpr bool has_extended_alignment = + kIsLinux && sizeof(void*) >= sizeof(std::uint64_t); + +namespace detail { + +// Implemented this way because of a bug in Clang for ARMv7, which gives the +// wrong result for `alignof` a `union` with a field of each scalar type. +// Modified for RocksDB to use C++11 only +constexpr std::size_t max_align_v = constexpr_max( + alignof(long double), + alignof(double), + alignof(float), + alignof(long long int), + alignof(long int), + alignof(int), + alignof(short int), + alignof(bool), + alignof(char), + alignof(char16_t), + alignof(char32_t), + alignof(wchar_t), + alignof(void*), + alignof(std::max_align_t)); + +} // namespace detail + +// max_align_v is the alignment of max_align_t. +// +// max_align_t is a type which is aligned at least as strictly as the +// most-aligned basic type (see the specification of std::max_align_t). This +// implementation exists because 32-bit iOS platforms have a broken +// std::max_align_t (see below). +// +// You should refer to this as `::folly::max_align_t` in portable code, even if +// you have `using namespace folly;` because C11 defines a global namespace +// `max_align_t` type. +// +// To be certain, we consider every non-void fundamental type specified by the +// standard. On most platforms `long double` would be enough, but iOS 32-bit +// has an 8-byte aligned `double` and `long long int` and a 4-byte aligned +// `long double`. +// +// So far we've covered locals and other non-allocated storage, but we also need +// confidence that allocated storage from `malloc`, `new`, etc will also be +// suitable for objects with this alignment requirement. +// +// Apple document that their implementation of malloc will issue 16-byte +// granularity chunks for small allocations (large allocations are page-size +// granularity and page-aligned). We think that allocated storage will be +// suitable for these objects based on the following assumptions: +// +// 1. 16-byte granularity also means 16-byte aligned. +// 2. `new` and other allocators follow the `malloc` rules. +// +// We also have some anecdotal evidence: we don't see lots of misaligned-storage +// crashes on 32-bit iOS apps that use `double`. +// +// Apple's allocation reference: http://bit.ly/malloc-small +constexpr std::size_t max_align_v = detail::max_align_v; +struct alignas(max_align_v) max_align_t {}; + // Memory locations within the same cache line are subject to destructive // interference, also known as false sharing, which is when concurrent // accesses to these different memory locations from different cores, where at @@ -23,7 +110,9 @@ namespace folly { // to avoid destructive interference. // // mimic: std::hardware_destructive_interference_size, C++17 -constexpr std::size_t hardware_destructive_interference_size = 128; +constexpr std::size_t hardware_destructive_interference_size = + kIsArchArm ? 64 : 128; +static_assert(hardware_destructive_interference_size >= max_align_v, "math?"); // Memory locations within the same cache line are subject to constructive // interference, also known as true sharing, which is when accesses to some @@ -33,6 +122,14 @@ constexpr std::size_t hardware_destructive_interference_size = 128; // // mimic: std::hardware_constructive_interference_size, C++17 constexpr std::size_t hardware_constructive_interference_size = 64; +static_assert(hardware_constructive_interference_size >= max_align_v, "math?"); -} // namespace folly +// A value corresponding to hardware_constructive_interference_size but which +// may be used with alignas, since hardware_constructive_interference_size may +// be too large on some platforms to be used with alignas. +constexpr std::size_t cacheline_align_v = has_extended_alignment + ? hardware_constructive_interference_size + : max_align_v; +struct alignas(cacheline_align_v) cacheline_align_t {}; +} // namespace folly