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
54namespace seastar {
55
56SEASTAR_MODULE_EXPORT
57template <typename T>
58struct 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
70template <typename T, typename F>
71[[deprecated("violates strict aliasing rules. See issue #165.")]]
72inline auto unaligned_cast(F* p) noexcept {
73 return reinterpret_cast<unaligned<std::remove_pointer_t<T>>*>(p);
74}
75
76template <typename T, typename F>
77[[deprecated("violates strict aliasing rules. See issue #165.")]]
78inline 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