The Pedigree Project 0.1
MemoryPressureKiller.cc
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include "pedigree/kernel/Log.h"
21#include "pedigree/kernel/Metrics.h"
22#include "pedigree/kernel/Subsystem.h"
23#include "pedigree/kernel/TargetInfo.h"
24#include "pedigree/kernel/process/MemoryPressureKiller.h"
25#include "pedigree/kernel/process/Process.h"
26#include "pedigree/kernel/process/Scheduler.h"
27#include "pedigree/kernel/processor/Processor.h"
28#include "pedigree/kernel/processor/types.h"
29#include "pedigree/kernel/utilities/utility.h"
30
31static size_t mb(size_t pages) {
32 return (pages * TargetInfo::getPageSize()) / 0x100000;
33}
34
37 for (size_t i = 0; i < Scheduler::instance().getNumProcesses(); ++i) {
39 if (!Scheduler::instance().acquireProcess(process, i)) {
40 continue;
41 }
42
43 // Requires a subsystem to kill.
44 if (!process->getSubsystem())
45 continue;
46
47 if (!candidate)
48 candidate = pedigree_std::move(process);
49 else {
50 if (process->getPhysicalPageCount() > candidate->getPhysicalPageCount()) {
51 candidate = pedigree_std::move(process);
52 }
53 }
54 }
55
56 if (!candidate)
57 return false;
58
59 NOTICE_NOLOCK("MemoryPressureProcessKiller will kill pid=" << Dec << candidate->getId() << Hex);
60 NOTICE_NOLOCK("virt=" << Dec << mb(candidate->getVirtualPageCount())
61 << "m phys=" << mb(candidate->getPhysicalPageCount())
62 << "m shared=" << mb(candidate->getSharedPageCount()) << "m" << Hex);
63
64 // Hard kill the process (SIGKILL, in POSIX terms).
65 // We cannot afford to let the thread do anything else.
66 Subsystem* pSubsystem = candidate->getSubsystem();
68 if (!candidate->acquireThread(target, static_cast<size_t>(0))) {
69 return false;
70 }
71 if (Processor::m_Initialised == 2) {
72 Metrics::increment(Metrics::MemoryPressureKill);
73 }
74 pSubsystem->kill(Subsystem::Unknown, target.get());
75
76 // Success means a victim accepted termination, not that its pages are
77 // already reclaimed. The pressure manager may make another pass later.
78 return true;
79}
size_t getId()
Definition Process.h:499
MUST_USE_RESULT bool acquireThread(ThreadLease &lease, size_t n)
Definition Process.cc:1385
static size_t m_Initialised
Definition Processor.h:483
static Scheduler & instance()
Definition Scheduler.h:96
size_t getNumProcesses()
Definition Scheduler.cc:268
MUST_USE_RESULT bool acquireProcess(ProcessLease &lease, size_t n)
Definition Scheduler.cc:275
virtual bool kill(KillReason killReason, Thread *pThread=0)=0
static constexpr size_t getPageSize() noexcept
Definition TargetInfo.h:40
@ Dec
Definition Log.h:126
@ Hex
Definition Log.h:124