1 /* 2 * Copyright 2013-2015, Michael Ellerman, IBM Corp. 3 * Licensed under GPLv2. 4 */ 5 6 #define _GNU_SOURCE /* For CPU_ZERO etc. */ 7 8 #include <elf.h> 9 #include <errno.h> 10 #include <fcntl.h> 11 #include <link.h> 12 #include <sched.h> 13 #include <stdio.h> 14 #include <sys/stat.h> 15 #include <sys/types.h> 16 #include <unistd.h> 17 18 #include "utils.h" 19 20 static char auxv[4096]; 21 22 void *get_auxv_entry(int type) 23 { 24 ElfW(auxv_t) *p; 25 void *result; 26 ssize_t num; 27 int fd; 28 29 fd = open("/proc/self/auxv", O_RDONLY); 30 if (fd == -1) { 31 perror("open"); 32 return NULL; 33 } 34 35 result = NULL; 36 37 num = read(fd, auxv, sizeof(auxv)); 38 if (num < 0) { 39 perror("read"); 40 goto out; 41 } 42 43 if (num > sizeof(auxv)) { 44 printf("Overflowed auxv buffer\n"); 45 goto out; 46 } 47 48 p = (ElfW(auxv_t) *)auxv; 49 50 while (p->a_type != AT_NULL) { 51 if (p->a_type == type) { 52 result = (void *)p->a_un.a_val; 53 break; 54 } 55 56 p++; 57 } 58 out: 59 close(fd); 60 return result; 61 } 62 63 int pick_online_cpu(void) 64 { 65 cpu_set_t mask; 66 int cpu; 67 68 CPU_ZERO(&mask); 69 70 if (sched_getaffinity(0, sizeof(mask), &mask)) { 71 perror("sched_getaffinity"); 72 return -1; 73 } 74 75 /* We prefer a primary thread, but skip 0 */ 76 for (cpu = 8; cpu < CPU_SETSIZE; cpu += 8) 77 if (CPU_ISSET(cpu, &mask)) 78 return cpu; 79 80 /* Search for anything, but in reverse */ 81 for (cpu = CPU_SETSIZE - 1; cpu >= 0; cpu--) 82 if (CPU_ISSET(cpu, &mask)) 83 return cpu; 84 85 printf("No cpus in affinity mask?!\n"); 86 return -1; 87 } 88