]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (c) 2006-2018 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * This file contains Original Code and/or Modifications of Original Code | |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
14 | * | |
15 | * Please obtain a copy of the License at | |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
17 | * | |
18 | * The Original Code and all software distributed under the License are | |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
23 | * Please see the License for the specific language governing rights and | |
24 | * limitations under the License. | |
25 | * | |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ | |
27 | */ | |
28 | ||
29 | #ifndef SYS_MEMORYSTATUS_FREEZE_H | |
30 | #define SYS_MEMORYSTATUS_FREEZE_H | |
31 | ||
32 | #include <stdint.h> | |
33 | #include <sys/time.h> | |
34 | #include <sys/proc.h> | |
35 | #include <sys/param.h> | |
36 | #include <sys/kern_memorystatus.h> | |
37 | #include <mach/resource_monitors.h> // command/proc_name_t | |
38 | ||
39 | typedef struct memorystatus_freeze_entry { | |
40 | int32_t pid; | |
41 | uint32_t flags; | |
42 | uint32_t pages; | |
43 | } memorystatus_freeze_entry_t; | |
44 | ||
45 | #ifdef PRIVATE | |
46 | #define FREEZE_PROCESSES_MAX 20 | |
47 | #endif /* PRIVATE */ | |
48 | ||
49 | #ifdef XNU_KERNEL_PRIVATE | |
50 | ||
51 | extern unsigned long freeze_threshold_percentage; | |
52 | extern unsigned int memorystatus_frozen_count; /* # of processes that are currently frozen. */ | |
53 | extern unsigned int memorystatus_frozen_processes_max; | |
54 | extern unsigned int memorystatus_frozen_shared_mb; | |
55 | extern unsigned int memorystatus_frozen_shared_mb_max; | |
56 | extern unsigned int memorystatus_freeze_shared_mb_per_process_max; /* Max. MB allowed per process to be freezer-eligible. */ | |
57 | extern unsigned int memorystatus_freeze_private_shared_pages_ratio; /* Ratio of private:shared pages for a process to be freezer-eligible. */ | |
58 | extern unsigned int memorystatus_suspended_count; | |
59 | extern unsigned int memorystatus_thaw_count; /* # of processes that have been thawed in the current interval. */ | |
60 | extern unsigned int memorystatus_refreeze_eligible_count; /* # of processes currently thawed i.e. have state on disk & in-memory */ | |
61 | extern uint32_t memorystatus_freeze_current_interval; /* Monotonically increasing interval id. */ | |
62 | ||
63 | void memorystatus_freeze_init(void); | |
64 | extern int memorystatus_freeze_process_sync(proc_t p); | |
65 | ||
66 | #ifdef CONFIG_FREEZE | |
67 | ||
68 | #define FREEZE_PAGES_MIN ( 8 * 1024 * 1024 / PAGE_SIZE) | |
69 | #define FREEZE_PAGES_MAX (max_task_footprint_mb == 0 ? INT_MAX : (max_task_footprint_mb << (20 - PAGE_SHIFT))) | |
70 | ||
71 | #define FREEZE_SUSPENDED_THRESHOLD_DEFAULT 4 | |
72 | ||
73 | #define FREEZE_DAILY_MB_MAX_DEFAULT 1024 | |
74 | #define FREEZE_DEGRADATION_BUDGET_THRESHOLD 25 //degraded perf. when the daily budget left falls below this threshold percentage | |
75 | ||
76 | #define MAX_FROZEN_SHARED_MB_PERCENT 10 | |
77 | #define MAX_FROZEN_PROCESS_DEMOTIONS 2 | |
78 | #define MIN_THAW_DEMOTION_THRESHOLD 5 | |
79 | #define MIN_THAW_REFREEZE_THRESHOLD 3 /* min # of global thaws needed for us to consider refreezing these processes. */ | |
80 | ||
81 | typedef struct throttle_interval_t { | |
82 | uint32_t mins; | |
83 | uint32_t burst_multiple; | |
84 | uint32_t pageouts; | |
85 | uint32_t max_pageouts; | |
86 | mach_timespec_t ts; | |
87 | } throttle_interval_t; | |
88 | ||
89 | extern boolean_t memorystatus_freeze_enabled; | |
90 | extern int memorystatus_freeze_wakeup; | |
91 | ||
92 | /* Thresholds */ | |
93 | extern unsigned int memorystatus_freeze_threshold; | |
94 | extern unsigned int memorystatus_freeze_pages_min; | |
95 | extern unsigned int memorystatus_freeze_pages_max; | |
96 | extern unsigned int memorystatus_freeze_suspended_threshold; | |
97 | extern unsigned int memorystatus_freeze_daily_mb_max; | |
98 | extern uint64_t memorystatus_freeze_budget_pages_remaining; //remaining # of pages that can be frozen to disk | |
99 | extern boolean_t memorystatus_freeze_degradation; //protected by the freezer mutex. Signals we are in a degraded freeze mode. | |
100 | ||
101 | extern unsigned int memorystatus_max_frozen_demotions_daily; | |
102 | extern unsigned int memorystatus_thaw_count_demotion_threshold; | |
103 | ||
104 | #if DEVELOPMENT || DEBUG | |
105 | #define FREEZER_CONTROL_GET_STATUS (1) | |
106 | #endif /* DEVELOPMENT || DEBUG */ | |
107 | ||
108 | extern boolean_t memorystatus_freeze_enabled; | |
109 | extern int memorystatus_freeze_wakeup; | |
110 | extern int memorystatus_freeze_jetsam_band; /* the jetsam band which will contain P_MEMSTAT_FROZEN processes */ | |
111 | ||
112 | boolean_t memorystatus_freeze_thread_should_run(void); | |
113 | int memorystatus_set_process_is_freezable(pid_t pid, boolean_t is_freezable); | |
114 | int memorystatus_get_process_is_freezable(pid_t pid, int *is_freezable); | |
115 | int memorystatus_freezer_control(int32_t flags, user_addr_t buffer, size_t buffer_size, int32_t *retval); | |
116 | void memorystatus_freeze_init_proc(proc_t p); | |
117 | errno_t memorystatus_get_process_is_frozen(pid_t pid, int *is_freezable); | |
118 | ||
119 | /* Freezer counters collected for telemtry */ | |
120 | struct memorystatus_freezer_stats_t { | |
121 | /* | |
122 | * # of processes that we've considered freezing. | |
123 | * Used to normalize the error reasons below. | |
124 | */ | |
125 | uint64_t mfs_process_considered_count; | |
126 | ||
127 | /* | |
128 | * The following counters track how many times we've failed to freeze | |
129 | * a process because of a specific FREEZER_ERROR. | |
130 | */ | |
131 | /* EXCESS_SHARED_MEMORY */ | |
132 | uint64_t mfs_error_excess_shared_memory_count; | |
133 | /* LOW_PRIVATE_SHARED_RATIO */ | |
134 | uint64_t mfs_error_low_private_shared_ratio_count; | |
135 | /* NO_COMPRESSOR_SPACE */ | |
136 | uint64_t mfs_error_no_compressor_space_count; | |
137 | /* NO_SWAP_SPACE */ | |
138 | uint64_t mfs_error_no_swap_space_count; | |
139 | /* pages < memorystatus_freeze_pages_min */ | |
140 | uint64_t mfs_error_below_min_pages_count; | |
141 | /* dasd determined it was unlikely to be relaunched. */ | |
142 | uint64_t mfs_error_low_probability_of_use_count; | |
143 | /* transient reasons (like inability to acquire a lock). */ | |
144 | uint64_t mfs_error_other_count; | |
145 | ||
146 | /* | |
147 | * # of times that we saw memorystatus_available_pages <= memorystatus_freeze_threshold. | |
148 | * Used to normalize skipped_full_count and shared_mb_high_count. | |
149 | */ | |
150 | uint64_t mfs_below_threshold_count; | |
151 | ||
152 | /* Skipped running the freezer because we were out of slots */ | |
153 | uint64_t mfs_skipped_full_count; | |
154 | ||
155 | /* Skipped running the freezer because we were over the shared mb limit*/ | |
156 | uint64_t mfs_skipped_shared_mb_high_count; | |
157 | ||
158 | /* | |
159 | * How many pages have not been sent to swap because they were in a shared object? | |
160 | * This is being used to gather telemtry so we can understand the impact we'd have | |
161 | * on our NAND budget if we did swap out these pages. | |
162 | */ | |
163 | uint64_t mfs_shared_pages_skipped; | |
164 | ||
165 | /* | |
166 | * A running sum of the total number of bytes sent to NAND during | |
167 | * refreeze operations since boot. | |
168 | */ | |
169 | uint64_t mfs_bytes_refrozen; | |
170 | /* The number of refreeze operations since boot */ | |
171 | uint64_t mfs_refreeze_count; | |
172 | ||
173 | /* The number of proceses which have been frozen at least once in the current interval. */ | |
174 | uint64_t mfs_processes_frozen; | |
175 | /* THe number of processes which have been thawed at least once in the current interval. */ | |
176 | uint64_t mfs_processes_thawed; | |
177 | }; | |
178 | extern struct memorystatus_freezer_stats_t memorystatus_freezer_stats; | |
179 | ||
180 | #endif /* CONFIG_FREEZE */ | |
181 | ||
182 | #endif /* XNU_KERNEL_PRIVATE */ | |
183 | ||
184 | #ifdef PRIVATE | |
185 | /* Lists all the processes that are currently in the freezer. */ | |
186 | #define FREEZER_CONTROL_GET_PROCS (2) | |
187 | ||
188 | #define FREEZER_CONTROL_GET_PROCS_MAX_COUNT (FREEZE_PROCESSES_MAX * 2) | |
189 | ||
190 | typedef struct _global_frozen_procs { | |
191 | size_t gfp_num_frozen; | |
192 | struct { | |
193 | pid_t fp_pid; | |
194 | proc_name_t fp_name; | |
195 | } gfp_procs[FREEZER_CONTROL_GET_PROCS_MAX_COUNT]; | |
196 | } global_frozen_procs_t; | |
197 | ||
198 | #endif /* PRIVATE */ | |
199 | ||
200 | #endif /* SYS_MEMORYSTATUS_FREEZE_H */ |