xref: /aosp_15_r20/external/cronet/base/profiler/stack_buffer.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2019 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_PROFILER_STACK_BUFFER_H_
6*6777b538SAndroid Build Coastguard Worker #define BASE_PROFILER_STACK_BUFFER_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
9*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
10*6777b538SAndroid Build Coastguard Worker #include <memory>
11*6777b538SAndroid Build Coastguard Worker 
12*6777b538SAndroid Build Coastguard Worker #include "base/base_export.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/memory/aligned_memory.h"
14*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
15*6777b538SAndroid Build Coastguard Worker 
16*6777b538SAndroid Build Coastguard Worker namespace base {
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker // This class contains a buffer for stack copies that can be shared across
19*6777b538SAndroid Build Coastguard Worker // multiple instances of StackSampler.
20*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT StackBuffer {
21*6777b538SAndroid Build Coastguard Worker  public:
22*6777b538SAndroid Build Coastguard Worker   // The expected alignment of the stack on the current platform. Windows and
23*6777b538SAndroid Build Coastguard Worker   // System V AMD64 ABIs on x86, x64, and ARM require the stack to be aligned
24*6777b538SAndroid Build Coastguard Worker   // to twice the pointer size. Excepted from this requirement is code setting
25*6777b538SAndroid Build Coastguard Worker   // up the stack during function calls (between pushing the return address
26*6777b538SAndroid Build Coastguard Worker   // and the end of the function prologue). The profiler will sometimes
27*6777b538SAndroid Build Coastguard Worker   // encounter this exceptional case for leaf frames.
28*6777b538SAndroid Build Coastguard Worker   static constexpr size_t kPlatformStackAlignment = 2 * sizeof(uintptr_t);
29*6777b538SAndroid Build Coastguard Worker 
30*6777b538SAndroid Build Coastguard Worker   explicit StackBuffer(size_t buffer_size);
31*6777b538SAndroid Build Coastguard Worker 
32*6777b538SAndroid Build Coastguard Worker   StackBuffer(const StackBuffer&) = delete;
33*6777b538SAndroid Build Coastguard Worker   StackBuffer& operator=(const StackBuffer&) = delete;
34*6777b538SAndroid Build Coastguard Worker 
35*6777b538SAndroid Build Coastguard Worker   ~StackBuffer();
36*6777b538SAndroid Build Coastguard Worker 
37*6777b538SAndroid Build Coastguard Worker   // Returns a kPlatformStackAlignment-aligned pointer to the stack buffer.
buffer()38*6777b538SAndroid Build Coastguard Worker   uintptr_t* buffer() const {
39*6777b538SAndroid Build Coastguard Worker     // Aligned during allocation.
40*6777b538SAndroid Build Coastguard Worker     return buffer_.get();
41*6777b538SAndroid Build Coastguard Worker   }
42*6777b538SAndroid Build Coastguard Worker 
43*6777b538SAndroid Build Coastguard Worker   // Size in bytes.
size()44*6777b538SAndroid Build Coastguard Worker   size_t size() const { return size_; }
45*6777b538SAndroid Build Coastguard Worker 
46*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_CHROMEOS)
47*6777b538SAndroid Build Coastguard Worker   // Tell the kernel that we no longer need the data currently in the upper
48*6777b538SAndroid Build Coastguard Worker   // parts of the buffer and that the kernel may discard it to free up space.
49*6777b538SAndroid Build Coastguard Worker   // Specifically, the bytes from |(uint8_t*)buffer + retained_bytes| to the
50*6777b538SAndroid Build Coastguard Worker   // end of the buffer may be discarded, while the bytes from |buffer| to
51*6777b538SAndroid Build Coastguard Worker   // |(uint8_t*)buffer + retained_bytes - 1| will not be affected.
52*6777b538SAndroid Build Coastguard Worker   // The program can still write to that part of the buffer, but should not read
53*6777b538SAndroid Build Coastguard Worker   // from that part of buffer until after the next write. (The contents of that
54*6777b538SAndroid Build Coastguard Worker   // part of the buffer are undefined.)
55*6777b538SAndroid Build Coastguard Worker   // After calling this function, there may be a page fault on the next write to
56*6777b538SAndroid Build Coastguard Worker   // that area, so it should only be called when parts of the buffer were
57*6777b538SAndroid Build Coastguard Worker   // written to and will probably not be written to again soon.
58*6777b538SAndroid Build Coastguard Worker   void MarkUpperBufferContentsAsUnneeded(size_t retained_bytes);
59*6777b538SAndroid Build Coastguard Worker #endif
60*6777b538SAndroid Build Coastguard Worker 
61*6777b538SAndroid Build Coastguard Worker  private:
62*6777b538SAndroid Build Coastguard Worker   // The size in bytes of the requested buffer allocation.
63*6777b538SAndroid Build Coastguard Worker   const size_t size_;
64*6777b538SAndroid Build Coastguard Worker 
65*6777b538SAndroid Build Coastguard Worker   // The buffer to store the stack. Already aligned.
66*6777b538SAndroid Build Coastguard Worker   const std::unique_ptr<uintptr_t, AlignedFreeDeleter> buffer_;
67*6777b538SAndroid Build Coastguard Worker };
68*6777b538SAndroid Build Coastguard Worker 
69*6777b538SAndroid Build Coastguard Worker }  // namespace base
70*6777b538SAndroid Build Coastguard Worker 
71*6777b538SAndroid Build Coastguard Worker #endif  // BASE_PROFILER_STACK_BUFFER_H_
72