Stage MC-0b: real kernel spinlocks; sf_mutex no longer a no-op (FABRIC-3.10.8 §3.2)
- New spinlock primitive (spinlock.h/.c): CAS on an owner word (core+1), interrupts masked while any lock is held (state kept in the per-core block, so release order doesn't matter). Recursion, release-not-held, held-at-switch and destroyed-while-held are counted and logged, never silent. Locks are no-ops until the boot core's block is installed (riscv64's monolithic early boot prints before sk_percpu_boot_init()). - Kernel locks in a documented order: hermes, switch, registry, doe, log, console, heap, vmm, pmm. sf_mutex (dict_lock/tuning_lock) uses the same lock word. - Hermes: public functions over *_locked internals; never held across the drain's vm_interpret_kind(); switch notifications after dropping the lock; event payload moved off static storage. Switch table and registry never call out while held (slot/entry copied under the lock). - No lock crosses a switch: checked at context switch (leave, resume) and the idle point. - Probe (removed): every lock balances on all three ISAs; 0 held at switch over 7.5M-51M checks; 0 recursions, 0 bad releases. - Standard sequence on amd64/aarch64/riscv64: hashes and G byte-identical to MC-0a, MINT/WIREBIND/USE ok, conservation true, 0 idle growth. - Block subsystem split out as MC-0b2 (Captain Bob's ruling). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
8409e376cf
commit
5bc7b4dee7
@@ -49,6 +49,14 @@ typedef struct sk_percpu {
|
||||
struct sk_percpu *self; /* must stay first: amd64 reads it as %gs:0 */
|
||||
uint32_t core_id; /* 0 = the boot core (the system core, MC-R1) */
|
||||
struct VM *current_vm; /* who is running on this core (switch.c) */
|
||||
/* MC-0b (spinlock.c): locks this core holds right now, and the
|
||||
* interrupt state to restore when that count returns to 0. Kept here,
|
||||
* not in each lock, so interrupts come back correctly whatever order
|
||||
* the locks are released in. */
|
||||
uint32_t lock_depth;
|
||||
uint64_t saved_irq;
|
||||
uint64_t lock_acquired; /* every acquire on this core, ever */
|
||||
uint64_t lock_released; /* every release on this core, ever */
|
||||
} sk_percpu_t;
|
||||
|
||||
/* Installs the boot core's block in this core's per-CPU register. Call
|
||||
@@ -56,6 +64,14 @@ typedef struct sk_percpu {
|
||||
* arch_early_init(): on amd64 that reloads GS, which would reset the base). */
|
||||
void sk_percpu_boot_init(void);
|
||||
|
||||
/* 1 once the boot core's block is installed (MC-0b). Before that the
|
||||
* per-CPU register still holds whatever the firmware left there -- on
|
||||
* riscv64 the monolithic loader's kernel_main() prints from
|
||||
* arch_early_init() with tp still the firmware's -- so the spinlocks
|
||||
* (spinlock.c) do nothing until it is set: early boot is one core with
|
||||
* interrupts off. */
|
||||
extern volatile int sk_percpu_ready;
|
||||
|
||||
/* This core's block. Valid from sk_percpu_boot_init() on. */
|
||||
static inline sk_percpu_t *sk_percpu(void)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user