affinity.c (1947B)
1// SPDX-License-Identifier: GPL-2.0 2/* Manage affinity to optimize IPIs inside the kernel perf API. */ 3#define _GNU_SOURCE 1 4#include <sched.h> 5#include <stdlib.h> 6#include <linux/bitmap.h> 7#include <linux/zalloc.h> 8#include "perf.h" 9#include "cpumap.h" 10#include "affinity.h" 11 12static int get_cpu_set_size(void) 13{ 14 int sz = cpu__max_cpu().cpu + 8 - 1; 15 /* 16 * sched_getaffinity doesn't like masks smaller than the kernel. 17 * Hopefully that's big enough. 18 */ 19 if (sz < 4096) 20 sz = 4096; 21 return sz / 8; 22} 23 24int affinity__setup(struct affinity *a) 25{ 26 int cpu_set_size = get_cpu_set_size(); 27 28 a->orig_cpus = bitmap_zalloc(cpu_set_size * 8); 29 if (!a->orig_cpus) 30 return -1; 31 sched_getaffinity(0, cpu_set_size, (cpu_set_t *)a->orig_cpus); 32 a->sched_cpus = bitmap_zalloc(cpu_set_size * 8); 33 if (!a->sched_cpus) { 34 zfree(&a->orig_cpus); 35 return -1; 36 } 37 bitmap_zero((unsigned long *)a->sched_cpus, cpu_set_size); 38 a->changed = false; 39 return 0; 40} 41 42/* 43 * perf_event_open does an IPI internally to the target CPU. 44 * It is more efficient to change perf's affinity to the target 45 * CPU and then set up all events on that CPU, so we amortize 46 * CPU communication. 47 */ 48void affinity__set(struct affinity *a, int cpu) 49{ 50 int cpu_set_size = get_cpu_set_size(); 51 52 if (cpu == -1) 53 return; 54 a->changed = true; 55 set_bit(cpu, a->sched_cpus); 56 /* 57 * We ignore errors because affinity is just an optimization. 58 * This could happen for example with isolated CPUs or cpusets. 59 * In this case the IPIs inside the kernel's perf API still work. 60 */ 61 sched_setaffinity(0, cpu_set_size, (cpu_set_t *)a->sched_cpus); 62 clear_bit(cpu, a->sched_cpus); 63} 64 65static void __affinity__cleanup(struct affinity *a) 66{ 67 int cpu_set_size = get_cpu_set_size(); 68 69 if (a->changed) 70 sched_setaffinity(0, cpu_set_size, (cpu_set_t *)a->orig_cpus); 71 zfree(&a->sched_cpus); 72 zfree(&a->orig_cpus); 73} 74 75void affinity__cleanup(struct affinity *a) 76{ 77 if (a != NULL) 78 __affinity__cleanup(a); 79}