#include "base/process/memory.h"
#include <stddef.h>
#include <new>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/process/internal_linux.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "partition_alloc/buildflags.h"
#if PA_BUILDFLAG(USE_ALLOCATOR_SHIM)
#include "partition_alloc/shim/allocator_shim.h"
#elif !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) && defined(LIBC_GLIBC)
extern "C" {
void* __libc_malloc(size_t);
void __libc_free(void*);
void* __libc_calloc(size_t, size_t);
}
#endif
namespace base {
namespace {
void ReleaseReservationOrTerminate() {
if (internal::ReleaseAddressSpaceReservation()) {
return;
}
TerminateBecauseOutOfMemory(0);
}
}
void EnableTerminationOnHeapCorruption() {
}
void EnableTerminationOnOutOfMemory() {
std::set_new_handler(&ReleaseReservationOrTerminate);
#if PA_BUILDFLAG(USE_ALLOCATOR_SHIM)
allocator_shim::SetCallNewHandlerOnMallocFailure(true);
#endif
}
class AdjustOOMScoreHelper {
public:
AdjustOOMScoreHelper() = delete;
AdjustOOMScoreHelper(const AdjustOOMScoreHelper&) = delete;
AdjustOOMScoreHelper& operator=(const AdjustOOMScoreHelper&) = delete;
static bool AdjustOOMScore(ProcessId process, int score);
};
bool AdjustOOMScoreHelper::AdjustOOMScore(ProcessId process, int score) {
if (score < 0 || score > kMaxOomScore) {
return false;
}
FilePath oom_path(internal::GetProcPidDir(process));
base::ScopedAllowBlocking allow_blocking;
FilePath oom_file = oom_path.AppendASCII("oom_score_adj");
if (PathExists(oom_file)) {
std::string score_str = NumberToString(score);
DVLOG(1) << "Adjusting oom_score_adj of " << process << " to " << score_str;
return WriteFile(oom_file, as_byte_span(score_str));
}
oom_file = oom_path.AppendASCII("oom_adj");
if (PathExists(oom_file)) {
const int kMaxOldOomScore = 15;
int converted_score = score * kMaxOldOomScore / kMaxOomScore;
std::string score_str = NumberToString(converted_score);
DVLOG(1) << "Adjusting oom_adj of " << process << " to " << score_str;
return WriteFile(oom_file, as_byte_span(score_str));
}
return false;
}
bool AdjustOOMScore(ProcessId process, int score) {
return AdjustOOMScoreHelper::AdjustOOMScore(process, score);
}
bool UncheckedCalloc(size_t num_items, size_t size, void** result) {
#if PA_BUILDFLAG(USE_ALLOCATOR_SHIM)
*result = allocator_shim::UncheckedCalloc(num_items, size);
#elif defined(MEMORY_TOOL_REPLACES_ALLOCATOR) || !defined(LIBC_GLIBC)
*result = calloc(num_items, size);
#elif defined(LIBC_GLIBC)
*result = __libc_calloc(num_items, size);
#endif
return *result != nullptr;
}
bool UncheckedMalloc(size_t size, void** result) {
#if PA_BUILDFLAG(USE_ALLOCATOR_SHIM)
*result = allocator_shim::UncheckedAlloc(size);
#elif defined(MEMORY_TOOL_REPLACES_ALLOCATOR) || !defined(LIBC_GLIBC)
*result = malloc(size);
#elif defined(LIBC_GLIBC)
*result = __libc_malloc(size);
#endif
return *result != nullptr;
}
void UncheckedFree(void* ptr) {
#if PA_BUILDFLAG(USE_ALLOCATOR_SHIM)
allocator_shim::UncheckedFree(ptr);
#elif defined(MEMORY_TOOL_REPLACES_ALLOCATOR) || !defined(LIBC_GLIBC)
free(ptr);
#elif defined(LIBC_GLIBC)
__libc_free(ptr);
#endif
}
}