1 // 2 // diag_mem_threshold_test.h 3 // DiagThresholdTest 4 // 5 // Copyright (c) 2022 Apple Inc. All rights reserved. 6 // 7 8 #pragma once 9 10 #include "System/sys/kern_memorystatus.h" 11 #include "mach/mach_init.h" 12 #include "mach/exception_types.h" 13 #include "mach/port.h" 14 #include "mach/mach.h" 15 #include "mach/vm_page_size.h" 16 #include "mach/mach_vm.h" 17 #include "mach/mach_port.h" 18 #include "mach/sync_policy.h" 19 #include "mach/task.h" 20 #include "mach/semaphore.h" 21 #include "mach/thread_act.h" 22 #include "sys/dtrace_glue.h" 23 #include "dispatch/dispatch.h" 24 #include <pthread.h> 25 #include <unistd.h> 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <unistd.h> 29 #include <darwintest.h> 30 31 32 #define MAX_MESSAGE 256 33 #define LOW_JETSAM_LIMIT (10*1024*1024) 34 #define WORKING_LIMIT (25*1024*1024) 35 #define COMMAND_LINE_MAX (128) 36 #define ABOVE_JETSAM_LIMIT (12*1024*1024) 37 #define HIGH_JETSAM_LIMIT (WORKING_LIMIT+(1*(1024*1024))) 38 #define TEST_LIMIT (WORKING_LIMIT+(2*(1024*1024))) 39 #define NUM_MASKS 256 40 41 /** 42 * Data types 43 */ 44 struct test_case; 45 typedef void (*test_code_fn)(struct test_case *, void *); /** Callback for the test execution code */ 46 typedef void (*eval_code_fn)(struct test_case *, void *); /** Callback for the test evaluation code */ 47 typedef struct test_case { 48 char short_name[MAX_MESSAGE]; /** Test name */ 49 char test_name[MAX_MESSAGE]; /** Test completion message */ 50 char completion_message[MAX_MESSAGE]; /** Test completion message */ 51 bool did_pass; /** When true, the test did pass */ 52 bool result_already_present; /** When true, the test itself had a veredict, do not update */ 53 bool exception_not_expected; /** When true, the test should not have an exception */ 54 test_code_fn test_code; /** Code to perform the test */ 55 bool exceptions_handled_in_test; /** Should the controller wait for exceptions */ 56 uint64_t required_minimum_hw_ram_size; /** When present (not zero) indicates how much memory must have the HW device to run this test*/ 57 } test_case_t; 58 59 typedef struct information_for_thread { 60 test_case_t *test; 61 semaphore_t exception_semaphore; 62 dispatch_semaphore_t exception_thread_start_sema; /** Semaphore used to sync the main thread to the exception thread*/ 63 dispatch_semaphore_t executor_thread_start_sema; /** Semaphore used to sync the main thread to the executor thread*/ 64 dispatch_semaphore_t executor_thread_end_sema; /** Semaphore used to signal the end of the executor thread*/ 65 dispatch_semaphore_t executor_ready_for_exceptions; /** A holding point from the test execution before waiting for the exception */ 66 pthread_t exception_handler_thread_id; /** Posix thread used to receive exception information */ 67 pthread_t executor_handler_thread_id; /** Posix thread used to execute the test */ 68 exception_mask_t old_mask[NUM_MASKS]; /** Save restore information about the task exeption handler */ 69 mach_msg_type_number_t size_mask; /** Same */ 70 exception_handler_t old_handlers[NUM_MASKS]; /** Same */ 71 exception_behavior_t old_behaviors[NUM_MASKS]; /** Same */ 72 thread_state_flavor_t old_flavors[NUM_MASKS]; /** Same */ 73 exception_mask_t masks_original[NUM_MASKS]; /** Same */ 74 bool exception_seen; /** Did the exception appear? */ 75 } test_context_t; 76 77 /** 78 * Function prototypes (see documentation at implementation) 79 */ 80 void diag_mem_threshold_set_setup(test_case_t *test); 81 void diag_mem_threshold_set_shutdown(void); 82 83 void * exception_thread(void *); 84 bool set_memory_diagnostics_threshold_limits(uint64_t limit, bool assert_on_error); 85 void diag_mem_threshold_waste_memory(uint64_t ammount); 86 void diag_mem_threshold_log_test(const char *fmt, ...); 87 mach_port_t diag_mem_threshold_get_exception_port(void); 88 exception_mask_t diag_mem_threshold_get_exceptions_mask(void); 89 bool diag_mem_threshold_wait_for_exception(test_context_t *param); 90 kern_return_t mach_exception_raise(mach_port_t exception_port, mach_port_t thread, mach_port_t task, exception_type_t exception, mach_exception_data_t code, mach_msg_type_number_t codeCnt); 91 kern_return_t catch_mach_exception_raise(mach_port_t exception_port, mach_port_t thread, mach_port_t task, exception_type_t exception, exception_data_t code, mach_msg_type_number_t code_count); 92 kern_return_t catch_mach_exception_raise_state(mach_port_t port, exception_type_t exception, const exception_data_t code, mach_msg_type_number_t codeCnt, int *flavor, const thread_state_t old_state, mach_msg_type_number_t old_stateCnt, thread_state_t new_state, mach_msg_type_number_t *new_stateCnt); 93 94 kern_return_t catch_mach_exception_raise_state_identity(mach_port_t exception_port, mach_port_t thread, mach_port_t task, exception_type_t exception, mach_exception_data_t code, mach_msg_type_number_t codeCnt, int *flavor, thread_state_t old_state, mach_msg_type_number_t old_stateCnt, thread_state_t new_state, mach_msg_type_number_t *new_stateCnt); 95 96 kern_return_t catch_mach_exception_raise_state_identity( 97 __unused mach_port_t exception_port, 98 __unused mach_port_t thread, 99 __unused mach_port_t task, 100 __unused exception_type_t exception, 101 __unused mach_exception_data_t code, 102 __unused mach_msg_type_number_t codeCnt, 103 __unused int *flavor, 104 __unused thread_state_t old_state, 105 __unused mach_msg_type_number_t old_stateCnt, 106 __unused thread_state_t new_state, 107 __unused mach_msg_type_number_t *new_stateCnt); 108 109 void diag_mem_set_jetsam_watermark(uint ammount); 110 void diag_mem_set_jetsam_limit(uint ammount); 111 112 113 114 boolean_t mach_exc_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); 115 116 /** Test definitions */ 117