Seastar
High performance C++ framework for concurrent servers
unaligned.hh
1 /*
2  * This file is open source software, licensed to you under the terms
3  * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
4  * distributed with this work for additional information regarding copyright
5  * ownership. You may not use this file except in compliance with the License.
6  *
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing,
12  * software distributed under the License is distributed on an
13  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14  * KIND, either express or implied. See the License for the
15  * specific language governing permissions and limitations
16  * under the License.
17  */
18 /*
19  * Copyright (C) 2015 Cloudius Systems, Ltd.
20  */
21 
22 #pragma once
23 
24 // The following unaligned_cast<T*>(p) is a portable replacement for
25 // reinterpret_cast<T*>(p) which should be used every time address p
26 // is not guaranteed to be properly aligned to alignof(T).
27 //
28 // On architectures like x86 and ARM, where unaligned access is allowed,
29 // unaligned_cast will behave the same as reinterpret_cast and will generate
30 // the same code.
31 //
32 // Certain architectures (e.g., MIPS) make it extremely slow or outright
33 // forbidden to use ordinary machine instructions on a primitive type at an
34 // unaligned addresses - e.g., access a uint32_t at an address which is not
35 // a multiple of 4. Gcc's "undefined behavior sanitizer" (enabled in our debug
36 // build) also catches such unaligned accesses and reports them as errors,
37 // even when running on x86.
38 //
39 // Therefore, reinterpret_cast<int32_t*> on an address which is not guaranteed
40 // to be a multiple of 4 may generate extremely slow code or runtime errors,
41 // and must be avoided. The compiler needs to be told about the unaligned
42 // access, so it can generate reasonably-efficient code for the access
43 // (in MIPS, this means generating two instructions "lwl" and "lwr", instead
44 // of the one instruction "lw" which faults on unaligned/ access). The way to
45 // tell the compiler this is with __attribute__((packed)). This will also
46 // cause the sanitizer not to generate runtime alignment checks for this
47 // access.
48 
49 #ifndef SEASTAR_MODULE
50 #include <type_traits>
51 #include <seastar/util/modules.hh>
52 #endif
53 
54 namespace seastar {
55 
56 SEASTAR_MODULE_EXPORT
57 template <typename T>
58 struct unaligned {
59  // This is made to support only simple types, so it is fine to
60  // require them to be trivially copy constructible.
61  static_assert(std::is_trivially_copy_constructible_v<T>);
62  T raw;
63  unaligned() noexcept = default;
64  unaligned(T x) noexcept : raw(x) {}
65  unaligned& operator=(const T& x) noexcept { raw = x; return *this; }
66  operator T() const noexcept { return raw; }
67 } __attribute__((packed));
68 
69 
70 template <typename T, typename F>
71 [[deprecated("violates strict aliasing rules. See issue #165.")]]
72 inline auto unaligned_cast(F* p) noexcept {
73  return reinterpret_cast<unaligned<std::remove_pointer_t<T>>*>(p);
74 }
75 
76 template <typename T, typename F>
77 [[deprecated("violates strict aliasing rules. See issue #165.")]]
78 inline auto unaligned_cast(const F* p) noexcept {
79  return reinterpret_cast<const unaligned<std::remove_pointer_t<T>>*>(p);
80 }
81 
82 }
Seastar API namespace.
Definition: abort_on_ebadf.hh:26
Definition: unaligned.hh:58