1*d89ec533Spatrick //===-- options.h -----------------------------------------------*- C++ -*-===//
2*d89ec533Spatrick //
3*d89ec533Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*d89ec533Spatrick // See https://llvm.org/LICENSE.txt for license information.
5*d89ec533Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*d89ec533Spatrick //
7*d89ec533Spatrick //===----------------------------------------------------------------------===//
8*d89ec533Spatrick
9*d89ec533Spatrick #ifndef SCUDO_OPTIONS_H_
10*d89ec533Spatrick #define SCUDO_OPTIONS_H_
11*d89ec533Spatrick
12*d89ec533Spatrick #include "atomic_helpers.h"
13*d89ec533Spatrick #include "common.h"
14*d89ec533Spatrick #include "memtag.h"
15*d89ec533Spatrick
16*d89ec533Spatrick namespace scudo {
17*d89ec533Spatrick
18*d89ec533Spatrick enum class OptionBit {
19*d89ec533Spatrick MayReturnNull,
20*d89ec533Spatrick FillContents0of2,
21*d89ec533Spatrick FillContents1of2,
22*d89ec533Spatrick DeallocTypeMismatch,
23*d89ec533Spatrick DeleteSizeMismatch,
24*d89ec533Spatrick TrackAllocationStacks,
25*d89ec533Spatrick UseOddEvenTags,
26*d89ec533Spatrick UseMemoryTagging,
27*d89ec533Spatrick AddLargeAllocationSlack,
28*d89ec533Spatrick };
29*d89ec533Spatrick
30*d89ec533Spatrick struct Options {
31*d89ec533Spatrick u32 Val;
32*d89ec533Spatrick
getOptions33*d89ec533Spatrick bool get(OptionBit Opt) const { return Val & (1U << static_cast<u32>(Opt)); }
34*d89ec533Spatrick
getFillContentsModeOptions35*d89ec533Spatrick FillContentsMode getFillContentsMode() const {
36*d89ec533Spatrick return static_cast<FillContentsMode>(
37*d89ec533Spatrick (Val >> static_cast<u32>(OptionBit::FillContents0of2)) & 3);
38*d89ec533Spatrick }
39*d89ec533Spatrick };
40*d89ec533Spatrick
useMemoryTagging(Options Options)41*d89ec533Spatrick template <typename Config> bool useMemoryTagging(Options Options) {
42*d89ec533Spatrick return allocatorSupportsMemoryTagging<Config>() &&
43*d89ec533Spatrick Options.get(OptionBit::UseMemoryTagging);
44*d89ec533Spatrick }
45*d89ec533Spatrick
46*d89ec533Spatrick struct AtomicOptions {
47*d89ec533Spatrick atomic_u32 Val = {};
48*d89ec533Spatrick
loadAtomicOptions49*d89ec533Spatrick Options load() const { return Options{atomic_load_relaxed(&Val)}; }
50*d89ec533Spatrick
clearAtomicOptions51*d89ec533Spatrick void clear(OptionBit Opt) {
52*d89ec533Spatrick atomic_fetch_and(&Val, ~(1U << static_cast<u32>(Opt)),
53*d89ec533Spatrick memory_order_relaxed);
54*d89ec533Spatrick }
55*d89ec533Spatrick
setAtomicOptions56*d89ec533Spatrick void set(OptionBit Opt) {
57*d89ec533Spatrick atomic_fetch_or(&Val, 1U << static_cast<u32>(Opt), memory_order_relaxed);
58*d89ec533Spatrick }
59*d89ec533Spatrick
setFillContentsModeAtomicOptions60*d89ec533Spatrick void setFillContentsMode(FillContentsMode FillContents) {
61*d89ec533Spatrick u32 Opts = atomic_load_relaxed(&Val), NewOpts;
62*d89ec533Spatrick do {
63*d89ec533Spatrick NewOpts = Opts;
64*d89ec533Spatrick NewOpts &= ~(3U << static_cast<u32>(OptionBit::FillContents0of2));
65*d89ec533Spatrick NewOpts |= static_cast<u32>(FillContents)
66*d89ec533Spatrick << static_cast<u32>(OptionBit::FillContents0of2);
67*d89ec533Spatrick } while (!atomic_compare_exchange_strong(&Val, &Opts, NewOpts,
68*d89ec533Spatrick memory_order_relaxed));
69*d89ec533Spatrick }
70*d89ec533Spatrick };
71*d89ec533Spatrick
72*d89ec533Spatrick } // namespace scudo
73*d89ec533Spatrick
74*d89ec533Spatrick #endif // SCUDO_OPTIONS_H_
75