Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
 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() + 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_alloc(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_alloc(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
65void 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}