|
PatchworkOS
69292a3
A non-POSIX operating system.
|
Per CPU data. More...
Per CPU data.
In the x86 architecture the gs and fs segment registers can be used to access data relative to the address stored in the MSR_GS_BASE or MSR_FS_BASE MSRs. In AT&T assembly this would look like this:
This means that, since each cpu has its own MSR_GS_BASE, we can store the address of each CPU's structure in its own MSR_GS_BASE and then access data within that structure using offsets.
Allocating a percpu variable then becomes as simple as allocating an offset within the percpu buffer in the CPU structure, and accessing it using the gs segment register.
gs register does not store an address directly, rather it allows us to access memory relative to the address stored in the MSR_GS_BASE MSR. This is why we define Per-CPU variables as offsets within the CPU structure rather than absolute addresses.To define a Per-CPU variable use the PERCPU_DEFINE() macro. This will add a percpu_def_t entry to the ._percpu section. The PERCPU_INIT()macro can be used to allocate and initialize all Per-CPU variables defined in the module's._percpu` section, potentially invoking any needed constructors.
pcpu_ prefix for clarity.All Per-CPU variables can optionally have constructors (ctor) and destructors (dtor) defined. These will be called on each CPU either during boot, when the CPU is initialized, or via a call to percpu_update().
By default, all variables are zero-initialized when allocated.
Data Structures | |
| struct | percpu_def_t |
| Structure to define a percpu variable. More... | |
Macros | |
| #define | PERCPU_ALIGNMENT 64 |
The PERCPU_ALIGNMENT constant defines the alignment for per-CPU variables. | |
| #define | PERCPU __seg_gs* |
Attribute specifying that the variable is an offset into the GS segment register. | |
| #define | SELF ((cpu_t PERCPU)0) |
| Macro to access data in the current cpu. | |
| #define | SELF_PTR(ptr) ((void*)((uintptr_t)(SELF->self->percpu) + ((uintptr_t)(ptr) - offsetof(cpu_t, percpu)))) |
| Macro to get a pointer to a percpu variable on the current CPU. | |
| #define | CPU_PTR(id, ptr) ((void*)((uintptr_t)(cpu_get_by_id(id)->percpu) + ((uintptr_t)(ptr) - offsetof(cpu_t, percpu)))) |
| Macro to get a pointer to a percpu variable on a specific CPU. | |
| #define | PERCPU_DEFINE(type, name, ...) |
| Macro to define a percpu variable. | |
| #define | PERCPU_DEFINE_CTOR(type, name) |
| Macro to define a percpu variable with a constructor. | |
| #define | PERCPU_DEFINE_DTOR(type, name) |
| Macro to define a percpu variable with a destructor. | |
| #define | PERCPU_INIT() |
Initialize all percpu variables within the current modules .percpu section. | |
| #define | PERCPU_DEINIT() |
Deinitialize all percpu variables within the current modules .percpu section. | |
Typedefs | |
| typedef size_t | percpu_t |
| The type that the compiler uses to store per-CPU variables. | |
Functions | |
| void | percpu_init (cpu_t *cpu) |
| Initialize the percpu system. | |
| percpu_t | percpu_alloc (size_t size) |
| Allocates a percpu variable. | |
| void | percpu_free (percpu_t ptr, size_t size) |
| Frees a percpu variable. | |
| void | percpu_update (void) |
| Update percpu sections on the current CPU. | |
| void | percpu_section_init (percpu_def_t *start, percpu_def_t *end) |
| Register a percpu section and run constructors. | |
| void | percpu_section_deinit (percpu_def_t *start, percpu_def_t *end) |
| Unregister a percpu section and run destructors. | |
| #define PERCPU_ALIGNMENT 64 |
| #define PERCPU __seg_gs* |
| #define PERCPU_DEFINE | ( | type, | |
| name, | |||
| ... | |||
| ) |
Macro to define a percpu variable.
This macro defines a percpu variable and registers it in the ._percpu section, so that it can be initialized by PERCPU_INIT().
| type | The type of the percpu variable. |
| name | The name of the percpu variable. |
| ... | Optional constructor and destructor functions for the percpu variable. |
| #define PERCPU_DEFINE_CTOR | ( | type, | |
| name | |||
| ) |
Macro to define a percpu variable with a constructor.
This macro defines a percpu variable with a constructor and registers it in the ._percpu section, so that it can be initialized by PERCPU_INIT().
| type | The type of the percpu variable. |
| name | The name of the percpu variable. |
| #define PERCPU_DEFINE_DTOR | ( | type, | |
| name | |||
| ) |
Macro to define a percpu variable with a destructor.
This macro defines a percpu variable with a destructor and registers it in the ._percpu section, so that it can be deinitialized by PERCPU_FINIT().
| type | The type of the percpu variable. |
| name | The name of the percpu variable. |
| #define PERCPU_INIT | ( | ) |
Initialize all percpu variables within the current modules .percpu section.
| #define PERCPU_DEINIT | ( | ) |
Deinitialize all percpu variables within the current modules .percpu section.
| void percpu_init | ( | cpu_t * | cpu | ) |
Initialize the percpu system.
This will setup the gs segment register to point to the CPU structure.
| cpu | The CPU to initialize percpu for, should be the current CPU. |
Definition at line 33 of file percpu.c.
| void percpu_update | ( | void | ) |
| void percpu_section_init | ( | percpu_def_t * | start, |
| percpu_def_t * | end | ||
| ) |
| void percpu_section_deinit | ( | percpu_def_t * | start, |
| percpu_def_t * | end | ||
| ) |