diff --git a/src/common/input.rs b/src/common/input.rs
index 8335a6b..e1bb417 100644
--- a/src/common/input.rs
+++ b/src/common/input.rs
@@ -299,7 +299,7 @@ pub struct MappedInputs {
 }
 
 impl MappedInputs {
-    pub fn empty() -> MappedInputs {
+    pub const fn empty() -> MappedInputs {
         MappedInputs {
             buttons: Buttons::empty(),
             lstick_x: 0,
diff --git a/src/training/input_record.rs b/src/training/input_record.rs
index 34f4953..d7b7143 100644
--- a/src/training/input_record.rs
+++ b/src/training/input_record.rs
@@ -1,7 +1,5 @@
 use std::cmp::Ordering;
 
-use lazy_static::lazy_static;
-use parking_lot::Mutex;
 use skyline::nn::ui2d::ResColor;
 use smash::app::{lua_bind::*, utility, BattleObjectModuleAccessor};
 use smash::lib::lua_const::*;
@@ -22,7 +20,7 @@ use crate::{error, warn};
 
 use training_mod_sync::*;
 
-#[derive(PartialEq, Debug)]
+#[derive(PartialEq, Debug, Clone, Copy)]
 pub enum InputRecordState {
     None,
     Pause,
@@ -30,7 +28,7 @@ pub enum InputRecordState {
     Playback,
 }
 
-#[derive(PartialEq, Debug)]
+#[derive(PartialEq, Debug, Clone, Copy)]
 pub enum PossessionState {
     Player,
     Cpu,
@@ -58,30 +56,26 @@ pub const STICK_NEUTRAL: f32 = 0.2;
 pub const STICK_CLAMP_MULTIPLIER: f32 = 1.0 / 120.0; // 120.0 = CLAMP_MAX
 const FINAL_RECORD_MAX: usize = 600; // Maximum length for input recording sequences (capacity)
 const TOTAL_SLOT_COUNT: usize = 5; // Total number of input recording slots
-pub static mut INPUT_RECORD: InputRecordState = InputRecordState::None;
-pub static mut INPUT_RECORD_FRAME: usize = 0;
-pub static mut POSSESSION: PossessionState = PossessionState::Player;
-pub static mut LOCKOUT_FRAME: usize = 0;
-pub static mut BUFFER_FRAME: usize = 0;
-pub static mut RECORDED_LR: f32 = 1.0; // The direction the CPU was facing before the current recording was recorded
-pub static mut CURRENT_LR: f32 = 1.0; // The direction the CPU was facing at the beginning of this playback
-pub static mut STARTING_STATUS: i32 = 0; // The first status entered in the recording outside of waits
-                                         //     used to calculate if the input playback should begin before hitstun would normally end (hitstun cancel, monado art?)
-pub static mut CURRENT_RECORD_SLOT: usize = 0; // Which slot is being used for recording right now? Want to make sure this is synced with menu choices, maybe just use menu instead
-pub static mut CURRENT_PLAYBACK_SLOT: usize = 0; // Which slot is being used for playback right now?
-pub static mut CURRENT_FRAME_LENGTH: usize = 60;
-
-lazy_static! {
-    static ref P1_FINAL_MAPPING: Mutex<[[MappedInputs; FINAL_RECORD_MAX]; TOTAL_SLOT_COUNT]> =
-        Mutex::new([[{ MappedInputs::empty() }; FINAL_RECORD_MAX]; TOTAL_SLOT_COUNT]);
-    static ref P1_FRAME_LENGTH_MAPPING: Mutex<[usize; TOTAL_SLOT_COUNT]> =
-        Mutex::new([60usize; TOTAL_SLOT_COUNT]);
-    static ref P1_STARTING_STATUSES: Mutex<[StartingStatus; TOTAL_SLOT_COUNT]> =
-        Mutex::new([{ StartingStatus::Other }; TOTAL_SLOT_COUNT]);
-}
+pub static INPUT_RECORD: RwLock<InputRecordState> = RwLock::new(InputRecordState::None);
+pub static INPUT_RECORD_FRAME: RwLock<usize> = RwLock::new(0);
+pub static POSSESSION: RwLock<PossessionState> = RwLock::new(PossessionState::Player);
+pub static LOCKOUT_FRAME: RwLock<usize> = RwLock::new(0);
+pub static BUFFER_FRAME: RwLock<usize> = RwLock::new(0);
+pub static RECORDED_LR: RwLock<f32> = RwLock::new(1.0); // The direction the CPU was facing before the current recording was recorded
+pub static CURRENT_LR: RwLock<f32> = RwLock::new(1.0); // The direction the CPU was facing at the beginning of this playback
+pub static STARTING_STATUS: RwLock<i32> = RwLock::new(0); // The first status entered in the recording outside of waits
+                                                          //     used to calculate if the input playback should begin before hitstun would normally end (hitstun cancel, monado art?)
+pub static CURRENT_RECORD_SLOT: RwLock<usize> = RwLock::new(0); // Which slot is being used for recording right now? Want to make sure this is synced with menu choices, maybe just use menu instead
+pub static CURRENT_PLAYBACK_SLOT: RwLock<usize> = RwLock::new(0); // Which slot is being used for playback right now?
+pub static CURRENT_FRAME_LENGTH: RwLock<usize> = RwLock::new(60);
+pub static P1_FINAL_MAPPING: RwLock<[[MappedInputs; FINAL_RECORD_MAX]; TOTAL_SLOT_COUNT]> =
+    RwLock::new([[{ MappedInputs::empty() }; FINAL_RECORD_MAX]; TOTAL_SLOT_COUNT]);
+pub static P1_FRAME_LENGTH_MAPPING: RwLock<[usize; TOTAL_SLOT_COUNT]> =
+    RwLock::new([60; TOTAL_SLOT_COUNT]);
+// pub static P1_STARTING_STATUSES: RwLock<[StartingStatus; TOTAL_SLOT_COUNT]> = RwLock::new([StartingStatus::Other; TOTAL_SLOT_COUNT]); // TODO! Not used currently
 
 unsafe fn can_transition(module_accessor: *mut BattleObjectModuleAccessor) -> bool {
-    let transition_term = into_transition_term(into_starting_status(STARTING_STATUS));
+    let transition_term = into_transition_term(into_starting_status(read_rwlock(&STARTING_STATUS)));
     WorkModule::is_enable_transition_term(module_accessor, transition_term)
 }
 
@@ -196,7 +190,10 @@ unsafe fn handle_recording_for_fighter(module_accessor: &mut BattleObjectModuleA
     let fighter_kind = utility::get_kind(module_accessor);
     let fighter_is_nana = fighter_kind == *FIGHTER_KIND_NANA;
 
-    CURRENT_RECORD_SLOT = get(&MENU).recording_slot.into_idx().unwrap_or(0);
+    assign_rwlock(
+        &CURRENT_RECORD_SLOT,
+        get(&MENU).recording_slot.into_idx().unwrap_or(0),
+    );
 
     if entry_id_int == 0 && !fighter_is_nana {
         if button_config::combo_passes(button_config::ButtonCombo::InputPlayback) {
@@ -206,44 +203,51 @@ unsafe fn handle_recording_for_fighter(module_accessor: &mut BattleObjectModuleA
         {
             lockout_record();
         }
-        if INPUT_RECORD == None {
+        let input_record = read_rwlock(&INPUT_RECORD);
+        if input_record == None {
             clear_notifications_except("Input Recording");
         }
         // Handle recording end
-        if (INPUT_RECORD == Record || INPUT_RECORD == Playback)
-            && INPUT_RECORD_FRAME >= CURRENT_FRAME_LENGTH - 1
+        let mut input_record_frame = lock_write_rwlock(&INPUT_RECORD_FRAME);
+        if (input_record == Record || input_record == Playback)
+            && *input_record_frame >= read_rwlock(&CURRENT_FRAME_LENGTH) - 1
         {
-            POSSESSION = Player;
+            assign_rwlock(&POSSESSION, Player);
             if mash::is_playback_queued() {
                 mash::reset();
             }
 
             // If we need to crop the recording for neutral input
             // INPUT_RECORD_FRAME must be > 0 to prevent bounding errors
-            if INPUT_RECORD == Record
+            if input_record == Record
                 && get(&MENU).recording_crop == OnOff::ON
-                && INPUT_RECORD_FRAME > 0
+                && *input_record_frame > 0
             {
-                while INPUT_RECORD_FRAME > 0 && is_input_neutral(INPUT_RECORD_FRAME - 1) {
+                while *input_record_frame > 0 && is_input_neutral(*input_record_frame - 1) {
                     // Discard frames at the end of the recording until the last frame with input
-                    INPUT_RECORD_FRAME -= 1;
+                    *input_record_frame -= 1;
                 }
-                CURRENT_FRAME_LENGTH = INPUT_RECORD_FRAME;
-                P1_FRAME_LENGTH_MAPPING.lock()[CURRENT_RECORD_SLOT] = CURRENT_FRAME_LENGTH;
+                assign_rwlock(&CURRENT_FRAME_LENGTH, *input_record_frame);
+                let mut p1_frame_length_mapping = lock_write_rwlock(&P1_FRAME_LENGTH_MAPPING);
+                (*p1_frame_length_mapping)[read_rwlock(&CURRENT_RECORD_SLOT)] = *input_record_frame;
+                drop(p1_frame_length_mapping);
             }
 
-            INPUT_RECORD_FRAME = 0;
+            *input_record_frame = 0;
 
-            if get(&MENU).playback_loop == OnOff::ON && INPUT_RECORD == Playback {
-                playback(Some(CURRENT_PLAYBACK_SLOT));
+            if get(&MENU).playback_loop == OnOff::ON && input_record == Playback {
+                let playback_slot = read_rwlock(&CURRENT_PLAYBACK_SLOT);
+                playback(Some(playback_slot));
             } else {
-                INPUT_RECORD = None;
+                assign_rwlock(&INPUT_RECORD, None);
             }
         }
+        drop(input_record_frame);
     }
 
     // Handle Possession Coloring
-    if entry_id_int == 1 && POSSESSION == Lockout {
+    let possession = read_rwlock(&POSSESSION);
+    if entry_id_int == 1 && possession == Lockout {
         clear_notifications_except("Input Recording");
         color_notification(
             "Input Recording".to_string(),
@@ -263,7 +267,7 @@ unsafe fn handle_recording_for_fighter(module_accessor: &mut BattleObjectModuleA
             1.0,
             *MODEL_COLOR_TYPE_COLOR_BLEND,
         );
-    } else if entry_id_int == 1 && POSSESSION == Standby {
+    } else if entry_id_int == 1 && possession == Standby {
         clear_notifications_except("Input Recording");
         color_notification(
             "Input Recording".to_string(),
@@ -283,7 +287,7 @@ unsafe fn handle_recording_for_fighter(module_accessor: &mut BattleObjectModuleA
             1.0,
             *MODEL_COLOR_TYPE_COLOR_BLEND,
         );
-    } else if entry_id_int == 1 && POSSESSION == Cpu {
+    } else if entry_id_int == 1 && possession == Cpu {
         clear_notifications_except("Input Recording");
         color_notification(
             "Input Recording".to_string(),
@@ -303,15 +307,17 @@ unsafe fn handle_recording_for_fighter(module_accessor: &mut BattleObjectModuleA
             0.0,
             *MODEL_COLOR_TYPE_COLOR_BLEND,
         );
-    } else if entry_id_int == 1 && POSSESSION == Player && INPUT_RECORD == Playback {
+    } else if entry_id_int == 1 && possession == Player && read_rwlock(&INPUT_RECORD) == Playback {
+        // Need to re-read INPUT_RECORD instead of using the local variable because we might have assigned to it early
         // Displays if the inputs from the current frame were a result of playback
-        if INPUT_RECORD_FRAME == 0 || INPUT_RECORD_FRAME == 1 {
+        let input_record_frame = read_rwlock(&INPUT_RECORD_FRAME);
+        if input_record_frame == 0 || input_record_frame == 1 {
             // can be either, seems like a thread issue
             clear_notifications_except("Input Recording");
             color_notification(
                 "Input Recording".to_string(),
                 "Playback".to_owned(),
-                CURRENT_FRAME_LENGTH as u32,
+                read_rwlock(&CURRENT_FRAME_LENGTH) as u32,
                 ResColor {
                     r: 0,
                     g: 0,
@@ -324,27 +330,29 @@ unsafe fn handle_recording_for_fighter(module_accessor: &mut BattleObjectModuleA
 }
 
 pub unsafe fn lockout_record() {
-    INPUT_RECORD = Pause;
-    INPUT_RECORD_FRAME = 0;
-    POSSESSION = Lockout;
-    P1_FINAL_MAPPING.lock()[CURRENT_RECORD_SLOT]
-        .iter_mut()
-        .for_each(|mapped_input| {
-            *mapped_input = MappedInputs::empty();
-        });
-    CURRENT_FRAME_LENGTH = get(&MENU).recording_duration.into_frames();
-    P1_FRAME_LENGTH_MAPPING.lock()[CURRENT_RECORD_SLOT] = CURRENT_FRAME_LENGTH;
-    LOCKOUT_FRAME = 30; // This needs to be this high or issues occur dropping shield - but does this cause problems when trying to record ledge?
-    BUFFER_FRAME = 0;
-    // Store the direction the CPU is facing when we initially record, so we can turn their inputs around if needed
     let cpu_module_accessor = get_module_accessor(FighterId::CPU);
-    RECORDED_LR = PostureModule::lr(cpu_module_accessor);
-    CURRENT_LR = RECORDED_LR;
+    let recording_duration = get(&MENU).recording_duration.into_frames();
+    let current_record_slot = read_rwlock(&CURRENT_RECORD_SLOT);
+    let mut p1_final_mapping = lock_write_rwlock(&P1_FINAL_MAPPING);
+    (*p1_final_mapping)[current_record_slot] = [{ MappedInputs::empty() }; FINAL_RECORD_MAX];
+    drop(p1_final_mapping);
+    let mut p1_frame_length_mapping = lock_write_rwlock(&P1_FRAME_LENGTH_MAPPING);
+    (*p1_frame_length_mapping)[current_record_slot] = recording_duration;
+    drop(p1_frame_length_mapping);
+    assign_rwlock(&CURRENT_FRAME_LENGTH, recording_duration);
+    assign_rwlock(&INPUT_RECORD, Pause);
+    assign_rwlock(&INPUT_RECORD_FRAME, 0);
+    assign_rwlock(&POSSESSION, Lockout);
+    assign_rwlock(&LOCKOUT_FRAME, 30); // This needs to be this high or issues occur dropping shield - but does this cause problems when trying to record ledge?
+    assign_rwlock(&BUFFER_FRAME, 0);
+    // Store the direction the CPU is facing when we initially record, so we can turn their inputs around if needed
+    assign_rwlock(&RECORDED_LR, PostureModule::lr(cpu_module_accessor));
+    assign_rwlock(&CURRENT_LR, PostureModule::lr(cpu_module_accessor));
 }
 
 // Returns whether we did playback
 pub unsafe fn playback(slot: Option<usize>) -> bool {
-    if INPUT_RECORD == Pause {
+    if read_rwlock(&INPUT_RECORD) == Pause {
         warn!("Tried to playback during lockout!");
         return false;
     }
@@ -353,15 +361,15 @@ pub unsafe fn playback(slot: Option<usize>) -> bool {
         return false;
     }
     let slot = slot.unwrap();
-
-    CURRENT_PLAYBACK_SLOT = slot;
-    CURRENT_FRAME_LENGTH = P1_FRAME_LENGTH_MAPPING.lock()[CURRENT_PLAYBACK_SLOT];
-    INPUT_RECORD = Playback;
-    POSSESSION = Player;
-    INPUT_RECORD_FRAME = 0;
-    BUFFER_FRAME = 0;
     let cpu_module_accessor = get_module_accessor(FighterId::CPU);
-    CURRENT_LR = PostureModule::lr(cpu_module_accessor);
+    let frame_length = read_rwlock(&P1_FRAME_LENGTH_MAPPING)[slot];
+    assign_rwlock(&CURRENT_FRAME_LENGTH, frame_length);
+    assign_rwlock(&CURRENT_PLAYBACK_SLOT, slot);
+    assign_rwlock(&INPUT_RECORD, Playback);
+    assign_rwlock(&POSSESSION, Player);
+    assign_rwlock(&INPUT_RECORD_FRAME, 0);
+    assign_rwlock(&BUFFER_FRAME, 0);
+    assign_rwlock(&CURRENT_LR, PostureModule::lr(cpu_module_accessor));
 
     true
 }
@@ -369,26 +377,28 @@ pub unsafe fn playback(slot: Option<usize>) -> bool {
 pub unsafe fn playback_ledge(slot: Option<usize>) {
     let did_playback = playback(slot);
     if did_playback {
-        BUFFER_FRAME = 5; // So we can make sure the option is buffered and won't get ledge trumped if delay is 0
-                          // drop down from ledge can't be buffered on the same frame as jump/attack/roll/ngu so we have to do this
-                          // Need to buffer 1 less frame for non-lassos
+        let mut buffer_frame = lock_write_rwlock(&BUFFER_FRAME);
+        *buffer_frame = 5; // So we can make sure the option is buffered and won't get ledge trumped if delay is 0
+                           // drop down from ledge can't be buffered on the same frame as jump/attack/roll/ngu so we have to do this
+                           // Need to buffer 1 less frame for non-lassos
         let cpu_module_accessor = get_module_accessor(FighterId::CPU);
         let status_kind = StatusModule::status_kind(cpu_module_accessor);
         if status_kind == *FIGHTER_STATUS_KIND_CLIFF_CATCH {
-            BUFFER_FRAME -= 1;
+            *buffer_frame -= 1;
         }
     }
 }
 
 pub unsafe fn stop_playback() {
-    INPUT_RECORD = None;
-    INPUT_RECORD_FRAME = 0;
-    POSSESSION = Player;
+    assign_rwlock(&INPUT_RECORD, None);
+    assign_rwlock(&INPUT_RECORD_FRAME, 0);
+    assign_rwlock(&POSSESSION, Player);
 }
 
 pub unsafe fn is_input_neutral(input_frame: usize) -> bool {
     // Returns whether we should be done with standby this frame (if any significant controller input has been made)
-    let frame_input = P1_FINAL_MAPPING.lock()[CURRENT_RECORD_SLOT][input_frame];
+    let current_record_slot = read_rwlock(&CURRENT_RECORD_SLOT);
+    let frame_input = read_rwlock(&P1_FINAL_MAPPING)[current_record_slot][input_frame];
 
     let clamped_lstick_x =
         ((frame_input.lstick_x as f32) * STICK_CLAMP_MULTIPLIER).clamp(-1.0, 1.0);
@@ -410,31 +420,40 @@ pub unsafe fn is_input_neutral(input_frame: usize) -> bool {
 }
 
 pub unsafe fn handle_final_input_mapping(player_idx: i32, out: *mut MappedInputs) {
+    let mut possession = lock_write_rwlock(&POSSESSION);
     if player_idx == 0 {
         // if player 1
-        if INPUT_RECORD == Record {
+        if read_rwlock(&INPUT_RECORD) == Record {
+            let mut input_record_frame = lock_write_rwlock(&INPUT_RECORD_FRAME);
             // check for standby before starting action:
-            if POSSESSION == Standby && !is_input_neutral(0) {
+            if *possession == Standby && !is_input_neutral(0) {
                 // last input made us start an action, so start recording and end standby.
-                INPUT_RECORD_FRAME += 1;
-                POSSESSION = Cpu;
+                *input_record_frame += 1;
+                *possession = Cpu;
             }
 
-            if INPUT_RECORD_FRAME == 1 {
+            if *input_record_frame == 1 {
                 // We're on the second frame of recording, grabbing the status should give us the status that resulted from the first frame of input
                 // We'll want to save this status so that we use the correct TRANSITION TERM for hitstun cancelling out of damage fly
                 let cpu_module_accessor = get_module_accessor(FighterId::CPU);
-                P1_STARTING_STATUSES.lock()[CURRENT_PLAYBACK_SLOT] =
-                    into_starting_status(StatusModule::status_kind(cpu_module_accessor));
-                STARTING_STATUS = StatusModule::status_kind(cpu_module_accessor);
+                assign_rwlock(
+                    &STARTING_STATUS,
+                    StatusModule::status_kind(cpu_module_accessor),
+                );
                 // TODO: Handle this based on slot later instead
+                // let p1_starting_statuses = lock_write_rwlock(&P1_STARTING_STATUSES);
+                // (*p1_starting_statuses)[read_rwlock(&CURRENT_PLAYBACK_SLOT)] =
+                //     into_starting_status(StatusModule::status_kind(cpu_module_accessor));
+                // drop(p1_starting_statuses);
             }
-
-            P1_FINAL_MAPPING.lock()[CURRENT_RECORD_SLOT][INPUT_RECORD_FRAME] = *out;
+            let mut p1_final_mapping = lock_write_rwlock(&P1_FINAL_MAPPING);
+            let current_record_slot = read_rwlock(&CURRENT_RECORD_SLOT);
+            (*p1_final_mapping)[current_record_slot][*input_record_frame] = *out;
+            drop(p1_final_mapping);
             *out = MappedInputs::empty(); // don't control player while recording
         }
         // Don't allow for player input during Lockout
-        if POSSESSION == Lockout {
+        if *possession == Lockout {
             *out = MappedInputs::empty();
         }
     }
@@ -454,7 +473,7 @@ unsafe fn set_cpu_controls(p_data: *mut *mut u8) {
     // TODO: Setup STARTING_STATUS based on current playback slot here
 
     // This check prevents out of shield if mash exiting is on
-    if INPUT_RECORD == None {
+    if read_rwlock(&INPUT_RECORD) == None {
         should_mash_playback();
     }
 
@@ -466,20 +485,22 @@ unsafe fn set_cpu_controls(p_data: *mut *mut u8) {
     }
     let cpu_module_accessor = cpu_module_accessor.unwrap();
 
-    if INPUT_RECORD == Pause {
-        match LOCKOUT_FRAME.cmp(&0) {
-            Ordering::Greater => LOCKOUT_FRAME -= 1,
+    if read_rwlock(&INPUT_RECORD) == Pause {
+        let lockout_frame = read_rwlock(&LOCKOUT_FRAME);
+        match lockout_frame.cmp(&0) {
+            Ordering::Greater => assign_rwlock(&LOCKOUT_FRAME, lockout_frame - 1),
             Ordering::Equal => {
-                INPUT_RECORD = Record;
-                POSSESSION = Standby;
+                assign_rwlock(&INPUT_RECORD, Record);
+                assign_rwlock(&POSSESSION, Standby);
             }
             Ordering::Less => error!("LOCKOUT_FRAME OUT OF BOUNDS"),
         }
     }
 
-    if INPUT_RECORD == Record || INPUT_RECORD == Playback {
+    let input_record = read_rwlock(&INPUT_RECORD);
+    if input_record == Record || input_record == Playback {
         // if we aren't facing the way we were when we initially recorded, we reverse horizontal inputs
-        let mut x_input_multiplier = RECORDED_LR * CURRENT_LR;
+        let mut x_input_multiplier = read_rwlock(&RECORDED_LR) * read_rwlock(&CURRENT_LR);
         // Don't flip Shulk's dial inputs
         let fighter_kind = utility::get_kind(&mut *cpu_module_accessor);
         if fighter_kind == *FIGHTER_KIND_SHULK {
@@ -509,13 +530,17 @@ unsafe fn set_cpu_controls(p_data: *mut *mut u8) {
             );
         }
 
-        let mut saved_mapped_inputs = P1_FINAL_MAPPING.lock()[if INPUT_RECORD == Record {
-            CURRENT_RECORD_SLOT
+        let mut input_record_frame = lock_write_rwlock(&INPUT_RECORD_FRAME);
+        let slot = if input_record == Record {
+            read_rwlock(&CURRENT_RECORD_SLOT)
         } else {
-            CURRENT_PLAYBACK_SLOT
-        }][INPUT_RECORD_FRAME];
-
-        if BUFFER_FRAME <= 3 && BUFFER_FRAME > 0 {
+            read_rwlock(&CURRENT_PLAYBACK_SLOT)
+        };
+        // TODO! I think something is wrong here, clippy says p1_final_mapping doesn't need to be mutable but we're definitely modifying its contents?
+        let mut p1_final_mapping = lock_write_rwlock(&P1_FINAL_MAPPING);
+        let mut saved_mapped_inputs = (*p1_final_mapping)[slot][*input_record_frame];
+        let mut buffer_frame = lock_write_rwlock(&BUFFER_FRAME);
+        if (0 < *buffer_frame) && (*buffer_frame <= 3) {
             // Our option is already buffered, now we need to 0 out inputs to make sure our future controls act like flicks/presses instead of holding the button
             saved_mapped_inputs = MappedInputs::empty();
         }
@@ -544,24 +569,28 @@ unsafe fn set_cpu_controls(p_data: *mut *mut u8) {
 
         // Keep counting frames, unless we're in standby waiting for an input, or are buffering an option
         // When buffering an option, we keep inputting the first frame of input during the buffer window
-        if BUFFER_FRAME > 0 {
-            BUFFER_FRAME -= 1;
-        } else if INPUT_RECORD_FRAME < CURRENT_FRAME_LENGTH - 1 && POSSESSION != Standby {
-            INPUT_RECORD_FRAME += 1;
+        if *buffer_frame > 0 {
+            *buffer_frame -= 1;
+        } else if *input_record_frame < read_rwlock(&CURRENT_FRAME_LENGTH) - 1
+            && read_rwlock(&POSSESSION) != Standby
+        {
+            *input_record_frame += 1;
         }
     }
 }
 
-pub unsafe fn is_playback() -> bool {
-    INPUT_RECORD == Record || INPUT_RECORD == Playback
+pub fn is_playback() -> bool {
+    let input_record = read_rwlock(&INPUT_RECORD);
+    input_record == Record || input_record == Playback
 }
 
-pub unsafe fn is_recording() -> bool {
-    INPUT_RECORD == Record
+pub fn is_recording() -> bool {
+    read_rwlock(&INPUT_RECORD) == Record
 }
 
 pub unsafe fn is_standby() -> bool {
-    POSSESSION == Standby || POSSESSION == Lockout
+    let possession = read_rwlock(&POSSESSION);
+    possession == Standby || possession == Lockout
 }
 
 extern "C" {