2.2 KiB
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 theIA32_GS_BASEMSR. with a value, return nothingsh_smp_gs_base(): take no argument and return ash_ap_CPU_STRUCT*
Spinlocks
The SMP services provide a basic implementation for a spinlock, which look like this:
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 variablesSH_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 nothingsh_spin_unlock(sh_SPIN_LOCK *lock): unlock a spinlock, return nothingsh_spin_trylock(sh_SPIN_LOCK *lock): Attempt to acquire the lock without blocking., returnSH_TRUEif successfull,SH_FALSEotherwise.sh_spin_wholock(sh_SPIN_LOCK *lock): return the LAPIC id of the CPU locking the spinlock. ReturnSH_UINT32_MAXif 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 bysh_ap_prepare_for_smp_launch()sh_smp_get_cpu_count(): return the count of CPU, return-1if 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.