Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Core] Use a mutex guard for split shared memory #16647

Merged
merged 1 commit into from
Apr 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 20 additions & 9 deletions platforms/chibios/drivers/serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "quantum.h"
#include "serial.h"
#include "wait.h"
#include "synchronization_util.h"

#include <hal.h>

Expand Down Expand Up @@ -86,7 +87,10 @@ static THD_FUNCTION(Thread1, arg) {
chRegSetThreadName("blinker");
while (true) {
palWaitLineTimeout(SOFT_SERIAL_PIN, TIME_INFINITE);

split_shared_memory_lock();
interrupt_handler(NULL);
split_shared_memory_unlock();
}
}

Expand Down Expand Up @@ -204,14 +208,9 @@ void interrupt_handler(void *arg) {
chSysUnlockFromISR();
}

/////////
// start transaction by initiator
//
// bool soft_serial_transaction(int sstd_index)
//
// this code is very time dependent, so we need to disable interrupts
bool soft_serial_transaction(int sstd_index) {
static inline bool initiate_transaction(uint8_t sstd_index) {
if (sstd_index > NUM_TOTAL_TRANSACTIONS) return false;

split_transaction_desc_t *trans = &split_transaction_table[sstd_index];

// TODO: remove extra delay between transactions
Expand All @@ -238,8 +237,7 @@ bool soft_serial_transaction(int sstd_index) {
return false;
}

// if the slave is present syncronize with it

// if the slave is present synchronize with it
uint8_t checksum = 0;
// send data to the slave
serial_write_byte(sstd_index); // first chunk is transaction id
Expand Down Expand Up @@ -285,3 +283,16 @@ bool soft_serial_transaction(int sstd_index) {
chSysUnlock();
return true;
}

/////////
// start transaction by initiator
//
// bool soft_serial_transaction(int sstd_index)
//
// this code is very time dependent, so we need to disable interrupts
bool soft_serial_transaction(int sstd_index) {
split_shared_memory_lock();
bool result = initiate_transaction((uint8_t)sstd_index);
split_shared_memory_unlock();
return result;
}
10 changes: 9 additions & 1 deletion platforms/chibios/drivers/serial_usart.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

#include "serial_usart.h"
#include "synchronization_util.h"

#if defined(SERIAL_USART_CONFIG)
static SerialConfig serial_config = SERIAL_USART_CONFIG;
Expand Down Expand Up @@ -173,6 +174,7 @@ static THD_FUNCTION(SlaveThread, arg) {
* Parts of failed transactions or spurious bytes could still be in it. */
usart_clear();
}
split_shared_memory_unlock();
}
}

Expand Down Expand Up @@ -200,6 +202,7 @@ static inline bool react_to_transactions(void) {
return false;
}

split_shared_memory_lock();
split_transaction_desc_t* trans = &split_transaction_table[sstd_index];

/* Send back the handshake which is XORed as a simple checksum,
Expand Down Expand Up @@ -254,7 +257,12 @@ bool soft_serial_transaction(int index) {
/* Clear the receive queue, to start with a clean slate.
* Parts of failed transactions or spurious bytes could still be in it. */
usart_clear();
return initiate_transaction((uint8_t)index);

split_shared_memory_lock();
bool result = initiate_transaction((uint8_t)index);
split_shared_memory_unlock();

return result;
}

/**
Expand Down
6 changes: 5 additions & 1 deletion platforms/chibios/platform.mk
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,8 @@ PLATFORM_SRC = \
$(STREAMSSRC) \
$(CHIBIOS)/os/various/syscalls.c \
$(PLATFORM_COMMON_DIR)/syscall-fallbacks.c \
$(PLATFORM_COMMON_DIR)/wait.c
$(PLATFORM_COMMON_DIR)/wait.c \
$(PLATFORM_COMMON_DIR)/synchronization_util.c

# Ensure the ASM files are not subjected to LTO -- it'll strip out interrupt handlers otherwise.
QUANTUM_LIB_SRC += $(STARTUPASM) $(PORTASM) $(OSALASM) $(PLATFORMASM)
Expand Down Expand Up @@ -420,6 +421,9 @@ LDFLAGS += $(SHARED_LDFLAGS) $(SHARED_LDSYMBOLS) $(TOOLCHAIN_LDFLAGS) $(TOOLCHA
# Tell QMK that we are hosting it on ChibiOS.
OPT_DEFS += -DPROTOCOL_CHIBIOS

# ChibiOS supports synchronization primitives like a Mutex
OPT_DEFS += -DPLATFORM_SUPPORTS_SYNCHRONIZATION

# Workaround to stop ChibiOS from complaining about new GCC -- it's been fixed for 7/8/9 already
OPT_DEFS += -DPORT_IGNORE_GCC_VERSION_CHECK=1

Expand Down
26 changes: 26 additions & 0 deletions platforms/chibios/synchronization_util.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2022 Stefan Kerkmann
// SPDX-License-Identifier: GPL-2.0-or-later

#include "synchronization_util.h"
#include "ch.h"

#if defined(SPLIT_KEYBOARD)
static MUTEX_DECL(SPLIT_SHARED_MEMORY_MUTEX);

/**
* @brief Acquire exclusive access to the split keyboard shared memory, by
* locking the mutex guarding it. If the mutex is already held, the calling
* thread will be suspended until the mutex currently owning thread releases the
* mutex again.
*/
void split_shared_memory_lock(void) {
chMtxLock(&SPLIT_SHARED_MEMORY_MUTEX);
}

/**
* @brief Release the split shared memory mutex that has been acquired before.
*/
void split_shared_memory_unlock(void) {
chMtxUnlock(&SPLIT_SHARED_MEMORY_MUTEX);
}
#endif
14 changes: 14 additions & 0 deletions platforms/synchronization_util.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright 2022 Stefan Kerkmann
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#if defined(PLATFORM_SUPPORTS_SYNCHRONIZATION)
# if defined(SPLIT_KEYBOARD)
void split_shared_memory_lock(void);
void split_shared_memory_unlock(void);
# endif
#else
inline void split_shared_memory_lock(void){};
inline void split_shared_memory_unlock(void){};
#endif
17 changes: 8 additions & 9 deletions quantum/split_common/transactions.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@
#include "quantum.h"
#include "transactions.h"
#include "transport.h"
#include "split_util.h"
#include "transaction_id_define.h"
#include "split_util.h"
#include "synchronization_util.h"

#define SYNC_TIMER_OFFSET 2

Expand Down Expand Up @@ -63,9 +64,7 @@ static bool transaction_handler_master(matrix_row_t master_matrix[], matrix_row_
}
}
bool this_okay = true;
ATOMIC_BLOCK_FORCEON {
this_okay = handler(master_matrix, slave_matrix);
};
this_okay = handler(master_matrix, slave_matrix);
if (this_okay) return true;
}
dprintf("Failed to execute %s\n", prefix);
Expand All @@ -77,11 +76,11 @@ static bool transaction_handler_master(matrix_row_t master_matrix[], matrix_row_
if (!transaction_handler_master(master_matrix, slave_matrix, #prefix, &prefix##_handlers_master)) return false; \
} while (0)

#define TRANSACTION_HANDLER_SLAVE(prefix) \
do { \
ATOMIC_BLOCK_FORCEON { \
prefix##_handlers_slave(master_matrix, slave_matrix); \
}; \
#define TRANSACTION_HANDLER_SLAVE(prefix) \
do { \
split_shared_memory_lock(); \
prefix##_handlers_slave(master_matrix, slave_matrix); \
split_shared_memory_unlock(); \
} while (0)

inline static bool read_if_checksum_mismatch(int8_t trans_id_checksum, int8_t trans_id_retrieve, uint32_t *last_update, void *destination, const void *equiv_shmem, size_t length) {
Expand Down