mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2025-02-26 11:53:19 +03:00
72 lines
2.6 KiB
C++
72 lines
2.6 KiB
C++
// Copyright 2019 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "base/profiler/stack_buffer.h"
|
|
|
|
#include "base/bits.h"
|
|
#if BUILDFLAG(IS_CHROMEOS)
|
|
#include <sys/mman.h>
|
|
|
|
#include <ostream>
|
|
|
|
#include "base/check.h"
|
|
#include "base/check_op.h"
|
|
#include "base/memory/page_size.h"
|
|
#endif // #if BUILDFLAG(IS_CHROMEOS)
|
|
|
|
namespace base {
|
|
|
|
constexpr size_t StackBuffer::kPlatformStackAlignment;
|
|
|
|
#if BUILDFLAG(IS_CHROMEOS)
|
|
|
|
void StackBuffer::MarkUpperBufferContentsAsUnneeded(size_t retained_bytes) {
|
|
// Round up to the next multiple of the page size. madvise needs the
|
|
// starting address to be page aligned. Since buffer_.get() is
|
|
// already page aligned, we just need to round up the retained bytes.
|
|
size_t actual_retained_bytes = bits::AlignUp(retained_bytes, GetPageSize());
|
|
|
|
// Avoid passing a negative discard_size to madvise(). Doing so would randomly
|
|
// discard large amounts of memory causing weird crashes.
|
|
CHECK_LE(actual_retained_bytes, size_);
|
|
|
|
uint8_t* start_of_discard =
|
|
reinterpret_cast<uint8_t*>(buffer_.get()) + actual_retained_bytes;
|
|
size_t discard_size = size_ - actual_retained_bytes;
|
|
int result = madvise(start_of_discard, discard_size, MADV_DONTNEED);
|
|
|
|
DPCHECK(result == 0) << "madvise failed: ";
|
|
}
|
|
|
|
#endif // #if BUILDFLAG(IS_CHROMEOS)
|
|
|
|
StackBuffer::StackBuffer(size_t buffer_size)
|
|
#if BUILDFLAG(IS_CHROMEOS)
|
|
// On ChromeOS, we have 8MB of stack space per thread; however, we normally
|
|
// only use a small fraction of that. To avoid blowing our memory budget,
|
|
// we use madvise(MADV_DONTNEED) to let the kernel discard the memory in the
|
|
// 8MB buffer except when we are actively using it. For madvise() to work,
|
|
// we need |buffer_| to be aligned to a page boundary.
|
|
//
|
|
// We also need the |size_| to be a multiple of the page size so that we
|
|
// don't pass partial pages to madvise(). This isn't documented but the
|
|
// program will consistently crash otherwise.
|
|
: size_(bits::AlignUp(buffer_size, GetPageSize())),
|
|
buffer_(static_cast<uintptr_t*>(AlignedAlloc(size_, GetPageSize()))) {
|
|
// Our (very large) buffer may already have data written to it & thus have
|
|
// backing pages. Tell the kernel we don't need the current contents.
|
|
MarkUpperBufferContentsAsUnneeded(0);
|
|
}
|
|
#else // #if BUILDFLAG(IS_CHROMEOS)
|
|
: size_(buffer_size),
|
|
buffer_(static_cast<uintptr_t*>(
|
|
AlignedAlloc(size_, kPlatformStackAlignment))) {
|
|
static_assert(bits::IsPowerOfTwo(kPlatformStackAlignment));
|
|
}
|
|
#endif // !#if BUILDFLAG(IS_CHROMEOS)
|
|
|
|
StackBuffer::~StackBuffer() = default;
|
|
|
|
} // namespace base
|