1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright © International Business Machines Corp., 2007, 2008 4f08c3bdfSopenharmony_ci * 5f08c3bdfSopenharmony_ci * Test Description: 6f08c3bdfSopenharmony_ci * The test process is affined to a CPU. It then calls getcpu and 7f08c3bdfSopenharmony_ci * checks that the CPU and node (if supported) match the expected 8f08c3bdfSopenharmony_ci * values. 9f08c3bdfSopenharmony_ci */ 10f08c3bdfSopenharmony_ci 11f08c3bdfSopenharmony_ci#define _GNU_SOURCE 12f08c3bdfSopenharmony_ci#include <dirent.h> 13f08c3bdfSopenharmony_ci#include <errno.h> 14f08c3bdfSopenharmony_ci#include <stdio.h> 15f08c3bdfSopenharmony_ci#include <stdlib.h> 16f08c3bdfSopenharmony_ci#include <sys/types.h> 17f08c3bdfSopenharmony_ci#include "tst_test.h" 18f08c3bdfSopenharmony_ci#include "lapi/cpuset.h" 19f08c3bdfSopenharmony_ci#include "lapi/sched.h" 20f08c3bdfSopenharmony_ci 21f08c3bdfSopenharmony_cistatic unsigned int max_cpuid(size_t size, cpu_set_t * set) 22f08c3bdfSopenharmony_ci{ 23f08c3bdfSopenharmony_ci unsigned int index, max = 0; 24f08c3bdfSopenharmony_ci for (index = 0; index < size * 8; index++) 25f08c3bdfSopenharmony_ci if (CPU_ISSET_S(index, size, set)) 26f08c3bdfSopenharmony_ci max = index; 27f08c3bdfSopenharmony_ci return max; 28f08c3bdfSopenharmony_ci} 29f08c3bdfSopenharmony_ci 30f08c3bdfSopenharmony_ci/* 31f08c3bdfSopenharmony_ci * This will set the affinity to max cpu on which process can run 32f08c3bdfSopenharmony_ci * and return that cpu id to the calling process 33f08c3bdfSopenharmony_ci */ 34f08c3bdfSopenharmony_cistatic unsigned int set_cpu_affinity(void) 35f08c3bdfSopenharmony_ci{ 36f08c3bdfSopenharmony_ci unsigned cpu_max; 37f08c3bdfSopenharmony_ci cpu_set_t *set; 38f08c3bdfSopenharmony_ci size_t size; 39f08c3bdfSopenharmony_ci int nrcpus = 1024; 40f08c3bdfSopenharmony_ci 41f08c3bdfSopenharmony_cirealloc: 42f08c3bdfSopenharmony_ci set = CPU_ALLOC(nrcpus); 43f08c3bdfSopenharmony_ci if (!set) 44f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "CPU_ALLOC()"); 45f08c3bdfSopenharmony_ci 46f08c3bdfSopenharmony_ci size = CPU_ALLOC_SIZE(nrcpus); 47f08c3bdfSopenharmony_ci CPU_ZERO_S(size, set); 48f08c3bdfSopenharmony_ci if (sched_getaffinity(0, size, set) < 0) { 49f08c3bdfSopenharmony_ci CPU_FREE(set); 50f08c3bdfSopenharmony_ci if (errno == EINVAL && nrcpus < (1024 << 8)) { 51f08c3bdfSopenharmony_ci nrcpus = nrcpus << 2; 52f08c3bdfSopenharmony_ci goto realloc; 53f08c3bdfSopenharmony_ci } 54f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "sched_getaffinity()"); 55f08c3bdfSopenharmony_ci } 56f08c3bdfSopenharmony_ci cpu_max = max_cpuid(size, set); 57f08c3bdfSopenharmony_ci CPU_ZERO_S(size, set); 58f08c3bdfSopenharmony_ci CPU_SET_S(cpu_max, size, set); 59f08c3bdfSopenharmony_ci if (sched_setaffinity(0, size, set) < 0) { 60f08c3bdfSopenharmony_ci CPU_FREE(set); 61f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "sched_setaffinity()"); 62f08c3bdfSopenharmony_ci } 63f08c3bdfSopenharmony_ci CPU_FREE(set); 64f08c3bdfSopenharmony_ci return cpu_max; 65f08c3bdfSopenharmony_ci} 66f08c3bdfSopenharmony_ci 67f08c3bdfSopenharmony_cistatic unsigned int get_nodeid(unsigned int cpu_id) 68f08c3bdfSopenharmony_ci{ 69f08c3bdfSopenharmony_ci DIR *directory_parent, *directory_node; 70f08c3bdfSopenharmony_ci struct dirent *de, *dn; 71f08c3bdfSopenharmony_ci char directory_path[PATH_MAX]; 72f08c3bdfSopenharmony_ci char *invalid_number; 73f08c3bdfSopenharmony_ci unsigned int cpu; 74f08c3bdfSopenharmony_ci int node_id = 0; 75f08c3bdfSopenharmony_ci 76f08c3bdfSopenharmony_ci directory_parent = opendir("/sys/devices/system/node"); 77f08c3bdfSopenharmony_ci if (!directory_parent) { 78f08c3bdfSopenharmony_ci tst_res(TINFO, 79f08c3bdfSopenharmony_ci "/sys not mounted or not a numa system. " 80f08c3bdfSopenharmony_ci "Assuming one node"); 81f08c3bdfSopenharmony_ci tst_res(TINFO, "Error opening: /sys/devices/system/node :%s", 82f08c3bdfSopenharmony_ci strerror(errno)); 83f08c3bdfSopenharmony_ci /* Assume CPU belongs to the only node, node zero. */ 84f08c3bdfSopenharmony_ci return 0; 85f08c3bdfSopenharmony_ci } else { 86f08c3bdfSopenharmony_ci while ((de = readdir(directory_parent)) != NULL) { 87f08c3bdfSopenharmony_ci if (strncmp(de->d_name, "node", 4)) 88f08c3bdfSopenharmony_ci continue; 89f08c3bdfSopenharmony_ci sprintf(directory_path, "/sys/devices/system/node/%s", 90f08c3bdfSopenharmony_ci de->d_name); 91f08c3bdfSopenharmony_ci directory_node = opendir(directory_path); 92f08c3bdfSopenharmony_ci while ((dn = readdir(directory_node)) != NULL) { 93f08c3bdfSopenharmony_ci if (strncmp(dn->d_name, "cpu", 3)) 94f08c3bdfSopenharmony_ci continue; 95f08c3bdfSopenharmony_ci cpu = strtoul(dn->d_name + 3, &invalid_number, 0); 96f08c3bdfSopenharmony_ci if (strcmp(invalid_number, "\0")) 97f08c3bdfSopenharmony_ci continue; 98f08c3bdfSopenharmony_ci if (cpu == cpu_id) { 99f08c3bdfSopenharmony_ci node_id = 100f08c3bdfSopenharmony_ci strtoul(de->d_name + 4, NULL, 0); 101f08c3bdfSopenharmony_ci break; 102f08c3bdfSopenharmony_ci } 103f08c3bdfSopenharmony_ci } 104f08c3bdfSopenharmony_ci closedir(directory_node); 105f08c3bdfSopenharmony_ci } 106f08c3bdfSopenharmony_ci closedir(directory_parent); 107f08c3bdfSopenharmony_ci } 108f08c3bdfSopenharmony_ci return node_id; 109f08c3bdfSopenharmony_ci} 110f08c3bdfSopenharmony_ci 111f08c3bdfSopenharmony_cistatic void run(void) 112f08c3bdfSopenharmony_ci{ 113f08c3bdfSopenharmony_ci unsigned int cpu_id, node_id = 0; 114f08c3bdfSopenharmony_ci unsigned int cpu_set; 115f08c3bdfSopenharmony_ci unsigned int node_set; 116f08c3bdfSopenharmony_ci 117f08c3bdfSopenharmony_ci cpu_set = set_cpu_affinity(); 118f08c3bdfSopenharmony_ci node_set = get_nodeid(cpu_set); 119f08c3bdfSopenharmony_ci 120f08c3bdfSopenharmony_ci TEST(getcpu(&cpu_id, &node_id)); 121f08c3bdfSopenharmony_ci if (TST_RET == 0) { 122f08c3bdfSopenharmony_ci if (cpu_id != cpu_set) 123f08c3bdfSopenharmony_ci tst_res(TFAIL, "getcpu() returned wrong value" 124f08c3bdfSopenharmony_ci " expected cpuid:%d, returned value cpuid: %d", 125f08c3bdfSopenharmony_ci cpu_set, cpu_id); 126f08c3bdfSopenharmony_ci else if (node_id != node_set) 127f08c3bdfSopenharmony_ci tst_res(TFAIL, "getcpu() returned wrong value" 128f08c3bdfSopenharmony_ci " expected node id:%d returned node id:%d", 129f08c3bdfSopenharmony_ci node_set, node_id); 130f08c3bdfSopenharmony_ci else 131f08c3bdfSopenharmony_ci tst_res(TPASS, "getcpu() returned proper" 132f08c3bdfSopenharmony_ci " cpuid:%d, node id:%d", cpu_id, 133f08c3bdfSopenharmony_ci node_id); 134f08c3bdfSopenharmony_ci } else { 135f08c3bdfSopenharmony_ci tst_res(TFAIL, "getcpu() Failed, errno=%d:%s", 136f08c3bdfSopenharmony_ci TST_ERR, strerror(TST_ERR)); 137f08c3bdfSopenharmony_ci } 138f08c3bdfSopenharmony_ci} 139f08c3bdfSopenharmony_ci 140f08c3bdfSopenharmony_cistatic struct tst_test test = { 141f08c3bdfSopenharmony_ci .test_all = run, 142f08c3bdfSopenharmony_ci}; 143