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 #include <uuid/uuid.h> 39 40 typedef struct memorystatus_freeze_entry { 41 int32_t pid; 42 uint32_t flags; 43 uint32_t pages; 44 } memorystatus_freeze_entry_t; 45 46 #ifdef PRIVATE 47 #define FREEZE_PROCESSES_MAX_DEFAULT 20 48 #define FREEZE_PROCESSES_MAX_SWAP_ENABLED_DEFAULT 36 49 #endif /* PRIVATE */ 50 51 #ifdef XNU_KERNEL_PRIVATE 52 53 extern unsigned long freeze_threshold_percentage; 54 extern unsigned int memorystatus_frozen_count; /* # of processes that are currently frozen. */ 55 extern unsigned int memorystatus_frozen_count_webcontent; /* # of webcontent processes that are currently frozen. */ 56 extern unsigned int memorystatus_frozen_count_xpc_service; /* # of xpc services that are currently frozen. */ 57 extern unsigned int memorystatus_frozen_processes_max; 58 extern unsigned int memorystatus_frozen_shared_mb; 59 extern unsigned int memorystatus_frozen_shared_mb_max; 60 extern unsigned int memorystatus_freeze_shared_mb_per_process_max; /* Max. MB allowed per process to be freezer-eligible. */ 61 extern unsigned int memorystatus_freeze_private_shared_pages_ratio; /* Ratio of private:shared pages for a process to be freezer-eligible. */ 62 extern unsigned int memorystatus_thaw_count; /* # of processes that have been thawed in the current interval. */ 63 extern unsigned int memorystatus_refreeze_eligible_count; /* # of processes currently thawed i.e. have state on disk & in-memory */ 64 extern unsigned int memorystatus_freeze_max_candidate_band; 65 extern uint32_t memorystatus_freeze_current_interval; /* Monotonically increasing interval id. */ 66 67 void memorystatus_freeze_init(void); 68 extern int memorystatus_freeze_process_sync(proc_t p); 69 70 #ifdef CONFIG_FREEZE 71 extern int memorystatus_entitled_max_task_footprint_mb; 72 73 #if XNU_TARGET_OS_WATCH 74 #define FREEZE_PAGES_MIN_DEFAULT ( 2 * 1024 * 1024 / PAGE_SIZE) 75 #else 76 #define FREEZE_PAGES_MIN_DEFAULT ( 8 * 1024 * 1024 / PAGE_SIZE) 77 #endif 78 #define FREEZE_PAGES_MAX_DEFAULT (max_task_footprint_mb == 0 ? INT_MAX : (max_task_footprint_mb << (20 - PAGE_SHIFT))) 79 #define FREEZE_PAGES_MAX_SWAP_ENABLED_DEFAULT \ 80 (memorystatus_entitled_max_task_footprint_mb == 0 ? INT_MAX : (memorystatus_entitled_max_task_footprint_mb << (20 - PAGE_SHIFT))) 81 82 #if XNU_TARGET_OS_WATCH 83 #define FREEZE_SUSPENDED_THRESHOLD_DEFAULT 0 84 #else 85 #define FREEZE_SUSPENDED_THRESHOLD_DEFAULT 4 86 #endif 87 88 #define FREEZE_DAILY_MB_MAX_DEFAULT 2048 89 #define FREEZE_DEGRADATION_BUDGET_THRESHOLD 25 //degraded perf. when the daily budget left falls below this threshold percentage 90 91 #define MAX_FROZEN_SHARED_MB_PERCENT 10 92 #define MAX_FROZEN_PROCESS_DEMOTIONS_DEFAULT 2 93 #define MAX_FROZEN_PROCESS_DEMOTIONS_SWAP_ENABLED_DEFAULT 4 94 #define MIN_THAW_DEMOTION_THRESHOLD_DEFAULT 5 95 96 #if XNU_TARGET_OS_WATCH 97 #define MIN_THAW_REFREEZE_THRESHOLD_DEFAULT 0 98 #else 99 #define MIN_THAW_REFREEZE_THRESHOLD_DEFAULT 3 100 #endif 101 102 #if XNU_TARGET_OS_WATCH 103 #define FREEZE_MAX_CANDIDATE_BAND JETSAM_PRIORITY_ELEVATED_INACTIVE 104 #else 105 #define FREEZE_MAX_CANDIDATE_BAND JETSAM_PRIORITY_AGING_BAND2 106 #endif 107 108 #if XNU_TARGET_OS_WATCH 109 #define FREEZE_USE_ELEVATED_INACTIVE_BAND 0 110 #else 111 #define FREEZE_USE_ELEVATED_INACTIVE_BAND 1 112 #endif 113 114 typedef struct throttle_interval_t { 115 uint32_t mins; 116 uint32_t burst_multiple; 117 uint32_t pageouts; 118 uint32_t max_pageouts; 119 mach_timespec_t ts; 120 } throttle_interval_t; 121 122 extern boolean_t memorystatus_freeze_enabled; 123 extern int memorystatus_freeze_wakeup; 124 125 /* Thresholds */ 126 extern unsigned int memorystatus_freeze_threshold; 127 extern unsigned int memorystatus_freeze_pages_min; 128 extern unsigned int memorystatus_freeze_pages_max; 129 extern unsigned int memorystatus_freeze_suspended_threshold; 130 extern unsigned int memorystatus_freeze_daily_mb_max; 131 extern uint64_t memorystatus_freeze_budget_pages_remaining; //remaining # of pages that can be frozen to disk 132 extern boolean_t memorystatus_freeze_degradation; //protected by the freezer mutex. Signals we are in a degraded freeze mode. 133 134 extern unsigned int memorystatus_max_frozen_demotions_daily; 135 extern unsigned int memorystatus_thaw_count_demotion_threshold; 136 extern unsigned int memorystatus_min_thaw_refreeze_threshold; 137 138 #if DEVELOPMENT || DEBUG 139 #define FREEZER_CONTROL_GET_STATUS (1) 140 #endif /* DEVELOPMENT || DEBUG */ 141 142 bool memorystatus_freeze_thread_should_run(void); 143 int memorystatus_set_process_is_freezable(pid_t pid, boolean_t is_freezable); 144 int memorystatus_get_process_is_freezable(pid_t pid, int *is_freezable); 145 int memorystatus_freezer_control(int32_t flags, user_addr_t buffer, size_t buffer_size, int32_t *retval); 146 void memorystatus_freeze_init_proc(proc_t p); 147 errno_t memorystatus_get_process_is_frozen(pid_t pid, int *is_freezable); 148 errno_t memorystatus_cmd_grp_set_freeze_list(user_addr_t buffer, size_t buffer_size); 149 errno_t memorystatus_cmd_grp_set_demote_list(user_addr_t buffer, size_t buffer_size); 150 151 /* Freezer counters collected for telemtry */ 152 struct memorystatus_freezer_stats_t { 153 /* 154 * # of processes that we've considered freezing. 155 * Used to normalize the error reasons below. 156 */ 157 uint64_t mfs_process_considered_count; 158 159 /* 160 * The following counters track how many times we've failed to freeze 161 * a process because of a specific FREEZER_ERROR. 162 */ 163 /* EXCESS_SHARED_MEMORY */ 164 uint64_t mfs_error_excess_shared_memory_count; 165 /* LOW_PRIVATE_SHARED_RATIO */ 166 uint64_t mfs_error_low_private_shared_ratio_count; 167 /* NO_COMPRESSOR_SPACE */ 168 uint64_t mfs_error_no_compressor_space_count; 169 /* NO_SWAP_SPACE */ 170 uint64_t mfs_error_no_swap_space_count; 171 /* pages < memorystatus_freeze_pages_min */ 172 uint64_t mfs_error_below_min_pages_count; 173 /* dasd determined it was unlikely to be relaunched. */ 174 uint64_t mfs_error_low_probability_of_use_count; 175 /* not in idle bands */ 176 uint64_t mfs_error_elevated_count; 177 /* transient reasons (like inability to acquire a lock). */ 178 uint64_t mfs_error_other_count; 179 180 /* 181 * # of times that we saw memorystatus_available_pages <= memorystatus_freeze_threshold. 182 * Used to normalize skipped_full_count and shared_mb_high_count. 183 */ 184 uint64_t mfs_below_threshold_count; 185 186 /* Skipped running the freezer because we were out of slots */ 187 uint64_t mfs_skipped_full_count; 188 189 /* Skipped running the freezer because we were over the shared mb limit*/ 190 uint64_t mfs_skipped_shared_mb_high_count; 191 192 /* 193 * How many pages have not been sent to swap because they were in a shared object? 194 * This is being used to gather telemtry so we can understand the impact we'd have 195 * on our NAND budget if we did swap out these pages. 196 */ 197 uint64_t mfs_shared_pages_skipped; 198 199 /* 200 * A running sum of the total number of bytes sent to NAND during 201 * refreeze operations since boot. 202 */ 203 uint64_t mfs_bytes_refrozen; 204 /* The number of refreeze operations since boot */ 205 uint64_t mfs_refreeze_count; 206 207 /* The number of proceses which have been frozen at least once in the current interval. */ 208 uint64_t mfs_processes_frozen; 209 /* The number of processes which have been thawed at least once in the current interval. */ 210 uint64_t mfs_processes_thawed; 211 212 /* 213 * Telemetry shows that the majority of freezer usage is attributed to webcontent 214 * so we track some specific webcontent telemetry here to get more visibility. 215 */ 216 217 /* The number of webcontent processes which have been frozen at least once in the current interval. */ 218 uint64_t mfs_processes_frozen_webcontent; 219 /* The number of webcontent processes which have been thawed at least once in the current interval. */ 220 uint64_t mfs_processes_thawed_webcontent; 221 222 /* The number of xpc service processes which have been frozen at least once in the current interval. */ 223 uint64_t mfs_processes_frozen_xpc_service; 224 225 /* The number of fg thaws in the current interval. */ 226 uint64_t mfs_processes_thawed_fg; 227 /* The number of fg xpc service thaws in the current interval. */ 228 uint64_t mfs_processes_thawed_fg_xpc_service; 229 230 /* 231 * Counts the number of incorrect pids provided via 232 * MEMORYSTATUS_FLAGS_GRP_SET_FREEZE_PRIORITY in the current interval. 233 * A high value means dasd should be updating the list more 234 * frequently. 235 */ 236 uint64_t mfs_freeze_pid_mismatches; 237 /* 238 * Counts the number of incorrect pids provided via 239 * MEMORYSTATUS_FLAGS_GRP_SET_DEMOTE_PRIORITY in the current interval. 240 * A high value means dasd should be updating the list more 241 * frequently. 242 */ 243 uint64_t mfs_demote_pid_mismatches; 244 245 /* 246 * When we run out of budget, this records how much time is left in the current 247 * interval. 0 means we have not run out of budget. 248 */ 249 uint64_t mfs_budget_exhaustion_duration_remaining; 250 251 /* The number of visible resumes in this interval. Mostly used to filter out idle devices. */ 252 uint64_t mfs_processes_fg_resumed; 253 }; 254 extern struct memorystatus_freezer_stats_t memorystatus_freezer_stats; 255 256 /* 257 * Called by kern_resource when a process gets a UI priority 258 */ 259 void memorystatus_freezer_mark_ui_transition(proc_t p); 260 261 #endif /* CONFIG_FREEZE */ 262 263 #endif /* XNU_KERNEL_PRIVATE */ 264 265 #ifdef PRIVATE 266 /* Lists all the processes that are currently in the freezer. */ 267 #define FREEZER_CONTROL_GET_PROCS (2) 268 269 #define FREEZER_CONTROL_GET_PROCS_MAX_COUNT (FREEZE_PROCESSES_MAX_DEFAULT * 2) 270 271 typedef struct _global_frozen_procs { 272 uint64_t gfp_num_frozen; 273 274 struct { 275 pid_t fp_pid; 276 proc_name_t fp_name; 277 } gfp_procs[FREEZER_CONTROL_GET_PROCS_MAX_COUNT]; 278 } global_frozen_procs_t; 279 280 /* Set the dasd trial identifiers */ 281 #define FREEZER_CONTROL_SET_DASD_TRIAL_IDENTIFIERS (3) 282 283 typedef struct _memorystatus_freezer_trial_identifiers_v1 { 284 int version; /* Must be set to 1 */ 285 uuid_string_t treatment_id; 286 uuid_string_t experiment_id; 287 int deployment_id; 288 } memorystatus_freezer_trial_identifiers_v1; 289 290 /* 291 * Destructively reset the freezer state in order to perform a policy change. 292 * Note that this could result in multiple suspended apps getting killed, 293 * so it should only be used when the device is idle. 294 */ 295 #define FREEZER_CONTROL_RESET_STATE (4) 296 297 #endif /* PRIVATE */ 298 299 #endif /* SYS_MEMORYSTATUS_FREEZE_H */ 300