#pragma once #include #include #include #include // # 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;