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