[go: nahoru, domu]

blob: f0dd3307e019ce9762c6463da9bc67239afe935d [file] [log] [blame]
Ryan Powellb569c222019-08-20 16:59:081// Copyright 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Albert J. Wong23183a12021-08-13 00:23:355#include "components/memory_pressure/system_memory_pressure_evaluator_mac.h"
Ryan Powellb569c222019-08-20 16:59:086
7#include <CoreFoundation/CoreFoundation.h>
8
9#include <dlfcn.h>
10#include <stddef.h>
11#include <sys/sysctl.h>
12
13#include <cmath>
14
15#include "base/bind.h"
Hans Wennborgc3cffa62020-04-27 10:09:1216#include "base/check_op.h"
Ryan Powellb569c222019-08-20 16:59:0817#include "base/mac/mac_util.h"
18#include "base/memory/memory_pressure_monitor.h"
Ryan Powell12fadab22019-09-04 18:41:3219#include "base/threading/sequenced_task_runner_handle.h"
Ryan Powellb569c222019-08-20 16:59:0820
Avi Drissmanc45f85f2022-05-10 22:07:0221namespace memory_pressure::mac {
Ryan Powellb569c222019-08-20 16:59:0822
23base::MemoryPressureListener::MemoryPressureLevel
24SystemMemoryPressureEvaluator::MemoryPressureLevelForMacMemoryPressureLevel(
25 int mac_memory_pressure_level) {
26 switch (mac_memory_pressure_level) {
27 case DISPATCH_MEMORYPRESSURE_NORMAL:
28 return base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE;
29 case DISPATCH_MEMORYPRESSURE_WARN:
30 return base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE;
31 case DISPATCH_MEMORYPRESSURE_CRITICAL:
32 return base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL;
33 }
34 return base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE;
35}
36
37SystemMemoryPressureEvaluator::SystemMemoryPressureEvaluator(
38 std::unique_ptr<MemoryPressureVoter> voter)
Albert J. Wong23183a12021-08-13 00:23:3539 : memory_pressure::SystemMemoryPressureEvaluator(std::move(voter)),
Ryan Powella9f69e032019-08-20 23:18:2740 memory_level_event_source_(dispatch_source_create(
Ryan Powellb569c222019-08-20 16:59:0841 DISPATCH_SOURCE_TYPE_MEMORYPRESSURE,
42 0,
43 DISPATCH_MEMORYPRESSURE_WARN | DISPATCH_MEMORYPRESSURE_CRITICAL |
44 DISPATCH_MEMORYPRESSURE_NORMAL,
Ryan Powell12fadab22019-09-04 18:41:3245 dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0))),
46 weak_ptr_factory_(this) {
47 // WeakPtr needed because there is no guarantee that |this| is still be alive
48 // when the task posted to the TaskRunner or event handler runs.
49 base::WeakPtr<SystemMemoryPressureEvaluator> weak_this =
50 weak_ptr_factory_.GetWeakPtr();
51 scoped_refptr<base::TaskRunner> task_runner =
52 base::SequencedTaskRunnerHandle::Get();
53
Ryan Powellb569c222019-08-20 16:59:0854 // Attach an event handler to the memory pressure event source.
55 if (memory_level_event_source_.get()) {
56 dispatch_source_set_event_handler(memory_level_event_source_, ^{
Ryan Powell12fadab22019-09-04 18:41:3257 task_runner->PostTask(
58 FROM_HERE,
59 base::BindRepeating(
60 &SystemMemoryPressureEvaluator::OnMemoryPressureChanged,
61 weak_this));
Ryan Powellb569c222019-08-20 16:59:0862 });
63
64 // Start monitoring the event source.
65 dispatch_resume(memory_level_event_source_);
66 }
67}
68
69SystemMemoryPressureEvaluator::~SystemMemoryPressureEvaluator() {
70 // Remove the memory pressure event source.
71 if (memory_level_event_source_.get()) {
72 dispatch_source_cancel(memory_level_event_source_);
73 }
74}
75
76int SystemMemoryPressureEvaluator::GetMacMemoryPressureLevel() {
77 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
78 // Get the raw memory pressure level from macOS.
79 int mac_memory_pressure_level;
80 size_t length = sizeof(int);
81 sysctlbyname("kern.memorystatus_vm_pressure_level",
82 &mac_memory_pressure_level, &length, nullptr, 0);
83
84 return mac_memory_pressure_level;
85}
86
87void SystemMemoryPressureEvaluator::UpdatePressureLevel() {
88 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
89 // Get the current macOS pressure level and convert to the corresponding
90 // Chrome pressure level.
Ryan Powella9f69e032019-08-20 23:18:2791 SetCurrentVote(MemoryPressureLevelForMacMemoryPressureLevel(
92 GetMacMemoryPressureLevel()));
Ryan Powellb569c222019-08-20 16:59:0893}
94
Ryan Powell12fadab22019-09-04 18:41:3295void SystemMemoryPressureEvaluator::OnMemoryPressureChanged() {
Ryan Powellb569c222019-08-20 16:59:0896 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
97 // The OS has sent a notification that the memory pressure level has changed.
98 // Go through the normal memory pressure level checking mechanism so that
99 // |current_vote_| and UMA get updated to the current value.
100 UpdatePressureLevel();
101
102 // Run the callback that's waiting on memory pressure change notifications.
103 // The convention is to not send notifiations on memory pressure returning to
104 // normal.
Ryan Powella9f69e032019-08-20 23:18:27105 bool notify = current_vote() !=
106 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE;
107 SendCurrentVote(notify);
Ryan Powellb569c222019-08-20 16:59:08108}
109
Avi Drissmanc45f85f2022-05-10 22:07:02110} // namespace memory_pressure::mac