theory StarForth_Mutex imports StarForth_Base begin (* ========================================================================= StarForth_Mutex — Mutex / lock-state model Mirrors: sf_mutex_t logic protecting tuning_lock and dict_lock in the VM. The VM has two locks: tuning_lock — guards physics-loop parameter updates (decay slope, window) dict_lock — guards dictionary writes (word definitions, SMUDGE, REVEAL) Modelled as first-class vm_state fields of type lock_state (defined in StarForth_Base as: LockFree | LockHeld nat). Safety property: mutual exclusion — at most one thread holds a lock. Since StarForth has exactly two threads (exec + heartbeat), thread IDs are 0 (ExecThread) and 1 (HeartbeatThread). ======================================================================== *) (* ========================================================================= Section 1: Thread identifiers ======================================================================== *) definition EXEC_THREAD :: nat where "EXEC_THREAD = 0" definition HEARTBEAT_THREAD :: nat where "HEARTBEAT_THREAD = 1" (* All valid thread IDs *) definition valid_thread :: "nat \ bool" where "valid_thread t \ t = EXEC_THREAD \ t = HEARTBEAT_THREAD" lemma threads_distinct: "EXEC_THREAD \ HEARTBEAT_THREAD" by (simp add: EXEC_THREAD_def HEARTBEAT_THREAD_def) (* ========================================================================= Section 2: Lock operations ======================================================================== *) (* acquire_lock t s: thread t acquires lock in state s. Precondition: lock is free (s = LockFree). Result: lock held by t. *) definition acquire_lock :: "nat \ lock_state \ lock_state" where "acquire_lock t s = (case s of LockFree \ LockHeld t | LockHeld h \ LockHeld h)" (* release_lock t s: thread t releases lock in state s. Precondition: lock held by t (s = LockHeld t). Result: lock free. *) definition release_lock :: "nat \ lock_state \ lock_state" where "release_lock t s = (case s of LockFree \ LockFree | LockHeld h \ (if h = t then LockFree else LockHeld h))" (* is_free, is_held predicates *) definition lock_free :: "lock_state \ bool" where "lock_free s \ s = LockFree" definition lock_held_by :: "nat \ lock_state \ bool" where "lock_held_by t s \ s = LockHeld t" (* ========================================================================= Section 3: Basic lock lemmas ======================================================================== *) lemma acquire_when_free: "acquire_lock t LockFree = LockHeld t" by (simp add: acquire_lock_def) lemma acquire_when_held_noop: "acquire_lock t (LockHeld h) = LockHeld h" by (simp add: acquire_lock_def) lemma release_own_lock: "release_lock t (LockHeld t) = LockFree" by (simp add: release_lock_def) lemma release_other_lock: assumes "h \ t" shows "release_lock t (LockHeld h) = LockHeld h" by (simp add: release_lock_def assms) lemma release_free_noop: "release_lock t LockFree = LockFree" by (simp add: release_lock_def) lemma acquire_then_release: "release_lock t (acquire_lock t LockFree) = LockFree" by (simp add: acquire_lock_def release_lock_def) (* ========================================================================= Section 4: Mutual exclusion — at most one holder ======================================================================== *) (* A lock is in a valid state: either free or held by exactly one thread. *) definition lock_wf :: "lock_state \ bool" where "lock_wf s \ (case s of LockFree \ True | LockHeld t \ valid_thread t)" lemma lock_wf_free [simp]: "lock_wf LockFree" by (simp add: lock_wf_def) lemma lock_wf_held: assumes "valid_thread t" shows "lock_wf (LockHeld t)" by (simp add: lock_wf_def assms) lemma acquire_preserves_wf: assumes "lock_wf s" "valid_thread t" shows "lock_wf (acquire_lock t s)" using assms by (cases s; simp add: acquire_lock_def lock_wf_def) lemma release_preserves_wf: assumes "lock_wf s" shows "lock_wf (release_lock t s)" using assms by (cases s; simp add: release_lock_def lock_wf_def) (* Two distinct threads cannot both hold the same lock. *) lemma mutex_exclusive: assumes "lock_held_by t s" "lock_held_by u s" shows "t = u" using assms by (cases s; simp add: lock_held_by_def) (* ========================================================================= Section 5: VM-level lock accessors ======================================================================== *) (* Acquire/release tuning_lock in the full vm_state record. *) definition vm_acquire_tuning :: "nat \ vm_state \ vm_state" where "vm_acquire_tuning t vm = vm\tuning_lock := acquire_lock t (tuning_lock vm)\" definition vm_release_tuning :: "nat \ vm_state \ vm_state" where "vm_release_tuning t vm = vm\tuning_lock := release_lock t (tuning_lock vm)\" (* Acquire/release dict_lock in the full vm_state record. *) definition vm_acquire_dict :: "nat \ vm_state \ vm_state" where "vm_acquire_dict t vm = vm\dict_lock := acquire_lock t (dict_lock vm)\" definition vm_release_dict :: "nat \ vm_state \ vm_state" where "vm_release_dict t vm = vm\dict_lock := release_lock t (dict_lock vm)\" (* Acquiring/releasing a lock does not change the data or return stacks. *) lemma acquire_tuning_ds [simp]: "data_stack (vm_acquire_tuning t vm) = data_stack vm" by (simp add: vm_acquire_tuning_def) lemma acquire_tuning_rs [simp]: "return_stack (vm_acquire_tuning t vm) = return_stack vm" by (simp add: vm_acquire_tuning_def) lemma release_tuning_ds [simp]: "data_stack (vm_release_tuning t vm) = data_stack vm" by (simp add: vm_release_tuning_def) lemma release_tuning_rs [simp]: "return_stack (vm_release_tuning t vm) = return_stack vm" by (simp add: vm_release_tuning_def) lemma acquire_dict_ds [simp]: "data_stack (vm_acquire_dict t vm) = data_stack vm" by (simp add: vm_acquire_dict_def) lemma acquire_dict_rs [simp]: "return_stack (vm_acquire_dict t vm) = return_stack vm" by (simp add: vm_acquire_dict_def) lemma release_dict_ds [simp]: "data_stack (vm_release_dict t vm) = data_stack vm" by (simp add: vm_release_dict_def) lemma release_dict_rs [simp]: "return_stack (vm_release_dict t vm) = return_stack vm" by (simp add: vm_release_dict_def) (* Acquire-then-release restores the tuning_lock to its original value (assuming the lock was free before acquisition). *) lemma tuning_lock_round_trip: assumes "tuning_lock vm = LockFree" shows "tuning_lock (vm_release_tuning t (vm_acquire_tuning t vm)) = LockFree" by (simp add: vm_acquire_tuning_def vm_release_tuning_def acquire_lock_def release_lock_def assms) (* ========================================================================= Section 6: Well-formedness of VM lock state ======================================================================== *) definition vm_locks_wf :: "vm_state \ bool" where "vm_locks_wf vm \ lock_wf (tuning_lock vm) \ lock_wf (dict_lock vm)" lemma vm_locks_wf_initial: assumes "tuning_lock vm = LockFree" assumes "dict_lock vm = LockFree" shows "vm_locks_wf vm" by (simp add: vm_locks_wf_def assms) end