FABRIC-3.10.8 K-11: check the lock order at run time
Every lock carries a rank (hermes < switch < registry < VM dict_lock < VM tuning_lock < stadium < slot < doe < log < block < console < heap < vmm < pmm); each core counts held locks per rank and an acquisition not above the highest held rank counts an order violation, reported in full at the idle point. Probe inversion reported exactly once; O-A, a 28-VM churn and the standard sequence show 0 violations on all three ISAs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
a66c4f3d5e
commit
7252e2ed72
@@ -38,7 +38,8 @@
|
||||
* on the same core, so it is never treated as legitimate. The call is
|
||||
* let through (spinning would hang the core) and counted;
|
||||
* - bad release: releasing a lock this core doesn't hold;
|
||||
* - held at switch: a switch or idle point reached with a lock held.
|
||||
* - held at switch: a switch or idle point reached with a lock held;
|
||||
* - order violation: see the rank check below.
|
||||
*
|
||||
* sf_mutex_t (the vendored VM's dict_lock/tuning_lock) uses the same lock
|
||||
* word through sk_lockword_acquire()/sk_lockword_release() (shim.c).
|
||||
@@ -72,22 +73,50 @@
|
||||
* decays cells) and below a VM's dict_lock (vm_core.c's heat bump dispatches
|
||||
* the word under it), and above block (MIGRATE calls blk_flush()); nothing
|
||||
* in the block path calls into Stadium.
|
||||
*
|
||||
* The order is checked at run time (FABRIC-3.10.8 K-11): every lock has a
|
||||
* rank (sk_lock_rank_t, same order as above, with a VM's dict_lock and
|
||||
* tuning_lock between the registry and Stadium), each core counts the
|
||||
* locks it holds per rank, and taking a lock whose rank is not above every
|
||||
* rank this core already holds counts an order violation. Two locks of one
|
||||
* rank (two Stadium slots, two VMs' dict_locks) count as one too. Counted
|
||||
* and logged like the other failures; never refused.
|
||||
*/
|
||||
#ifndef STARKERNEL_SPINLOCK_H
|
||||
#define STARKERNEL_SPINLOCK_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum sk_lock_rank {
|
||||
SK_LOCK_RANK_NONE = 0, /* unranked: neither checked nor counted */
|
||||
SK_LOCK_RANK_HERMES,
|
||||
SK_LOCK_RANK_SWITCH,
|
||||
SK_LOCK_RANK_REGISTRY,
|
||||
SK_LOCK_RANK_VM_DICT, /* a VM's dict_lock (sf_mutex_t) */
|
||||
SK_LOCK_RANK_VM_TUNING, /* a VM's tuning_lock (sf_mutex_t) */
|
||||
SK_LOCK_RANK_STADIUM,
|
||||
SK_LOCK_RANK_STADIUM_SLOT,
|
||||
SK_LOCK_RANK_DOE,
|
||||
SK_LOCK_RANK_LOG,
|
||||
SK_LOCK_RANK_BLOCK,
|
||||
SK_LOCK_RANK_CONSOLE,
|
||||
SK_LOCK_RANK_HEAP,
|
||||
SK_LOCK_RANK_VMM,
|
||||
SK_LOCK_RANK_PMM,
|
||||
SK_LOCK_RANK_COUNT
|
||||
} sk_lock_rank_t;
|
||||
|
||||
typedef struct sk_spinlock {
|
||||
volatile uint32_t owner; /* 0 = free, else core_id + 1 */
|
||||
uint64_t acquired; /* updated while held, so exact */
|
||||
uint64_t released;
|
||||
uint32_t rank; /* sk_lock_rank_t */
|
||||
} sk_spinlock_t;
|
||||
|
||||
#define SK_SPINLOCK_INIT { 0, 0, 0 }
|
||||
#define SK_SPINLOCK_INIT(rank) { 0, 0, 0, (rank) }
|
||||
|
||||
void sk_lockword_acquire(volatile uint32_t *word);
|
||||
void sk_lockword_release(volatile uint32_t *word);
|
||||
void sk_lockword_acquire(volatile uint32_t *word, uint32_t rank);
|
||||
void sk_lockword_release(volatile uint32_t *word, uint32_t rank);
|
||||
|
||||
void sk_spin_lock(sk_spinlock_t *l);
|
||||
void sk_spin_unlock(sk_spinlock_t *l);
|
||||
@@ -107,6 +136,7 @@ void sk_lock_report(void);
|
||||
uint64_t sk_lock_recursions(void);
|
||||
uint64_t sk_lock_bad_releases(void);
|
||||
uint64_t sk_lock_held_at_switch(void);
|
||||
uint64_t sk_lock_order_violations(void);
|
||||
|
||||
extern sk_spinlock_t g_lock_registry;
|
||||
extern sk_spinlock_t g_lock_stadium;
|
||||
|
||||
Reference in New Issue
Block a user