kernel/irq/matrix.c

Source file repositories/reference/linux-study-clean/kernel/irq/matrix.c

File Facts

System
Linux kernel
Corpus path
kernel/irq/matrix.c
Extension
.c
Size
13710 bytes
Lines
520
Domain
Core OS
Bucket
Scheduler, Processes, Timers, Sync, And Syscalls
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

struct cpumap {
	unsigned int		available;
	unsigned int		allocated;
	unsigned int		managed;
	unsigned int		managed_allocated;
	bool			initialized;
	bool			online;
	unsigned long		*managed_map;
	unsigned long		alloc_map[];
};

struct irq_matrix {
	unsigned int		matrix_bits;
	unsigned int		alloc_start;
	unsigned int		alloc_end;
	unsigned int		alloc_size;
	unsigned int		global_available;
	unsigned int		global_reserved;
	unsigned int		systembits_inalloc;
	unsigned int		total_allocated;
	unsigned int		online_maps;
	struct cpumap __percpu	*maps;
	unsigned long		*system_map;
	unsigned long		scratch_map[];
};

#define CREATE_TRACE_POINTS
#include <trace/events/irq_matrix.h>

/**
 * irq_alloc_matrix - Allocate a irq_matrix structure and initialize it
 * @matrix_bits:	Number of matrix bits
 * @alloc_start:	From which bit the allocation search starts
 * @alloc_end:		At which bit the allocation search ends, i.e first
 *			invalid bit
 */
__init struct irq_matrix *irq_alloc_matrix(unsigned int matrix_bits,
					   unsigned int alloc_start,
					   unsigned int alloc_end)
{
	unsigned int cpu, matrix_size = BITS_TO_LONGS(matrix_bits);
	struct irq_matrix *m;

	m = kzalloc_flex(*m, scratch_map, matrix_size * 2);
	if (!m)
		return NULL;

	m->system_map = &m->scratch_map[matrix_size];

	m->matrix_bits = matrix_bits;
	m->alloc_start = alloc_start;
	m->alloc_end = alloc_end;
	m->alloc_size = alloc_end - alloc_start;
	m->maps = __alloc_percpu(struct_size(m->maps, alloc_map, matrix_size * 2),
				 __alignof__(*m->maps));
	if (!m->maps) {
		kfree(m);
		return NULL;
	}

	for_each_possible_cpu(cpu) {
		struct cpumap *cm = per_cpu_ptr(m->maps, cpu);

		cm->managed_map = &cm->alloc_map[matrix_size];
	}

	return m;
}

/**
 * irq_matrix_online - Bring the local CPU matrix online
 * @m:		Matrix pointer
 */
void irq_matrix_online(struct irq_matrix *m)
{
	struct cpumap *cm = this_cpu_ptr(m->maps);

	BUG_ON(cm->online);

	if (!cm->initialized) {
		cm->available = m->alloc_size;
		cm->available -= cm->managed + m->systembits_inalloc;
		cm->initialized = true;
	}
	m->global_available += cm->available;
	cm->online = true;
	m->online_maps++;
	trace_irq_matrix_online(m);
}

Annotation

Implementation Notes