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