-
-
Notifications
You must be signed in to change notification settings - Fork 39.8k
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] rewrite locking in split transaction handlers #18417
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -76,7 +76,26 @@ 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) | ||
|
||
/** | ||
* @brief Constructs a transaction handler that doesn't acquire a lock to the | ||
* split shared memory. Therefore the locking and unlocking has to be done | ||
* manually inside the handler. Use this macro only if the handler is | ||
* non-deterministic in runtime and thus needs a manual lock unlock | ||
* implementation to hold the lock for the shortest possible time. | ||
*/ | ||
#define TRANSACTION_HANDLER_SLAVE(prefix) \ | ||
do { \ | ||
prefix##_handlers_slave(master_matrix, slave_matrix); \ | ||
} while (0) | ||
|
||
/** | ||
* @brief Constructs a transaction handler that automatically acquires a lock to | ||
* safely access the split shared memory and releases the lock again after | ||
* processing the handler. Use this macro if the handler is fast and | ||
* deterministic in runtime and thus holds the lock only for a very short time. | ||
* If not fallback to manually locking and unlocking inside the handler. | ||
*/ | ||
#define TRANSACTION_HANDLER_SLAVE_AUTOLOCK(prefix) \ | ||
do { \ | ||
split_shared_memory_lock(); \ | ||
prefix##_handlers_slave(master_matrix, slave_matrix); \ | ||
|
@@ -139,7 +158,7 @@ static void slave_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row | |
|
||
// clang-format off | ||
#define TRANSACTIONS_SLAVE_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(slave_matrix) | ||
#define TRANSACTIONS_SLAVE_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(slave_matrix) | ||
#define TRANSACTIONS_SLAVE_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE_AUTOLOCK(slave_matrix) | ||
#define TRANSACTIONS_SLAVE_MATRIX_REGISTRATIONS \ | ||
[GET_SLAVE_MATRIX_CHECKSUM] = trans_target2initiator_initializer(smatrix.checksum), \ | ||
[GET_SLAVE_MATRIX_DATA] = trans_target2initiator_initializer(smatrix.matrix), | ||
|
@@ -161,7 +180,7 @@ static void master_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_ro | |
} | ||
|
||
# define TRANSACTIONS_MASTER_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(master_matrix) | ||
# define TRANSACTIONS_MASTER_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(master_matrix) | ||
# define TRANSACTIONS_MASTER_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE_AUTOLOCK(master_matrix) | ||
# define TRANSACTIONS_MASTER_MATRIX_REGISTRATIONS [PUT_MASTER_MATRIX] = trans_initiator2target_initializer(mmatrix.matrix), | ||
|
||
#else // SPLIT_TRANSPORT_MIRROR | ||
|
@@ -197,7 +216,7 @@ static void encoder_handlers_slave(matrix_row_t master_matrix[], matrix_row_t sl | |
|
||
// clang-format off | ||
# define TRANSACTIONS_ENCODERS_MASTER() TRANSACTION_HANDLER_MASTER(encoder) | ||
# define TRANSACTIONS_ENCODERS_SLAVE() TRANSACTION_HANDLER_SLAVE(encoder) | ||
# define TRANSACTIONS_ENCODERS_SLAVE() TRANSACTION_HANDLER_SLAVE_AUTOLOCK(encoder) | ||
# define TRANSACTIONS_ENCODERS_REGISTRATIONS \ | ||
[GET_ENCODERS_CHECKSUM] = trans_target2initiator_initializer(encoders.checksum), \ | ||
[GET_ENCODERS_DATA] = trans_target2initiator_initializer(encoders.state), | ||
|
@@ -239,7 +258,7 @@ static void sync_timer_handlers_slave(matrix_row_t master_matrix[], matrix_row_t | |
} | ||
|
||
# define TRANSACTIONS_SYNC_TIMER_MASTER() TRANSACTION_HANDLER_MASTER(sync_timer) | ||
# define TRANSACTIONS_SYNC_TIMER_SLAVE() TRANSACTION_HANDLER_SLAVE(sync_timer) | ||
# define TRANSACTIONS_SYNC_TIMER_SLAVE() TRANSACTION_HANDLER_SLAVE_AUTOLOCK(sync_timer) | ||
# define TRANSACTIONS_SYNC_TIMER_REGISTRATIONS [PUT_SYNC_TIMER] = trans_initiator2target_initializer(sync_timer), | ||
|
||
#else // DISABLE_SYNC_TIMER | ||
|
@@ -273,7 +292,7 @@ static void layer_state_handlers_slave(matrix_row_t master_matrix[], matrix_row_ | |
|
||
// clang-format off | ||
# define TRANSACTIONS_LAYER_STATE_MASTER() TRANSACTION_HANDLER_MASTER(layer_state) | ||
# define TRANSACTIONS_LAYER_STATE_SLAVE() TRANSACTION_HANDLER_SLAVE(layer_state) | ||
# define TRANSACTIONS_LAYER_STATE_SLAVE() TRANSACTION_HANDLER_SLAVE_AUTOLOCK(layer_state) | ||
# define TRANSACTIONS_LAYER_STATE_REGISTRATIONS \ | ||
[PUT_LAYER_STATE] = trans_initiator2target_initializer(layers.layer_state), \ | ||
[PUT_DEFAULT_LAYER_STATE] = trans_initiator2target_initializer(layers.default_layer_state), | ||
|
@@ -304,7 +323,7 @@ static void led_state_handlers_slave(matrix_row_t master_matrix[], matrix_row_t | |
} | ||
|
||
# define TRANSACTIONS_LED_STATE_MASTER() TRANSACTION_HANDLER_MASTER(led_state) | ||
# define TRANSACTIONS_LED_STATE_SLAVE() TRANSACTION_HANDLER_SLAVE(led_state) | ||
# define TRANSACTIONS_LED_STATE_SLAVE() TRANSACTION_HANDLER_SLAVE_AUTOLOCK(led_state) | ||
# define TRANSACTIONS_LED_STATE_REGISTRATIONS [PUT_LED_STATE] = trans_initiator2target_initializer(led_state), | ||
|
||
#else // SPLIT_LED_STATE_ENABLE | ||
|
@@ -353,10 +372,15 @@ static bool mods_handlers_master(matrix_row_t master_matrix[], matrix_row_t slav | |
} | ||
|
||
static void mods_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
set_mods(split_shmem->mods.real_mods); | ||
set_weak_mods(split_shmem->mods.weak_mods); | ||
split_shared_memory_lock(); | ||
split_mods_sync_t mods; | ||
memcpy(&mods, &split_shmem->mods, sizeof(split_mods_sync_t)); | ||
split_shared_memory_unlock(); | ||
|
||
set_mods(mods.real_mods); | ||
set_weak_mods(mods.weak_mods); | ||
# ifndef NO_ACTION_ONESHOT | ||
set_oneshot_mods(split_shmem->mods.oneshot_mods); | ||
set_oneshot_mods(mods.oneshot_mods); | ||
# endif | ||
} | ||
|
||
|
@@ -384,7 +408,11 @@ static bool backlight_handlers_master(matrix_row_t master_matrix[], matrix_row_t | |
} | ||
|
||
static void backlight_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
backlight_set(split_shmem->backlight_level); | ||
split_shared_memory_lock(); | ||
uint8_t backlight_level = split_shmem->backlight_level; | ||
split_shared_memory_unlock(); | ||
|
||
backlight_set(backlight_level); | ||
} | ||
|
||
# define TRANSACTIONS_BACKLIGHT_MASTER() TRANSACTION_HANDLER_MASTER(backlight) | ||
|
@@ -417,10 +445,15 @@ static bool rgblight_handlers_master(matrix_row_t master_matrix[], matrix_row_t | |
} | ||
|
||
static void rgblight_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
split_shared_memory_lock(); | ||
// Update the RGB with the new data | ||
if (split_shmem->rgblight_sync.status.change_flags != 0) { | ||
rgblight_update_sync(&split_shmem->rgblight_sync, false); | ||
split_shmem->rgblight_sync.status.change_flags = 0; | ||
rgblight_syncinfo_t rgblight_sync; | ||
memcpy(&rgblight_sync, &split_shmem->rgblight_sync, sizeof(rgblight_syncinfo_t)); | ||
split_shmem->rgblight_sync.status.change_flags = 0; | ||
split_shared_memory_unlock(); | ||
|
||
if (rgblight_sync.status.change_flags != 0) { | ||
rgblight_update_sync(&rgblight_sync, false); | ||
} | ||
} | ||
|
||
|
@@ -450,8 +483,12 @@ static bool led_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_ | |
} | ||
|
||
static void led_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
split_shared_memory_lock(); | ||
memcpy(&led_matrix_eeconfig, &split_shmem->led_matrix_sync.led_matrix, sizeof(led_eeconfig_t)); | ||
led_matrix_set_suspend_state(split_shmem->led_matrix_sync.led_suspend_state); | ||
bool led_suspend_state = split_shmem->led_matrix_sync.led_suspend_state; | ||
split_shared_memory_unlock(); | ||
|
||
led_matrix_set_suspend_state(led_suspend_state); | ||
} | ||
|
||
# define TRANSACTIONS_LED_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(led_matrix) | ||
|
@@ -480,8 +517,12 @@ static bool rgb_matrix_handlers_master(matrix_row_t master_matrix[], matrix_row_ | |
} | ||
|
||
static void rgb_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
split_shared_memory_lock(); | ||
memcpy(&rgb_matrix_config, &split_shmem->rgb_matrix_sync.rgb_matrix, sizeof(rgb_config_t)); | ||
rgb_matrix_set_suspend_state(split_shmem->rgb_matrix_sync.rgb_suspend_state); | ||
bool rgb_suspend_state = split_shmem->rgb_matrix_sync.rgb_suspend_state; | ||
split_shared_memory_unlock(); | ||
|
||
rgb_matrix_set_suspend_state(rgb_suspend_state); | ||
} | ||
|
||
# define TRANSACTIONS_RGB_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(rgb_matrix) | ||
|
@@ -512,7 +553,7 @@ static void wpm_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_ | |
} | ||
|
||
# define TRANSACTIONS_WPM_MASTER() TRANSACTION_HANDLER_MASTER(wpm) | ||
# define TRANSACTIONS_WPM_SLAVE() TRANSACTION_HANDLER_SLAVE(wpm) | ||
# define TRANSACTIONS_WPM_SLAVE() TRANSACTION_HANDLER_SLAVE_AUTOLOCK(wpm) | ||
# define TRANSACTIONS_WPM_REGISTRATIONS [PUT_WPM] = trans_initiator2target_initializer(current_wpm), | ||
|
||
#else // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE) | ||
|
@@ -535,7 +576,11 @@ static bool oled_handlers_master(matrix_row_t master_matrix[], matrix_row_t slav | |
} | ||
|
||
static void oled_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
if (split_shmem->current_oled_state) { | ||
split_shared_memory_lock(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The value of having a lock around a single read of a byte; either you read the value before or after the concurrent update, but there is no possibility of getting an inconsistent view of a single byte. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are right, I didn't think of that. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Appreciate the concern for defensive measures, though. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doing a checksum on a single byte isn't going to speed things up either -- may as well just transfer the actual byte unconditionally. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're right, but the checksum is actually meant to prevent/detect data corruption as we usually don't use any resilient to means of communication (except for odd/even parity checks for some USART peripherals). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Understood; but in that circumstance the request/response nature of the protocol should probably be modified such that at a certain amount of data transfer, you transmit payload+checksum in a single operation. That's a longer term discussion, at least. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure the refactoring should be done after some discussion, does this prevent merging the changes in this PR? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No. |
||
uint8_t current_oled_state = split_shmem->current_oled_state; | ||
split_shared_memory_unlock(); | ||
|
||
if (current_oled_state) { | ||
oled_on(); | ||
} else { | ||
oled_off(); | ||
|
@@ -566,15 +611,19 @@ static bool st7565_handlers_master(matrix_row_t master_matrix[], matrix_row_t sl | |
} | ||
|
||
static void st7565_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | ||
if (split_shmem->current_st7565_state) { | ||
split_shared_memory_lock(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ditto |
||
uint8_t current_st7565_state = split_shmem->current_st7565_state; | ||
split_shared_memory_unlock(); | ||
|
||
if (current_st7565_state) { | ||
st7565_on(); | ||
} else { | ||
st7565_off(); | ||
} | ||
} | ||
|
||
# define TRANSACTIONS_ST7565_MASTER() TRANSACTION_HANDLER_MASTER(st7565) | ||
# define TRANSACTIONS_ST7565_SLAVE() TRANSACTION_HANDLER_SLAVE(st7565) | ||
# define TRANSACTIONS_ST7565_SLAVE() TRANSACTION_HANDLER_SLAVE_AUTOLOCK(st7565) | ||
# define TRANSACTIONS_ST7565_REGISTRATIONS [PUT_ST7565] = trans_initiator2target_initializer(current_st7565_state), | ||
|
||
#else // defined(ST7565_ENABLE) && defined(SPLIT_ST7565_ENABLE) | ||
|
@@ -607,9 +656,9 @@ static bool pointing_handlers_master(matrix_row_t master_matrix[], matrix_row_t | |
bool okay = read_if_checksum_mismatch(GET_POINTING_CHECKSUM, GET_POINTING_DATA, &last_update, &temp_state, &split_shmem->pointing.report, sizeof(temp_state)); | ||
if (okay) pointing_device_set_shared_report(temp_state); | ||
temp_cpi = pointing_device_get_shared_cpi(); | ||
if (temp_cpi && memcmp(&last_cpi, &temp_cpi, sizeof(temp_cpi)) != 0) { | ||
memcpy(&split_shmem->pointing.cpi, &temp_cpi, sizeof(temp_cpi)); | ||
okay = transport_write(PUT_POINTING_CPI, &split_shmem->pointing.cpi, sizeof(split_shmem->pointing.cpi)); | ||
if (temp_cpi && last_cpi != temp_cpi) { | ||
split_shmem->pointing.cpi = temp_cpi; | ||
okay = transport_write(PUT_POINTING_CPI, &split_shmem->pointing.cpi, sizeof(split_shmem->pointing.cpi)); | ||
if (okay) { | ||
last_cpi = temp_cpi; | ||
} | ||
|
@@ -629,26 +678,32 @@ static void pointing_handlers_slave(matrix_row_t master_matrix[], matrix_row_t s | |
return; | ||
} | ||
# endif | ||
report_mouse_t temp_report; | ||
uint16_t temp_cpi; | ||
# if (POINTING_DEVICE_TASK_THROTTLE_MS > 0) | ||
static uint32_t last_exec = 0; | ||
if (timer_elapsed32(last_exec) < POINTING_DEVICE_TASK_THROTTLE_MS) { | ||
return; | ||
} | ||
last_exec = timer_read32(); | ||
# endif | ||
temp_cpi = !pointing_device_driver.get_cpi ? 0 : pointing_device_driver.get_cpi(); // check for NULL | ||
if (split_shmem->pointing.cpi && memcmp(&split_shmem->pointing.cpi, &temp_cpi, sizeof(temp_cpi)) != 0) { | ||
if (pointing_device_driver.set_cpi) { | ||
pointing_device_driver.set_cpi(split_shmem->pointing.cpi); | ||
} | ||
|
||
uint16_t temp_cpi = !pointing_device_driver.get_cpi ? 0 : pointing_device_driver.get_cpi(); // check for NULL | ||
|
||
split_shared_memory_lock(); | ||
split_slave_pointing_sync_t pointing; | ||
memcpy(&pointing, &split_shmem->pointing, sizeof(split_slave_pointing_sync_t)); | ||
split_shared_memory_unlock(); | ||
|
||
if (pointing.cpi && pointing.cpi != temp_cpi && pointing_device_driver.set_cpi) { | ||
pointing_device_driver.set_cpi(pointing.cpi); | ||
} | ||
memset(&temp_report, 0, sizeof(temp_report)); | ||
temp_report = pointing_device_driver.get_report(temp_report); | ||
memcpy(&split_shmem->pointing.report, &temp_report, sizeof(temp_report)); | ||
|
||
pointing.report = pointing_device_driver.get_report((report_mouse_t){0}); | ||
// Now update the checksum given that the pointing has been written to | ||
split_shmem->pointing.checksum = crc8(&temp_report, sizeof(temp_report)); | ||
pointing.checksum = crc8(&pointing.report, sizeof(report_mouse_t)); | ||
|
||
split_shared_memory_lock(); | ||
memcpy(&split_shmem->pointing, &pointing, sizeof(split_slave_pointing_sync_t)); | ||
split_shared_memory_unlock(); | ||
} | ||
|
||
# define TRANSACTIONS_POINTING_MASTER() TRANSACTION_HANDLER_MASTER(pointing) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keep this line - locking is not necessary for accessing a single byte.