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