// SPDX-License-Identifier: GPL-2.0
/* Manage affinity to optimize IPIs inside the kernel perf API. */
#define _GNU_SOURCE 1
#include <sched.h>
#include <stdlib.h>
#include <linux/bitmap.h>
#include <linux/zalloc.h>
#include <perf/cpumap.h>
#include "perf.h"
#include "cpumap.h"
#include "affinity.h"
static int get_cpu_set_size(void )
{
int sz = cpu__max_cpu().cpu + 8 - 1 ;
/*
* sched_getaffinity doesn ' t like masks smaller than the kernel .
* Hopefully that ' s big enough .
*/
if (sz < 4096 )
sz = 4096 ;
return sz / 8 ;
}
int affinity__setup(struct affinity *a)
{
int cpu_set_size = get_cpu_set_size();
a->orig_cpus = bitmap_zalloc(cpu_set_size * 8 );
if (!a->orig_cpus)
return -1 ;
sched_getaffinity(0 , cpu_set_size, (cpu_set_t *)a->orig_cpus);
a->sched_cpus = bitmap_zalloc(cpu_set_size * 8 );
if (!a->sched_cpus) {
zfree(&a->orig_cpus);
return -1 ;
}
bitmap_zero((unsigned long *)a->sched_cpus, cpu_set_size);
a->changed = false ;
return 0 ;
}
/*
* perf_event_open does an IPI internally to the target CPU .
* It is more efficient to change perf ' s affinity to the target
* CPU and then set up all events on that CPU , so we amortize
* CPU communication .
*/
void affinity__set(struct affinity *a, int cpu)
{
int cpu_set_size = get_cpu_set_size();
/*
* Return :
* - if cpu is - 1
* - restrict out of bound access to sched_cpus
*/
if (cpu == -1 || ((cpu >= (cpu_set_size * 8 ))))
return ;
a->changed = true ;
__set_bit(cpu, a->sched_cpus);
/*
* We ignore errors because affinity is just an optimization .
* This could happen for example with isolated CPUs or cpusets .
* In this case the IPIs inside the kernel ' s perf API still work .
*/
sched_setaffinity(0 , cpu_set_size, (cpu_set_t *)a->sched_cpus);
__clear_bit(cpu, a->sched_cpus);
}
static void __affinity__cleanup(struct affinity *a)
{
int cpu_set_size = get_cpu_set_size();
if (a->changed)
sched_setaffinity(0 , cpu_set_size, (cpu_set_t *)a->orig_cpus);
zfree(&a->sched_cpus);
zfree(&a->orig_cpus);
}
void affinity__cleanup(struct affinity *a)
{
if (a != NULL)
__affinity__cleanup(a);
}
void cpu_map__set_affinity(const struct perf_cpu_map *cpumap)
{
int cpu_set_size = get_cpu_set_size();
unsigned long *cpuset = bitmap_zalloc(cpu_set_size * 8 );
struct perf_cpu cpu;
int idx;
if (!cpuset)
return ;
perf_cpu_map__for_each_cpu_skip_any(cpu, idx, cpumap)
__set_bit(cpu.cpu, cpuset);
sched_setaffinity(0 , cpu_set_size, (cpu_set_t *)cpuset);
zfree(&cpuset);
}
Messung V0.5 in Prozent C=95 H=100 G=97
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-10-11)
¤
*© Formatika GbR, Deutschland