File: mozmemory_stall.h

package info (click to toggle)
firefox 149.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,767,760 kB
  • sloc: cpp: 7,416,064; javascript: 6,752,859; ansic: 3,774,850; python: 1,250,473; xml: 641,578; asm: 439,191; java: 186,617; sh: 56,634; makefile: 18,856; objc: 13,092; perl: 12,763; pascal: 5,960; yacc: 4,583; cs: 3,846; lex: 1,720; ruby: 1,002; php: 436; lisp: 258; awk: 105; sql: 66; sed: 53; csh: 10; exp: 6
file content (80 lines) | stat: -rw-r--r-- 2,497 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozjemalloc_stall_h
#define mozjemalloc_stall_h

#include <optional>

#if defined(MOZ_MEMORY) && defined(XP_WIN)
#  include "mozmemory_wrap.h"
#endif

// See
// https://hacks.mozilla.org/2022/11/improving-firefox-stability-with-this-one-weird-trick/

namespace mozilla {

namespace detail {
// Helper for StallAndRetry error messages.
template <typename T>
constexpr bool is_std_optional = false;
template <typename T>
constexpr bool is_std_optional<std::optional<T>> = true;
}  // namespace detail

struct StallSpecs {
  // Maximum number of retry-attempts before giving up.
  size_t maxAttempts;
  // Delay time between successive events.
  size_t delayMs;

  // Retry a fallible operation until it succeeds or until we've run out of
  // retries.
  //
  // Note that this invokes `aDelayFunc` immediately upon being called! It's
  // intended for use in the unhappy path, after an initial attempt has failed.
  //
  // The function type here may be read:
  // ```
  // fn StallAndRetry<R>(
  //     delay_func: impl Fn(usize) -> (),
  //     operation: impl Fn() -> Option<R>,
  // ) -> Option<R>;
  // ```
  //
  template <typename DelayFunc, typename OpFunc>
  auto StallAndRetry(DelayFunc&& aDelayFunc, OpFunc&& aOperation) const
      -> decltype(aOperation()) {
    {
      // Explicit typecheck for OpFunc, to provide an explicit error message.
      using detail::is_std_optional;
      static_assert(is_std_optional<decltype(aOperation())>,
                    "aOperation() must return std::optional");

      // (clang's existing error messages suffice for aDelayFunc.)
    }

    for (size_t i = 0; i < maxAttempts; ++i) {
      aDelayFunc(delayMs);
      if (const auto opt = aOperation()) {
        return opt;
      }
    }
    return std::nullopt;
  }
};

#if defined(MOZ_MEMORY) && defined(XP_WIN)
MOZ_JEMALLOC_API StallSpecs GetAllocatorStallSpecs();
MOZ_JEMALLOC_API_NODISCARD void* MozVirtualAlloc(void* lpAddress, size_t dwSize,
                                                 uint32_t flAllocationType,
                                                 uint32_t flProtect);
#endif

}  // namespace mozilla

#endif  // mozjemalloc_stall_h