Files
vystem/docs/shelter/std/smp.md
2026-05-27 19:34:54 +02:00

55 lines
2.2 KiB
Markdown

# SMP services
## Introduction
The SMP services provide various abstractions related to SMP programming. It is defined inside `shelter/lib/include/std/smp.h` and implemented in `shelter/lib/src/std/smp.c`
## GS register
Regarding the GS register, two functions are provided:
- `sh_smp_write_gs_base(sh_uint64 value)`: Write the `IA32_GS_BASE` MSR. with a value, return nothing
- `sh_smp_gs_base()`: take no argument and return a `sh_ap_CPU_STRUCT*`
## Spinlocks
The SMP services provide a basic implementation for a spinlock, which look like this:
``` C
typedef struct {
volatile sh_uint32 spinlock;
sh_uint32 lapic_id;
} sh_SPIN_LOCK;
```
Two macros are provided to initialize an unlocked spinlock:
- `SH_LOCK()`: intended for spinlocks stored as global variables
- `SH_LOCK_LOCAL()`: intended for spinlocks stored as local variables or into structs
This spinlock implementation requires `sh_smp_gs_base()` to return a valid pointer to a CPU struct. It uses the atomics primitives provided by compilers. Spinlock operations provide full memory ordering guarantees.
Four functions are provided for spinlock manipulation:
- `sh_spin_lock(sh_SPIN_LOCK *lock)`: lock a spinlock, block until the lock is acquired. Return nothing
- `sh_spin_unlock(sh_SPIN_LOCK *lock)`: unlock a spinlock, return nothing
- `sh_spin_trylock(sh_SPIN_LOCK *lock)`: Attempt to acquire the lock without blocking., return `SH_TRUE` if successfull, `SH_FALSE` otherwise.
- `sh_spin_wholock(sh_SPIN_LOCK *lock)`: return the LAPIC id of the CPU locking the spinlock. Return `SH_UINT32_MAX` if the spinlock isn't owned by any CPU
Current implementation doesn't disable interrupts while holding locks.
## CPU count
SMP services can store the amount of CPU cores using the following functions:
- `sh_smp_set_cpu_count(sh_int16 cpu_count)`: set the count of CPU. It is only called one time by `sh_ap_prepare_for_smp_launch()`
- `sh_smp_get_cpu_count()`: return the count of CPU, return `-1` if value isn't initialized
## Memory barrier
The SMP services provide the following primitives:
Function name | Role
--------------|-----
`sh_mb()` | Full memory barrier
`sh_rmb()` | Read memory barrier
`sh_wmb()` | Write memory barrier
Current x86_64 implementation uses mfence/lfence/sfence.