1 #include <sys/kern_memorystatus.h> 2 #include <sys/sysctl.h> 3 #include <sys/types.h> 4 #include <unistd.h> 5 6 #include <darwintest.h> 7 8 #define MAX_TASK_MEM "kern.max_task_pmem" 9 10 T_GLOBAL_META( 11 T_META_NAMESPACE("xnu.vm"), 12 T_META_RADAR_COMPONENT_NAME("xnu"), 13 T_META_RADAR_COMPONENT_VERSION("VM"), 14 T_META_BOOTARGS_SET("memstat_no_task_limit_increase=1"), 15 T_META_ENABLED(!TARGET_OS_OSX)); 16 17 T_DECL(memorystatus_convert_limit_bytes, "memorystatus_convert_limit_bytes default limit", T_META_TAG_VM_PREFERRED) 18 { 19 int ret; 20 int32_t max_task_pmem = 0; 21 size_t size_max_task_pmem = sizeof(max_task_pmem); 22 23 ret = sysctlbyname(MAX_TASK_MEM, &max_task_pmem, &size_max_task_pmem, NULL, 0); 24 T_ASSERT_POSIX_SUCCESS(ret, "call sysctlbyname to get max task physical memory."); 25 26 if (max_task_pmem == 0) { 27 T_SKIP("Device does not have a default task memory limit."); 28 } 29 30 ret = memorystatus_control(MEMORYSTATUS_CMD_CONVERT_MEMLIMIT_MB, getpid(), (int32_t) -1, NULL, 0); 31 T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "memorystatus_control"); 32 T_QUIET; T_ASSERT_EQ(ret, max_task_pmem, "default limit is converted correctly"); 33 } 34 35 T_DECL(memorystatus_set_task_limit_always_fatal, 36 "Verify that a converted task limit is always fatal") 37 { 38 int ret; 39 int32_t max_task_pmem = 0; 40 size_t size_max_task_pmem = sizeof(max_task_pmem); 41 pid_t pid = getpid(); 42 43 ret = sysctlbyname(MAX_TASK_MEM, &max_task_pmem, &size_max_task_pmem, NULL, 0); 44 T_ASSERT_POSIX_SUCCESS(ret, "call sysctlbyname to get max task physical memory."); 45 46 if (max_task_pmem == 0) { 47 T_SKIP("Device does not have a default task memory limit."); 48 } 49 50 /* Request non-fatal memlimits */ 51 memorystatus_memlimit_properties2_t mmprops = { 52 .v1 = { 53 .memlimit_active = max_task_pmem, 54 .memlimit_inactive = max_task_pmem, 55 .memlimit_active_attr = 0, 56 .memlimit_inactive_attr = 0, 57 }, 58 }; 59 ret = memorystatus_control(MEMORYSTATUS_CMD_SET_MEMLIMIT_PROPERTIES, pid, 0, &mmprops.v1, sizeof(mmprops.v1)); 60 T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "memorystatus_control"); 61 62 ret = memorystatus_control(MEMORYSTATUS_CMD_GET_MEMLIMIT_PROPERTIES, pid, 0, &mmprops, sizeof(mmprops)); 63 T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "memorystatus_control"); 64 65 T_EXPECT_BITS_SET(mmprops.v1.memlimit_active_attr, MEMORYSTATUS_MEMLIMIT_ATTR_FATAL, 66 "Active limit (task limit) should be fatal"); 67 T_EXPECT_BITS_SET(mmprops.v1.memlimit_inactive_attr, MEMORYSTATUS_MEMLIMIT_ATTR_FATAL, 68 "Inactive limit (task limit) should be fatal"); 69 70 /* Request non-fatal memlimits */ 71 mmprops.v1.memlimit_active = -1; 72 mmprops.v1.memlimit_inactive = -1; 73 mmprops.v1.memlimit_active_attr = 0; 74 mmprops.v1.memlimit_inactive_attr = 0; 75 76 ret = memorystatus_control(MEMORYSTATUS_CMD_SET_MEMLIMIT_PROPERTIES, pid, 0, &mmprops.v1, sizeof(mmprops.v1)); 77 T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "memorystatus_control"); 78 79 ret = memorystatus_control(MEMORYSTATUS_CMD_GET_MEMLIMIT_PROPERTIES, pid, 0, &mmprops, sizeof(mmprops)); 80 T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "memorystatus_control"); 81 82 T_EXPECT_BITS_SET(mmprops.v1.memlimit_active_attr, MEMORYSTATUS_MEMLIMIT_ATTR_FATAL, 83 "Active limit (-1) should be fatal"); 84 T_EXPECT_BITS_SET(mmprops.v1.memlimit_inactive_attr, MEMORYSTATUS_MEMLIMIT_ATTR_FATAL, 85 "Inactive (-1) limit should be fatal"); 86 87 /* Request non-fatal memlimits */ 88 mmprops.v1.memlimit_active = 0; 89 mmprops.v1.memlimit_inactive = 0; 90 mmprops.v1.memlimit_active_attr = 0; 91 mmprops.v1.memlimit_inactive_attr = 0; 92 93 ret = memorystatus_control(MEMORYSTATUS_CMD_SET_MEMLIMIT_PROPERTIES, pid, 0, &mmprops.v1, sizeof(mmprops.v1)); 94 T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "memorystatus_control"); 95 96 ret = memorystatus_control(MEMORYSTATUS_CMD_GET_MEMLIMIT_PROPERTIES, pid, 0, &mmprops, sizeof(mmprops)); 97 T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "memorystatus_control"); 98 99 T_EXPECT_BITS_SET(mmprops.v1.memlimit_active_attr, MEMORYSTATUS_MEMLIMIT_ATTR_FATAL, 100 "Active limit (0) should be fatal"); 101 T_EXPECT_BITS_SET(mmprops.v1.memlimit_inactive_attr, MEMORYSTATUS_MEMLIMIT_ATTR_FATAL, 102 "Inactive (0) limit should be fatal"); 103 } 104 105 T_DECL(memorystatus_memlimit_gt_task_limit, 106 "Verify that memory limits can exceed the task limit") 107 { 108 int ret; 109 int32_t max_task_pmem = 0; 110 size_t size_max_task_pmem = sizeof(max_task_pmem); 111 pid_t pid = getpid(); 112 113 ret = sysctlbyname(MAX_TASK_MEM, &max_task_pmem, &size_max_task_pmem, NULL, 0); 114 T_ASSERT_POSIX_SUCCESS(ret, "call sysctlbyname to get max task physical memory."); 115 116 if (max_task_pmem == 0) { 117 T_SKIP("Device does not have a default task memory limit."); 118 } 119 120 /* Request non-fatal memlimits */ 121 int32_t expected_memlimit = max_task_pmem + 100; 122 memorystatus_memlimit_properties2_t mmprops = { 123 .v1 = { 124 .memlimit_active = expected_memlimit, 125 .memlimit_inactive = expected_memlimit, 126 .memlimit_active_attr = 0, 127 .memlimit_inactive_attr = 0, 128 }, 129 }; 130 ret = memorystatus_control(MEMORYSTATUS_CMD_SET_MEMLIMIT_PROPERTIES, pid, 0, &mmprops.v1, sizeof(mmprops.v1)); 131 T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "memorystatus_control"); 132 133 ret = memorystatus_control(MEMORYSTATUS_CMD_GET_MEMLIMIT_PROPERTIES, pid, 0, &mmprops, sizeof(mmprops)); 134 T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "memorystatus_control"); 135 136 T_EXPECT_EQ(mmprops.v1.memlimit_active, expected_memlimit, "Active limit can exceed task limit"); 137 T_EXPECT_EQ(mmprops.v1.memlimit_inactive, expected_memlimit, "Inactive limit can exceed task limit"); 138 T_EXPECT_BITS_NOTSET(mmprops.v1.memlimit_active_attr, MEMORYSTATUS_MEMLIMIT_ATTR_FATAL, 139 "Active limit should be non-fatal"); 140 T_EXPECT_BITS_NOTSET(mmprops.v1.memlimit_inactive_attr, MEMORYSTATUS_MEMLIMIT_ATTR_FATAL, 141 "Inactive limit should be non-fatal"); 142 } 143