47 lines
1.3 KiB
C
47 lines
1.3 KiB
C
#pragma once
|
|
|
|
#include <zinnia/compiler.h>
|
|
#include <zinnia/sched.h>
|
|
#include <zinnia/usercopy.h>
|
|
#include <stddef.h>
|
|
|
|
// # On using per-CPU data
|
|
//
|
|
// Defining variables with `[[__percpu]]` will put them in a special section.
|
|
// This section is unique for every CPU. To access the correct memory of the
|
|
// caller's CPU, use `percpu_ref`. To access another CPU's copy, use `percpu_ref_on`.
|
|
//
|
|
// ## Example
|
|
//
|
|
// ```
|
|
// [[__percpu]]
|
|
// int my_cpu_data = 0;
|
|
//
|
|
// int get_foo() {
|
|
// return *percpu_ref(my_cpu_data);
|
|
// }
|
|
// ```
|
|
|
|
#define __percpu __used, __section(".percpu.data")
|
|
#define percpu_ref_on(cpu, x) ((typeof(&(x)))((void*)(cpu) + ((void*)&(x) - (void*)&percpu_bsp)))
|
|
#define percpu_ref(x) percpu_ref_on(percpu_get(), x)
|
|
|
|
// CPU-relative information.
|
|
struct percpu {
|
|
struct percpu* self; // A pointer to this structure.
|
|
size_t id; // The virtual ID of this CPU.
|
|
bool online; // Whether this CPU is initialized and active.
|
|
uintptr_t kernel_stack; // The kernel mode stack.
|
|
uintptr_t user_stack; // The user mode stack.
|
|
struct scheduler sched; // Scheduler information.
|
|
};
|
|
|
|
struct percpu* percpu_new();
|
|
size_t percpu_max_cpus();
|
|
struct percpu* percpu_get();
|
|
void percpu_bsp_init();
|
|
void percpu_init();
|
|
|
|
// Per-CPU data for the bootstrap processor.
|
|
extern struct percpu percpu_bsp;
|