1f08c3bdfSopenharmony_ci#define TST_NO_DEFAULT_MAIN 2f08c3bdfSopenharmony_ci 3f08c3bdfSopenharmony_ci#include "config.h" 4f08c3bdfSopenharmony_ci#include <sys/types.h> 5f08c3bdfSopenharmony_ci#include <sys/mman.h> 6f08c3bdfSopenharmony_ci#include <sys/mount.h> 7f08c3bdfSopenharmony_ci#include <sys/stat.h> 8f08c3bdfSopenharmony_ci#include <sys/wait.h> 9f08c3bdfSopenharmony_ci#include <sys/param.h> 10f08c3bdfSopenharmony_ci#include <errno.h> 11f08c3bdfSopenharmony_ci#include <fcntl.h> 12f08c3bdfSopenharmony_ci#if HAVE_NUMA_H 13f08c3bdfSopenharmony_ci#include <numa.h> 14f08c3bdfSopenharmony_ci#endif 15f08c3bdfSopenharmony_ci#if HAVE_NUMAIF_H 16f08c3bdfSopenharmony_ci#include <numaif.h> 17f08c3bdfSopenharmony_ci#endif 18f08c3bdfSopenharmony_ci#include <pthread.h> 19f08c3bdfSopenharmony_ci#include <stdarg.h> 20f08c3bdfSopenharmony_ci#include <stdio.h> 21f08c3bdfSopenharmony_ci#include <string.h> 22f08c3bdfSopenharmony_ci#include <stdlib.h> 23f08c3bdfSopenharmony_ci#include <unistd.h> 24f08c3bdfSopenharmony_ci 25f08c3bdfSopenharmony_ci#include "mem.h" 26f08c3bdfSopenharmony_ci#include "numa_helper.h" 27f08c3bdfSopenharmony_ci 28f08c3bdfSopenharmony_ci/* OOM */ 29f08c3bdfSopenharmony_ci 30f08c3bdfSopenharmony_cistatic int alloc_mem(long int length, int testcase) 31f08c3bdfSopenharmony_ci{ 32f08c3bdfSopenharmony_ci char *s; 33f08c3bdfSopenharmony_ci long i, pagesz = getpagesize(); 34f08c3bdfSopenharmony_ci int loop = 10; 35f08c3bdfSopenharmony_ci 36f08c3bdfSopenharmony_ci tst_res(TINFO, "thread (%lx), allocating %ld bytes.", 37f08c3bdfSopenharmony_ci (unsigned long) pthread_self(), length); 38f08c3bdfSopenharmony_ci 39f08c3bdfSopenharmony_ci s = mmap(NULL, length, PROT_READ | PROT_WRITE, 40f08c3bdfSopenharmony_ci MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 41f08c3bdfSopenharmony_ci if (s == MAP_FAILED) 42f08c3bdfSopenharmony_ci return errno; 43f08c3bdfSopenharmony_ci 44f08c3bdfSopenharmony_ci if (testcase == MLOCK) { 45f08c3bdfSopenharmony_ci while (mlock(s, length) == -1 && loop > 0) { 46f08c3bdfSopenharmony_ci if (EAGAIN != errno) 47f08c3bdfSopenharmony_ci return errno; 48f08c3bdfSopenharmony_ci usleep(300000); 49f08c3bdfSopenharmony_ci loop--; 50f08c3bdfSopenharmony_ci } 51f08c3bdfSopenharmony_ci } 52f08c3bdfSopenharmony_ci 53f08c3bdfSopenharmony_ci#ifdef HAVE_DECL_MADV_MERGEABLE 54f08c3bdfSopenharmony_ci if (testcase == KSM && madvise(s, length, MADV_MERGEABLE) == -1) 55f08c3bdfSopenharmony_ci return errno; 56f08c3bdfSopenharmony_ci#endif 57f08c3bdfSopenharmony_ci for (i = 0; i < length; i += pagesz) 58f08c3bdfSopenharmony_ci s[i] = '\a'; 59f08c3bdfSopenharmony_ci 60f08c3bdfSopenharmony_ci return 0; 61f08c3bdfSopenharmony_ci} 62f08c3bdfSopenharmony_ci 63f08c3bdfSopenharmony_cistatic void *child_alloc_thread(void *args) 64f08c3bdfSopenharmony_ci{ 65f08c3bdfSopenharmony_ci int ret = 0; 66f08c3bdfSopenharmony_ci 67f08c3bdfSopenharmony_ci /* keep allocating until there's an error */ 68f08c3bdfSopenharmony_ci while (!ret) 69f08c3bdfSopenharmony_ci ret = alloc_mem(LENGTH, (long)args); 70f08c3bdfSopenharmony_ci exit(ret); 71f08c3bdfSopenharmony_ci} 72f08c3bdfSopenharmony_ci 73f08c3bdfSopenharmony_cistatic void child_alloc(int testcase, int lite, int threads) 74f08c3bdfSopenharmony_ci{ 75f08c3bdfSopenharmony_ci int i; 76f08c3bdfSopenharmony_ci pthread_t *th; 77f08c3bdfSopenharmony_ci 78f08c3bdfSopenharmony_ci if (lite) { 79f08c3bdfSopenharmony_ci int ret = alloc_mem(TESTMEM * 2 + MB, testcase); 80f08c3bdfSopenharmony_ci exit(ret); 81f08c3bdfSopenharmony_ci } 82f08c3bdfSopenharmony_ci 83f08c3bdfSopenharmony_ci th = malloc(sizeof(pthread_t) * threads); 84f08c3bdfSopenharmony_ci if (!th) { 85f08c3bdfSopenharmony_ci tst_res(TINFO | TERRNO, "malloc"); 86f08c3bdfSopenharmony_ci goto out; 87f08c3bdfSopenharmony_ci } 88f08c3bdfSopenharmony_ci 89f08c3bdfSopenharmony_ci for (i = 0; i < threads; i++) { 90f08c3bdfSopenharmony_ci TEST(pthread_create(&th[i], NULL, child_alloc_thread, 91f08c3bdfSopenharmony_ci (void *)((long)testcase))); 92f08c3bdfSopenharmony_ci if (TST_RET) { 93f08c3bdfSopenharmony_ci tst_res(TINFO | TRERRNO, "pthread_create"); 94f08c3bdfSopenharmony_ci /* 95f08c3bdfSopenharmony_ci * Keep going if thread other than first fails to 96f08c3bdfSopenharmony_ci * spawn due to lack of resources. 97f08c3bdfSopenharmony_ci */ 98f08c3bdfSopenharmony_ci if (i == 0 || TST_RET != EAGAIN) 99f08c3bdfSopenharmony_ci goto out; 100f08c3bdfSopenharmony_ci } 101f08c3bdfSopenharmony_ci } 102f08c3bdfSopenharmony_ci 103f08c3bdfSopenharmony_ci /* wait for one of threads to exit whole process */ 104f08c3bdfSopenharmony_ci while (1) 105f08c3bdfSopenharmony_ci sleep(1); 106f08c3bdfSopenharmony_ciout: 107f08c3bdfSopenharmony_ci exit(1); 108f08c3bdfSopenharmony_ci} 109f08c3bdfSopenharmony_ci 110f08c3bdfSopenharmony_ci/* 111f08c3bdfSopenharmony_ci * oom - allocates memory according to specified testcase and checks 112f08c3bdfSopenharmony_ci * desired outcome (e.g. child killed, operation failed with ENOMEM) 113f08c3bdfSopenharmony_ci * @testcase: selects how child allocates memory 114f08c3bdfSopenharmony_ci * valid choices are: NORMAL, MLOCK and KSM 115f08c3bdfSopenharmony_ci * @lite: if non-zero, child makes only single TESTMEM+MB allocation 116f08c3bdfSopenharmony_ci * if zero, child keeps allocating memory until it gets killed 117f08c3bdfSopenharmony_ci * or some operation fails 118f08c3bdfSopenharmony_ci * @retcode: expected return code of child process 119f08c3bdfSopenharmony_ci * if matches child ret code, this function reports PASS, 120f08c3bdfSopenharmony_ci * otherwise it reports FAIL 121f08c3bdfSopenharmony_ci * @allow_sigkill: if zero and child is killed, this function reports FAIL 122f08c3bdfSopenharmony_ci * if non-zero, then if child is killed by SIGKILL 123f08c3bdfSopenharmony_ci * it is considered as PASS 124f08c3bdfSopenharmony_ci */ 125f08c3bdfSopenharmony_civoid oom(int testcase, int lite, int retcode, int allow_sigkill) 126f08c3bdfSopenharmony_ci{ 127f08c3bdfSopenharmony_ci pid_t pid; 128f08c3bdfSopenharmony_ci int status, threads; 129f08c3bdfSopenharmony_ci 130f08c3bdfSopenharmony_ci tst_enable_oom_protection(0); 131f08c3bdfSopenharmony_ci 132f08c3bdfSopenharmony_ci switch (pid = SAFE_FORK()) { 133f08c3bdfSopenharmony_ci case 0: 134f08c3bdfSopenharmony_ci tst_disable_oom_protection(0); 135f08c3bdfSopenharmony_ci threads = MAX(1, tst_ncpus() - 1); 136f08c3bdfSopenharmony_ci child_alloc(testcase, lite, threads); 137f08c3bdfSopenharmony_ci default: 138f08c3bdfSopenharmony_ci break; 139f08c3bdfSopenharmony_ci } 140f08c3bdfSopenharmony_ci 141f08c3bdfSopenharmony_ci tst_res(TINFO, "expected victim is %d.", pid); 142f08c3bdfSopenharmony_ci SAFE_WAITPID(-1, &status, 0); 143f08c3bdfSopenharmony_ci 144f08c3bdfSopenharmony_ci if (WIFSIGNALED(status)) { 145f08c3bdfSopenharmony_ci if (allow_sigkill && WTERMSIG(status) == SIGKILL) { 146f08c3bdfSopenharmony_ci tst_res(TPASS, "victim signalled: (%d) %s", 147f08c3bdfSopenharmony_ci SIGKILL, 148f08c3bdfSopenharmony_ci tst_strsig(SIGKILL)); 149f08c3bdfSopenharmony_ci } else { 150f08c3bdfSopenharmony_ci tst_res(TFAIL, "victim signalled: (%d) %s", 151f08c3bdfSopenharmony_ci WTERMSIG(status), 152f08c3bdfSopenharmony_ci tst_strsig(WTERMSIG(status))); 153f08c3bdfSopenharmony_ci } 154f08c3bdfSopenharmony_ci } else if (WIFEXITED(status)) { 155f08c3bdfSopenharmony_ci if (WEXITSTATUS(status) == retcode) { 156f08c3bdfSopenharmony_ci tst_res(TPASS, "victim retcode: (%d) %s", 157f08c3bdfSopenharmony_ci retcode, strerror(retcode)); 158f08c3bdfSopenharmony_ci } else { 159f08c3bdfSopenharmony_ci tst_res(TFAIL, "victim unexpectedly ended with " 160f08c3bdfSopenharmony_ci "retcode: %d, expected: %d", 161f08c3bdfSopenharmony_ci WEXITSTATUS(status), retcode); 162f08c3bdfSopenharmony_ci } 163f08c3bdfSopenharmony_ci } else { 164f08c3bdfSopenharmony_ci tst_res(TFAIL, "victim unexpectedly ended"); 165f08c3bdfSopenharmony_ci } 166f08c3bdfSopenharmony_ci} 167f08c3bdfSopenharmony_ci 168f08c3bdfSopenharmony_ci#ifdef HAVE_NUMA_V2 169f08c3bdfSopenharmony_cistatic void set_global_mempolicy(int mempolicy) 170f08c3bdfSopenharmony_ci{ 171f08c3bdfSopenharmony_ci unsigned long nmask[MAXNODES / BITS_PER_LONG] = { 0 }; 172f08c3bdfSopenharmony_ci int num_nodes, *nodes; 173f08c3bdfSopenharmony_ci int ret; 174f08c3bdfSopenharmony_ci 175f08c3bdfSopenharmony_ci if (mempolicy) { 176f08c3bdfSopenharmony_ci ret = get_allowed_nodes_arr(NH_MEMS|NH_CPUS, &num_nodes, &nodes); 177f08c3bdfSopenharmony_ci if (ret != 0) 178f08c3bdfSopenharmony_ci tst_brk(TBROK|TERRNO, "get_allowed_nodes_arr"); 179f08c3bdfSopenharmony_ci if (num_nodes < 2) { 180f08c3bdfSopenharmony_ci tst_res(TINFO, "mempolicy need NUMA system support"); 181f08c3bdfSopenharmony_ci free(nodes); 182f08c3bdfSopenharmony_ci return; 183f08c3bdfSopenharmony_ci } 184f08c3bdfSopenharmony_ci switch(mempolicy) { 185f08c3bdfSopenharmony_ci case MPOL_BIND: 186f08c3bdfSopenharmony_ci /* bind the second node */ 187f08c3bdfSopenharmony_ci set_node(nmask, nodes[1]); 188f08c3bdfSopenharmony_ci break; 189f08c3bdfSopenharmony_ci case MPOL_INTERLEAVE: 190f08c3bdfSopenharmony_ci case MPOL_PREFERRED: 191f08c3bdfSopenharmony_ci if (num_nodes == 2) { 192f08c3bdfSopenharmony_ci tst_res(TINFO, "The mempolicy need " 193f08c3bdfSopenharmony_ci "more than 2 numa nodes"); 194f08c3bdfSopenharmony_ci free(nodes); 195f08c3bdfSopenharmony_ci return; 196f08c3bdfSopenharmony_ci } else { 197f08c3bdfSopenharmony_ci /* Using the 2nd,3rd node */ 198f08c3bdfSopenharmony_ci set_node(nmask, nodes[1]); 199f08c3bdfSopenharmony_ci set_node(nmask, nodes[2]); 200f08c3bdfSopenharmony_ci } 201f08c3bdfSopenharmony_ci break; 202f08c3bdfSopenharmony_ci default: 203f08c3bdfSopenharmony_ci tst_brk(TBROK|TERRNO, "Bad mempolicy mode"); 204f08c3bdfSopenharmony_ci } 205f08c3bdfSopenharmony_ci if (set_mempolicy(mempolicy, nmask, MAXNODES) == -1) 206f08c3bdfSopenharmony_ci tst_brk(TBROK|TERRNO, "set_mempolicy"); 207f08c3bdfSopenharmony_ci } 208f08c3bdfSopenharmony_ci} 209f08c3bdfSopenharmony_ci#else 210f08c3bdfSopenharmony_cistatic void set_global_mempolicy(int mempolicy LTP_ATTRIBUTE_UNUSED) { } 211f08c3bdfSopenharmony_ci#endif 212f08c3bdfSopenharmony_ci 213f08c3bdfSopenharmony_civoid testoom(int mempolicy, int lite, int retcode, int allow_sigkill) 214f08c3bdfSopenharmony_ci{ 215f08c3bdfSopenharmony_ci int ksm_run_orig; 216f08c3bdfSopenharmony_ci 217f08c3bdfSopenharmony_ci set_global_mempolicy(mempolicy); 218f08c3bdfSopenharmony_ci 219f08c3bdfSopenharmony_ci tst_res(TINFO, "start normal OOM testing."); 220f08c3bdfSopenharmony_ci oom(NORMAL, lite, retcode, allow_sigkill); 221f08c3bdfSopenharmony_ci 222f08c3bdfSopenharmony_ci tst_res(TINFO, "start OOM testing for mlocked pages."); 223f08c3bdfSopenharmony_ci oom(MLOCK, lite, retcode, allow_sigkill); 224f08c3bdfSopenharmony_ci 225f08c3bdfSopenharmony_ci /* 226f08c3bdfSopenharmony_ci * Skip oom(KSM) if lite == 1, since limit_in_bytes may vary from 227f08c3bdfSopenharmony_ci * run to run, which isn't reliable for oom03 cgroup test. 228f08c3bdfSopenharmony_ci */ 229f08c3bdfSopenharmony_ci if (access(PATH_KSM, F_OK) == -1 || lite == 1) { 230f08c3bdfSopenharmony_ci tst_res(TINFO, "KSM is not configed or lite == 1, " 231f08c3bdfSopenharmony_ci "skip OOM test for KSM pags"); 232f08c3bdfSopenharmony_ci } else { 233f08c3bdfSopenharmony_ci tst_res(TINFO, "start OOM testing for KSM pages."); 234f08c3bdfSopenharmony_ci SAFE_FILE_SCANF(PATH_KSM "run", "%d", &ksm_run_orig); 235f08c3bdfSopenharmony_ci SAFE_FILE_PRINTF(PATH_KSM "run", "1"); 236f08c3bdfSopenharmony_ci oom(KSM, lite, retcode, allow_sigkill); 237f08c3bdfSopenharmony_ci SAFE_FILE_PRINTF(PATH_KSM "run", "%d", ksm_run_orig); 238f08c3bdfSopenharmony_ci } 239f08c3bdfSopenharmony_ci} 240f08c3bdfSopenharmony_ci 241f08c3bdfSopenharmony_ci/* KSM */ 242f08c3bdfSopenharmony_ci 243f08c3bdfSopenharmony_cistatic void check(char *path, long int value) 244f08c3bdfSopenharmony_ci{ 245f08c3bdfSopenharmony_ci char fullpath[BUFSIZ]; 246f08c3bdfSopenharmony_ci long actual_val; 247f08c3bdfSopenharmony_ci 248f08c3bdfSopenharmony_ci snprintf(fullpath, BUFSIZ, PATH_KSM "%s", path); 249f08c3bdfSopenharmony_ci SAFE_FILE_SCANF(fullpath, "%ld", &actual_val); 250f08c3bdfSopenharmony_ci 251f08c3bdfSopenharmony_ci if (actual_val != value) 252f08c3bdfSopenharmony_ci tst_res(TFAIL, "%s is not %ld but %ld.", path, value, 253f08c3bdfSopenharmony_ci actual_val); 254f08c3bdfSopenharmony_ci else 255f08c3bdfSopenharmony_ci tst_res(TPASS, "%s is %ld.", path, actual_val); 256f08c3bdfSopenharmony_ci} 257f08c3bdfSopenharmony_ci 258f08c3bdfSopenharmony_cistatic void final_group_check(int run, int pages_shared, int pages_sharing, 259f08c3bdfSopenharmony_ci int pages_volatile, int pages_unshared, 260f08c3bdfSopenharmony_ci int sleep_millisecs, int pages_to_scan) 261f08c3bdfSopenharmony_ci{ 262f08c3bdfSopenharmony_ci int ksm_run_orig; 263f08c3bdfSopenharmony_ci 264f08c3bdfSopenharmony_ci tst_res(TINFO, "check!"); 265f08c3bdfSopenharmony_ci check("run", run); 266f08c3bdfSopenharmony_ci 267f08c3bdfSopenharmony_ci /* 268f08c3bdfSopenharmony_ci * Temporarily stop the KSM scan during the checks: during the 269f08c3bdfSopenharmony_ci * KSM scan the rmap_items in the stale unstable tree of the 270f08c3bdfSopenharmony_ci * old pass are removed from it and are later reinserted in 271f08c3bdfSopenharmony_ci * the new unstable tree of the current pass. So if the checks 272f08c3bdfSopenharmony_ci * run in the race window between removal and re-insertion, it 273f08c3bdfSopenharmony_ci * can lead to unexpected false positives where page_volatile 274f08c3bdfSopenharmony_ci * is elevated and page_unshared is recessed. 275f08c3bdfSopenharmony_ci */ 276f08c3bdfSopenharmony_ci SAFE_FILE_SCANF(PATH_KSM "run", "%d", &ksm_run_orig); 277f08c3bdfSopenharmony_ci SAFE_FILE_PRINTF(PATH_KSM "run", "0"); 278f08c3bdfSopenharmony_ci 279f08c3bdfSopenharmony_ci check("pages_shared", pages_shared); 280f08c3bdfSopenharmony_ci check("pages_sharing", pages_sharing); 281f08c3bdfSopenharmony_ci check("pages_volatile", pages_volatile); 282f08c3bdfSopenharmony_ci check("pages_unshared", pages_unshared); 283f08c3bdfSopenharmony_ci check("sleep_millisecs", sleep_millisecs); 284f08c3bdfSopenharmony_ci check("pages_to_scan", pages_to_scan); 285f08c3bdfSopenharmony_ci 286f08c3bdfSopenharmony_ci SAFE_FILE_PRINTF(PATH_KSM "run", "%d", ksm_run_orig); 287f08c3bdfSopenharmony_ci} 288f08c3bdfSopenharmony_ci 289f08c3bdfSopenharmony_civoid ksm_group_check(int run, int pages_shared, int pages_sharing, 290f08c3bdfSopenharmony_ci int pages_volatile, int pages_unshared, 291f08c3bdfSopenharmony_ci int sleep_millisecs, int pages_to_scan) 292f08c3bdfSopenharmony_ci{ 293f08c3bdfSopenharmony_ci if (run != 1) { 294f08c3bdfSopenharmony_ci tst_res(TFAIL, "group_check run is not 1, %d.", run); 295f08c3bdfSopenharmony_ci } else { 296f08c3bdfSopenharmony_ci /* wait for ksm daemon to scan all mergeable pages. */ 297f08c3bdfSopenharmony_ci wait_ksmd_full_scan(); 298f08c3bdfSopenharmony_ci } 299f08c3bdfSopenharmony_ci 300f08c3bdfSopenharmony_ci final_group_check(run, pages_shared, pages_sharing, 301f08c3bdfSopenharmony_ci pages_volatile, pages_unshared, 302f08c3bdfSopenharmony_ci sleep_millisecs, pages_to_scan); 303f08c3bdfSopenharmony_ci} 304f08c3bdfSopenharmony_ci 305f08c3bdfSopenharmony_cistatic void verify(char **memory, char value, int proc, 306f08c3bdfSopenharmony_ci int start, int end, int start2, int end2) 307f08c3bdfSopenharmony_ci{ 308f08c3bdfSopenharmony_ci int i, j; 309f08c3bdfSopenharmony_ci void *s = NULL; 310f08c3bdfSopenharmony_ci 311f08c3bdfSopenharmony_ci s = SAFE_MALLOC((end - start) * (end2 - start2)); 312f08c3bdfSopenharmony_ci 313f08c3bdfSopenharmony_ci tst_res(TINFO, "child %d verifies memory content.", proc); 314f08c3bdfSopenharmony_ci memset(s, value, (end - start) * (end2 - start2)); 315f08c3bdfSopenharmony_ci if (memcmp(memory[start], s, (end - start) * (end2 - start2)) 316f08c3bdfSopenharmony_ci != 0) 317f08c3bdfSopenharmony_ci for (j = start; j < end; j++) 318f08c3bdfSopenharmony_ci for (i = start2; i < end2; i++) 319f08c3bdfSopenharmony_ci if (memory[j][i] != value) 320f08c3bdfSopenharmony_ci tst_res(TFAIL, "child %d has %c at " 321f08c3bdfSopenharmony_ci "%d,%d,%d.", 322f08c3bdfSopenharmony_ci proc, memory[j][i], proc, 323f08c3bdfSopenharmony_ci j, i); 324f08c3bdfSopenharmony_ci free(s); 325f08c3bdfSopenharmony_ci} 326f08c3bdfSopenharmony_ci 327f08c3bdfSopenharmony_civoid check_hugepage(void) 328f08c3bdfSopenharmony_ci{ 329f08c3bdfSopenharmony_ci if (access(PATH_HUGEPAGES, F_OK)) 330f08c3bdfSopenharmony_ci tst_brk(TCONF, "Huge page is not supported."); 331f08c3bdfSopenharmony_ci} 332f08c3bdfSopenharmony_ci 333f08c3bdfSopenharmony_cistruct ksm_merge_data { 334f08c3bdfSopenharmony_ci char data; 335f08c3bdfSopenharmony_ci unsigned int mergeable_size; 336f08c3bdfSopenharmony_ci}; 337f08c3bdfSopenharmony_ci 338f08c3bdfSopenharmony_cistatic void ksm_child_memset(int child_num, int size, int total_unit, 339f08c3bdfSopenharmony_ci struct ksm_merge_data ksm_merge_data, char **memory) 340f08c3bdfSopenharmony_ci{ 341f08c3bdfSopenharmony_ci int i = 0, j; 342f08c3bdfSopenharmony_ci int unit = size / total_unit; 343f08c3bdfSopenharmony_ci 344f08c3bdfSopenharmony_ci tst_res(TINFO, "child %d continues...", child_num); 345f08c3bdfSopenharmony_ci 346f08c3bdfSopenharmony_ci if (ksm_merge_data.mergeable_size == size * MB) { 347f08c3bdfSopenharmony_ci tst_res(TINFO, "child %d allocates %d MB filled with '%c'", 348f08c3bdfSopenharmony_ci child_num, size, ksm_merge_data.data); 349f08c3bdfSopenharmony_ci 350f08c3bdfSopenharmony_ci } else { 351f08c3bdfSopenharmony_ci tst_res(TINFO, "child %d allocates %d MB filled with '%c'" 352f08c3bdfSopenharmony_ci " except one page with 'e'", 353f08c3bdfSopenharmony_ci child_num, size, ksm_merge_data.data); 354f08c3bdfSopenharmony_ci } 355f08c3bdfSopenharmony_ci 356f08c3bdfSopenharmony_ci for (j = 0; j < total_unit; j++) { 357f08c3bdfSopenharmony_ci for (i = 0; (unsigned int)i < unit * MB; i++) 358f08c3bdfSopenharmony_ci memory[j][i] = ksm_merge_data.data; 359f08c3bdfSopenharmony_ci } 360f08c3bdfSopenharmony_ci 361f08c3bdfSopenharmony_ci /* if it contains unshared page, then set 'e' char 362f08c3bdfSopenharmony_ci * at the end of the last page 363f08c3bdfSopenharmony_ci */ 364f08c3bdfSopenharmony_ci if (ksm_merge_data.mergeable_size < size * MB) 365f08c3bdfSopenharmony_ci memory[j-1][i-1] = 'e'; 366f08c3bdfSopenharmony_ci} 367f08c3bdfSopenharmony_ci 368f08c3bdfSopenharmony_cistatic void create_ksm_child(int child_num, int size, int unit, 369f08c3bdfSopenharmony_ci struct ksm_merge_data *ksm_merge_data) 370f08c3bdfSopenharmony_ci{ 371f08c3bdfSopenharmony_ci int j, total_unit; 372f08c3bdfSopenharmony_ci char **memory; 373f08c3bdfSopenharmony_ci 374f08c3bdfSopenharmony_ci /* The total units in all */ 375f08c3bdfSopenharmony_ci total_unit = size / unit; 376f08c3bdfSopenharmony_ci 377f08c3bdfSopenharmony_ci /* Apply for the space for memory */ 378f08c3bdfSopenharmony_ci memory = SAFE_MALLOC(total_unit * sizeof(char *)); 379f08c3bdfSopenharmony_ci for (j = 0; j < total_unit; j++) { 380f08c3bdfSopenharmony_ci memory[j] = SAFE_MMAP(NULL, unit * MB, PROT_READ|PROT_WRITE, 381f08c3bdfSopenharmony_ci MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); 382f08c3bdfSopenharmony_ci#ifdef HAVE_DECL_MADV_MERGEABLE 383f08c3bdfSopenharmony_ci if (madvise(memory[j], unit * MB, MADV_MERGEABLE) == -1) 384f08c3bdfSopenharmony_ci tst_brk(TBROK|TERRNO, "madvise"); 385f08c3bdfSopenharmony_ci#endif 386f08c3bdfSopenharmony_ci } 387f08c3bdfSopenharmony_ci 388f08c3bdfSopenharmony_ci tst_res(TINFO, "child %d stops.", child_num); 389f08c3bdfSopenharmony_ci if (raise(SIGSTOP) == -1) 390f08c3bdfSopenharmony_ci tst_brk(TBROK|TERRNO, "kill"); 391f08c3bdfSopenharmony_ci fflush(stdout); 392f08c3bdfSopenharmony_ci 393f08c3bdfSopenharmony_ci for (j = 0; j < 4; j++) { 394f08c3bdfSopenharmony_ci 395f08c3bdfSopenharmony_ci ksm_child_memset(child_num, size, total_unit, 396f08c3bdfSopenharmony_ci ksm_merge_data[j], memory); 397f08c3bdfSopenharmony_ci 398f08c3bdfSopenharmony_ci fflush(stdout); 399f08c3bdfSopenharmony_ci 400f08c3bdfSopenharmony_ci tst_res(TINFO, "child %d stops.", child_num); 401f08c3bdfSopenharmony_ci if (raise(SIGSTOP) == -1) 402f08c3bdfSopenharmony_ci tst_brk(TBROK|TERRNO, "kill"); 403f08c3bdfSopenharmony_ci 404f08c3bdfSopenharmony_ci if (ksm_merge_data[j].mergeable_size < size * MB) { 405f08c3bdfSopenharmony_ci verify(memory, 'e', child_num, total_unit - 1, 406f08c3bdfSopenharmony_ci total_unit, unit * MB - 1, unit * MB); 407f08c3bdfSopenharmony_ci verify(memory, ksm_merge_data[j].data, child_num, 408f08c3bdfSopenharmony_ci 0, total_unit, 0, unit * MB - 1); 409f08c3bdfSopenharmony_ci } else { 410f08c3bdfSopenharmony_ci verify(memory, ksm_merge_data[j].data, child_num, 411f08c3bdfSopenharmony_ci 0, total_unit, 0, unit * MB); 412f08c3bdfSopenharmony_ci } 413f08c3bdfSopenharmony_ci } 414f08c3bdfSopenharmony_ci 415f08c3bdfSopenharmony_ci tst_res(TINFO, "child %d finished.", child_num); 416f08c3bdfSopenharmony_ci} 417f08c3bdfSopenharmony_ci 418f08c3bdfSopenharmony_cistatic void stop_ksm_children(int *child, int num) 419f08c3bdfSopenharmony_ci{ 420f08c3bdfSopenharmony_ci int k, status; 421f08c3bdfSopenharmony_ci 422f08c3bdfSopenharmony_ci tst_res(TINFO, "wait for all children to stop."); 423f08c3bdfSopenharmony_ci for (k = 0; k < num; k++) { 424f08c3bdfSopenharmony_ci SAFE_WAITPID(child[k], &status, WUNTRACED); 425f08c3bdfSopenharmony_ci if (!WIFSTOPPED(status)) 426f08c3bdfSopenharmony_ci tst_brk(TBROK, "child %d was not stopped", k); 427f08c3bdfSopenharmony_ci } 428f08c3bdfSopenharmony_ci} 429f08c3bdfSopenharmony_ci 430f08c3bdfSopenharmony_cistatic void resume_ksm_children(int *child, int num) 431f08c3bdfSopenharmony_ci{ 432f08c3bdfSopenharmony_ci int k; 433f08c3bdfSopenharmony_ci 434f08c3bdfSopenharmony_ci tst_res(TINFO, "resume all children."); 435f08c3bdfSopenharmony_ci for (k = 0; k < num; k++) 436f08c3bdfSopenharmony_ci SAFE_KILL(child[k], SIGCONT); 437f08c3bdfSopenharmony_ci 438f08c3bdfSopenharmony_ci fflush(stdout); 439f08c3bdfSopenharmony_ci} 440f08c3bdfSopenharmony_ci 441f08c3bdfSopenharmony_civoid create_same_memory(int size, int num, int unit) 442f08c3bdfSopenharmony_ci{ 443f08c3bdfSopenharmony_ci int i, j, status, *child; 444f08c3bdfSopenharmony_ci unsigned long ps, pages; 445f08c3bdfSopenharmony_ci struct ksm_merge_data **ksm_data; 446f08c3bdfSopenharmony_ci 447f08c3bdfSopenharmony_ci struct ksm_merge_data ksm_data0[] = { 448f08c3bdfSopenharmony_ci {'c', size*MB}, {'c', size*MB}, {'d', size*MB}, {'d', size*MB}, 449f08c3bdfSopenharmony_ci }; 450f08c3bdfSopenharmony_ci struct ksm_merge_data ksm_data1[] = { 451f08c3bdfSopenharmony_ci {'a', size*MB}, {'b', size*MB}, {'d', size*MB}, {'d', size*MB-1}, 452f08c3bdfSopenharmony_ci }; 453f08c3bdfSopenharmony_ci struct ksm_merge_data ksm_data2[] = { 454f08c3bdfSopenharmony_ci {'a', size*MB}, {'a', size*MB}, {'d', size*MB}, {'d', size*MB}, 455f08c3bdfSopenharmony_ci }; 456f08c3bdfSopenharmony_ci 457f08c3bdfSopenharmony_ci ps = sysconf(_SC_PAGE_SIZE); 458f08c3bdfSopenharmony_ci pages = MB / ps; 459f08c3bdfSopenharmony_ci 460f08c3bdfSopenharmony_ci ksm_data = malloc((num - 3) * sizeof(struct ksm_merge_data *)); 461f08c3bdfSopenharmony_ci /* Since from third child, the data is same with the first child's */ 462f08c3bdfSopenharmony_ci for (i = 0; i < num - 3; i++) { 463f08c3bdfSopenharmony_ci ksm_data[i] = malloc(4 * sizeof(struct ksm_merge_data)); 464f08c3bdfSopenharmony_ci for (j = 0; j < 4; j++) { 465f08c3bdfSopenharmony_ci ksm_data[i][j].data = ksm_data0[j].data; 466f08c3bdfSopenharmony_ci ksm_data[i][j].mergeable_size = 467f08c3bdfSopenharmony_ci ksm_data0[j].mergeable_size; 468f08c3bdfSopenharmony_ci } 469f08c3bdfSopenharmony_ci } 470f08c3bdfSopenharmony_ci 471f08c3bdfSopenharmony_ci child = SAFE_MALLOC(num * sizeof(int)); 472f08c3bdfSopenharmony_ci 473f08c3bdfSopenharmony_ci for (i = 0; i < num; i++) { 474f08c3bdfSopenharmony_ci fflush(stdout); 475f08c3bdfSopenharmony_ci switch (child[i] = SAFE_FORK()) { 476f08c3bdfSopenharmony_ci case 0: 477f08c3bdfSopenharmony_ci if (i == 0) { 478f08c3bdfSopenharmony_ci create_ksm_child(i, size, unit, ksm_data0); 479f08c3bdfSopenharmony_ci exit(0); 480f08c3bdfSopenharmony_ci } else if (i == 1) { 481f08c3bdfSopenharmony_ci create_ksm_child(i, size, unit, ksm_data1); 482f08c3bdfSopenharmony_ci exit(0); 483f08c3bdfSopenharmony_ci } else if (i == 2) { 484f08c3bdfSopenharmony_ci create_ksm_child(i, size, unit, ksm_data2); 485f08c3bdfSopenharmony_ci exit(0); 486f08c3bdfSopenharmony_ci } else { 487f08c3bdfSopenharmony_ci create_ksm_child(i, size, unit, ksm_data[i-3]); 488f08c3bdfSopenharmony_ci exit(0); 489f08c3bdfSopenharmony_ci } 490f08c3bdfSopenharmony_ci } 491f08c3bdfSopenharmony_ci } 492f08c3bdfSopenharmony_ci 493f08c3bdfSopenharmony_ci stop_ksm_children(child, num); 494f08c3bdfSopenharmony_ci 495f08c3bdfSopenharmony_ci tst_res(TINFO, "KSM merging..."); 496f08c3bdfSopenharmony_ci if (access(PATH_KSM "max_page_sharing", F_OK) == 0) { 497f08c3bdfSopenharmony_ci SAFE_FILE_PRINTF(PATH_KSM "run", "2"); 498f08c3bdfSopenharmony_ci SAFE_FILE_PRINTF(PATH_KSM "max_page_sharing", "%ld", size * pages * num); 499f08c3bdfSopenharmony_ci } 500f08c3bdfSopenharmony_ci 501f08c3bdfSopenharmony_ci SAFE_FILE_PRINTF(PATH_KSM "run", "1"); 502f08c3bdfSopenharmony_ci SAFE_FILE_PRINTF(PATH_KSM "pages_to_scan", "%ld", size * pages * num); 503f08c3bdfSopenharmony_ci SAFE_FILE_PRINTF(PATH_KSM "sleep_millisecs", "0"); 504f08c3bdfSopenharmony_ci 505f08c3bdfSopenharmony_ci resume_ksm_children(child, num); 506f08c3bdfSopenharmony_ci stop_ksm_children(child, num); 507f08c3bdfSopenharmony_ci ksm_group_check(1, 2, size * num * pages - 2, 0, 0, 0, size * pages * num); 508f08c3bdfSopenharmony_ci 509f08c3bdfSopenharmony_ci resume_ksm_children(child, num); 510f08c3bdfSopenharmony_ci stop_ksm_children(child, num); 511f08c3bdfSopenharmony_ci ksm_group_check(1, 3, size * num * pages - 3, 0, 0, 0, size * pages * num); 512f08c3bdfSopenharmony_ci 513f08c3bdfSopenharmony_ci resume_ksm_children(child, num); 514f08c3bdfSopenharmony_ci stop_ksm_children(child, num); 515f08c3bdfSopenharmony_ci ksm_group_check(1, 1, size * num * pages - 1, 0, 0, 0, size * pages * num); 516f08c3bdfSopenharmony_ci 517f08c3bdfSopenharmony_ci resume_ksm_children(child, num); 518f08c3bdfSopenharmony_ci stop_ksm_children(child, num); 519f08c3bdfSopenharmony_ci ksm_group_check(1, 1, size * num * pages - 2, 0, 1, 0, size * pages * num); 520f08c3bdfSopenharmony_ci 521f08c3bdfSopenharmony_ci tst_res(TINFO, "KSM unmerging..."); 522f08c3bdfSopenharmony_ci SAFE_FILE_PRINTF(PATH_KSM "run", "2"); 523f08c3bdfSopenharmony_ci 524f08c3bdfSopenharmony_ci resume_ksm_children(child, num); 525f08c3bdfSopenharmony_ci final_group_check(2, 0, 0, 0, 0, 0, size * pages * num); 526f08c3bdfSopenharmony_ci 527f08c3bdfSopenharmony_ci tst_res(TINFO, "stop KSM."); 528f08c3bdfSopenharmony_ci SAFE_FILE_PRINTF(PATH_KSM "run", "0"); 529f08c3bdfSopenharmony_ci final_group_check(0, 0, 0, 0, 0, 0, size * pages * num); 530f08c3bdfSopenharmony_ci 531f08c3bdfSopenharmony_ci while (waitpid(-1, &status, 0) > 0) 532f08c3bdfSopenharmony_ci if (WEXITSTATUS(status) != 0) 533f08c3bdfSopenharmony_ci tst_res(TFAIL, "child exit status is %d", 534f08c3bdfSopenharmony_ci WEXITSTATUS(status)); 535f08c3bdfSopenharmony_ci} 536f08c3bdfSopenharmony_ci 537f08c3bdfSopenharmony_ci/* THP */ 538f08c3bdfSopenharmony_ci 539f08c3bdfSopenharmony_ci/* cpuset/memcg */ 540f08c3bdfSopenharmony_cistatic void gather_node_cpus(char *cpus, long nd) 541f08c3bdfSopenharmony_ci{ 542f08c3bdfSopenharmony_ci int ncpus = 0; 543f08c3bdfSopenharmony_ci int i; 544f08c3bdfSopenharmony_ci long online; 545f08c3bdfSopenharmony_ci char buf[BUFSIZ]; 546f08c3bdfSopenharmony_ci char path[BUFSIZ], path1[BUFSIZ]; 547f08c3bdfSopenharmony_ci 548f08c3bdfSopenharmony_ci while (path_exist(PATH_SYS_SYSTEM "/cpu/cpu%d", ncpus)) 549f08c3bdfSopenharmony_ci ncpus++; 550f08c3bdfSopenharmony_ci 551f08c3bdfSopenharmony_ci for (i = 0; i < ncpus; i++) { 552f08c3bdfSopenharmony_ci snprintf(path, BUFSIZ, 553f08c3bdfSopenharmony_ci PATH_SYS_SYSTEM "/node/node%ld/cpu%d", nd, i); 554f08c3bdfSopenharmony_ci if (path_exist(path)) { 555f08c3bdfSopenharmony_ci snprintf(path1, BUFSIZ, "%s/online", path); 556f08c3bdfSopenharmony_ci /* 557f08c3bdfSopenharmony_ci * if there is no online knob, then the cpu cannot 558f08c3bdfSopenharmony_ci * be taken offline 559f08c3bdfSopenharmony_ci */ 560f08c3bdfSopenharmony_ci if (path_exist(path1)) { 561f08c3bdfSopenharmony_ci SAFE_FILE_SCANF(path1, "%ld", &online); 562f08c3bdfSopenharmony_ci if (online == 0) 563f08c3bdfSopenharmony_ci continue; 564f08c3bdfSopenharmony_ci } 565f08c3bdfSopenharmony_ci sprintf(buf, "%d,", i); 566f08c3bdfSopenharmony_ci strcat(cpus, buf); 567f08c3bdfSopenharmony_ci } 568f08c3bdfSopenharmony_ci } 569f08c3bdfSopenharmony_ci /* Remove the trailing comma. */ 570f08c3bdfSopenharmony_ci cpus[strlen(cpus) - 1] = '\0'; 571f08c3bdfSopenharmony_ci} 572f08c3bdfSopenharmony_ci 573f08c3bdfSopenharmony_civoid write_cpusets(const struct tst_cg_group *cg, long nd) 574f08c3bdfSopenharmony_ci{ 575f08c3bdfSopenharmony_ci char cpus[BUFSIZ] = ""; 576f08c3bdfSopenharmony_ci 577f08c3bdfSopenharmony_ci SAFE_CG_PRINTF(cg, "cpuset.mems", "%ld", nd); 578f08c3bdfSopenharmony_ci 579f08c3bdfSopenharmony_ci gather_node_cpus(cpus, nd); 580f08c3bdfSopenharmony_ci /* 581f08c3bdfSopenharmony_ci * If the 'nd' node doesn't contain any CPUs, 582f08c3bdfSopenharmony_ci * the first ID of CPU '0' will be used as 583f08c3bdfSopenharmony_ci * the value of cpuset.cpus. 584f08c3bdfSopenharmony_ci */ 585f08c3bdfSopenharmony_ci if (strlen(cpus) != 0) { 586f08c3bdfSopenharmony_ci SAFE_CG_PRINT(cg, "cpuset.cpus", cpus); 587f08c3bdfSopenharmony_ci } else { 588f08c3bdfSopenharmony_ci tst_res(TINFO, "No CPUs in the node%ld; " 589f08c3bdfSopenharmony_ci "using only CPU0", nd); 590f08c3bdfSopenharmony_ci SAFE_CG_PRINT(cg, "cpuset.cpus", "0"); 591f08c3bdfSopenharmony_ci } 592f08c3bdfSopenharmony_ci} 593f08c3bdfSopenharmony_ci 594f08c3bdfSopenharmony_ci/* shared */ 595f08c3bdfSopenharmony_ci 596f08c3bdfSopenharmony_ci/* Warning: *DO NOT* use this function in child */ 597f08c3bdfSopenharmony_ciunsigned int get_a_numa_node(void) 598f08c3bdfSopenharmony_ci{ 599f08c3bdfSopenharmony_ci unsigned int nd1, nd2; 600f08c3bdfSopenharmony_ci int ret; 601f08c3bdfSopenharmony_ci 602f08c3bdfSopenharmony_ci ret = get_allowed_nodes(0, 2, &nd1, &nd2); 603f08c3bdfSopenharmony_ci switch (ret) { 604f08c3bdfSopenharmony_ci case 0: 605f08c3bdfSopenharmony_ci break; 606f08c3bdfSopenharmony_ci case -3: 607f08c3bdfSopenharmony_ci tst_brk(TCONF, "requires a NUMA system."); 608f08c3bdfSopenharmony_ci default: 609f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "1st get_allowed_nodes"); 610f08c3bdfSopenharmony_ci } 611f08c3bdfSopenharmony_ci 612f08c3bdfSopenharmony_ci ret = get_allowed_nodes(NH_MEMS | NH_CPUS, 1, &nd1); 613f08c3bdfSopenharmony_ci switch (ret) { 614f08c3bdfSopenharmony_ci case 0: 615f08c3bdfSopenharmony_ci tst_res(TINFO, "get node%u.", nd1); 616f08c3bdfSopenharmony_ci return nd1; 617f08c3bdfSopenharmony_ci case -3: 618f08c3bdfSopenharmony_ci tst_brk(TCONF, "requires a NUMA system that has " 619f08c3bdfSopenharmony_ci "at least one node with both memory and CPU " 620f08c3bdfSopenharmony_ci "available."); 621f08c3bdfSopenharmony_ci default: 622f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "2nd get_allowed_nodes"); 623f08c3bdfSopenharmony_ci } 624f08c3bdfSopenharmony_ci 625f08c3bdfSopenharmony_ci /* not reached */ 626f08c3bdfSopenharmony_ci abort(); 627f08c3bdfSopenharmony_ci} 628f08c3bdfSopenharmony_ci 629f08c3bdfSopenharmony_ciint path_exist(const char *path, ...) 630f08c3bdfSopenharmony_ci{ 631f08c3bdfSopenharmony_ci va_list ap; 632f08c3bdfSopenharmony_ci char pathbuf[PATH_MAX]; 633f08c3bdfSopenharmony_ci 634f08c3bdfSopenharmony_ci va_start(ap, path); 635f08c3bdfSopenharmony_ci vsnprintf(pathbuf, sizeof(pathbuf), path, ap); 636f08c3bdfSopenharmony_ci va_end(ap); 637f08c3bdfSopenharmony_ci 638f08c3bdfSopenharmony_ci return access(pathbuf, F_OK) == 0; 639f08c3bdfSopenharmony_ci} 640f08c3bdfSopenharmony_ci 641f08c3bdfSopenharmony_civoid set_sys_tune(char *sys_file, long tune, int check) 642f08c3bdfSopenharmony_ci{ 643f08c3bdfSopenharmony_ci long val; 644f08c3bdfSopenharmony_ci char path[BUFSIZ]; 645f08c3bdfSopenharmony_ci 646f08c3bdfSopenharmony_ci tst_res(TINFO, "set %s to %ld", sys_file, tune); 647f08c3bdfSopenharmony_ci 648f08c3bdfSopenharmony_ci snprintf(path, BUFSIZ, PATH_SYSVM "%s", sys_file); 649f08c3bdfSopenharmony_ci SAFE_FILE_PRINTF(path, "%ld", tune); 650f08c3bdfSopenharmony_ci 651f08c3bdfSopenharmony_ci if (check) { 652f08c3bdfSopenharmony_ci val = get_sys_tune(sys_file); 653f08c3bdfSopenharmony_ci if (val != tune) 654f08c3bdfSopenharmony_ci tst_brk(TBROK, "%s = %ld, but expect %ld", 655f08c3bdfSopenharmony_ci sys_file, val, tune); 656f08c3bdfSopenharmony_ci } 657f08c3bdfSopenharmony_ci} 658f08c3bdfSopenharmony_ci 659f08c3bdfSopenharmony_cilong get_sys_tune(char *sys_file) 660f08c3bdfSopenharmony_ci{ 661f08c3bdfSopenharmony_ci char path[BUFSIZ]; 662f08c3bdfSopenharmony_ci long tune; 663f08c3bdfSopenharmony_ci 664f08c3bdfSopenharmony_ci snprintf(path, BUFSIZ, PATH_SYSVM "%s", sys_file); 665f08c3bdfSopenharmony_ci SAFE_FILE_SCANF(path, "%ld", &tune); 666f08c3bdfSopenharmony_ci 667f08c3bdfSopenharmony_ci return tune; 668f08c3bdfSopenharmony_ci} 669f08c3bdfSopenharmony_ci 670f08c3bdfSopenharmony_civoid update_shm_size(size_t * shm_size) 671f08c3bdfSopenharmony_ci{ 672f08c3bdfSopenharmony_ci size_t shmmax; 673f08c3bdfSopenharmony_ci 674f08c3bdfSopenharmony_ci SAFE_FILE_SCANF(PATH_SHMMAX, "%zu", &shmmax); 675f08c3bdfSopenharmony_ci if (*shm_size > shmmax) { 676f08c3bdfSopenharmony_ci tst_res(TINFO, "Set shm_size to shmmax: %zu", shmmax); 677f08c3bdfSopenharmony_ci *shm_size = shmmax; 678f08c3bdfSopenharmony_ci } 679f08c3bdfSopenharmony_ci} 680f08c3bdfSopenharmony_ci 681f08c3bdfSopenharmony_ciint range_is_mapped(unsigned long low, unsigned long high) 682f08c3bdfSopenharmony_ci{ 683f08c3bdfSopenharmony_ci FILE *fp; 684f08c3bdfSopenharmony_ci 685f08c3bdfSopenharmony_ci fp = fopen("/proc/self/maps", "r"); 686f08c3bdfSopenharmony_ci if (fp == NULL) 687f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "Failed to open /proc/self/maps."); 688f08c3bdfSopenharmony_ci 689f08c3bdfSopenharmony_ci while (!feof(fp)) { 690f08c3bdfSopenharmony_ci unsigned long start, end; 691f08c3bdfSopenharmony_ci int ret; 692f08c3bdfSopenharmony_ci 693f08c3bdfSopenharmony_ci ret = fscanf(fp, "%lx-%lx %*[^\n]\n", &start, &end); 694f08c3bdfSopenharmony_ci if (ret != 2) { 695f08c3bdfSopenharmony_ci fclose(fp); 696f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "Couldn't parse /proc/self/maps line."); 697f08c3bdfSopenharmony_ci } 698f08c3bdfSopenharmony_ci 699f08c3bdfSopenharmony_ci if ((start >= low) && (start < high)) { 700f08c3bdfSopenharmony_ci fclose(fp); 701f08c3bdfSopenharmony_ci return 1; 702f08c3bdfSopenharmony_ci } 703f08c3bdfSopenharmony_ci if ((end >= low) && (end < high)) { 704f08c3bdfSopenharmony_ci fclose(fp); 705f08c3bdfSopenharmony_ci return 1; 706f08c3bdfSopenharmony_ci } 707f08c3bdfSopenharmony_ci } 708f08c3bdfSopenharmony_ci 709f08c3bdfSopenharmony_ci fclose(fp); 710f08c3bdfSopenharmony_ci return 0; 711f08c3bdfSopenharmony_ci} 712