Skip to content

Commit

Permalink
refactor: use low priority workqueue for underglow and battery reporting
Browse files Browse the repository at this point in the history
Blocking operations on the high priority system workqueue may result in
deadlocks, particularly when Bluetooth is in use.
  • Loading branch information
xudongzheng authored and petejohanson committed Jul 25, 2023
1 parent f743d57 commit 9a963ab
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 10 deletions.
1 change: 1 addition & 0 deletions app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ target_sources_ifdef(CONFIG_USB_DEVICE_STACK app PRIVATE src/usb.c)
target_sources_ifdef(CONFIG_ZMK_USB app PRIVATE src/usb_hid.c)
target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/rgb_underglow.c)
target_sources_ifdef(CONFIG_ZMK_BACKLIGHT app PRIVATE src/backlight.c)
target_sources(app PRIVATE src/workqueue.c)
target_sources(app PRIVATE src/main.c)

add_subdirectory(src/display/)
Expand Down
8 changes: 8 additions & 0 deletions app/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,14 @@ config ZMK_BATTERY_REPORT_INTERVAL
int "Battery level report interval in seconds"
default 60

config ZMK_LOW_PRIORITY_THREAD_STACK_SIZE
int "Low priority thread stack size"
default 768

config ZMK_LOW_PRIORITY_THREAD_PRIORITY
int "Low priority thread priority"
default 10

#Advanced
endmenu

Expand Down
1 change: 1 addition & 0 deletions app/include/zmk/workqueue.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
struct k_work_q *zmk_workqueue_lowprio_work_q();
14 changes: 5 additions & 9 deletions app/src/battery.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/event_manager.h>
#include <zmk/battery.h>
#include <zmk/events/battery_state_changed.h>
#include <zmk/workqueue.h>

static uint8_t last_state_of_charge = 0;

Expand Down Expand Up @@ -77,7 +78,9 @@ static void zmk_battery_work(struct k_work *work) {

K_WORK_DEFINE(battery_work, zmk_battery_work);

static void zmk_battery_timer(struct k_timer *timer) { k_work_submit(&battery_work); }
static void zmk_battery_timer(struct k_timer *timer) {
k_work_submit_to_queue(zmk_workqueue_lowprio_work_q(), &battery_work);
}

K_TIMER_DEFINE(battery_timer, zmk_battery_timer, NULL);

Expand All @@ -97,14 +100,7 @@ static int zmk_battery_init(const struct device *_arg) {
return -ENODEV;
}

int rc = zmk_battery_update(battery);

if (rc != 0) {
LOG_DBG("Failed to update battery value: %d.", rc);
return rc;
}

k_timer_start(&battery_timer, K_MINUTES(1), K_SECONDS(CONFIG_ZMK_BATTERY_REPORT_INTERVAL));
k_timer_start(&battery_timer, K_NO_WAIT, K_SECONDS(CONFIG_ZMK_BATTERY_REPORT_INTERVAL));

return 0;
}
Expand Down
3 changes: 2 additions & 1 deletion app/src/rgb_underglow.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <zmk/event_manager.h>
#include <zmk/events/activity_state_changed.h>
#include <zmk/events/usb_conn_state_changed.h>
#include <zmk/workqueue.h>

LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);

Expand Down Expand Up @@ -203,7 +204,7 @@ static void zmk_rgb_underglow_tick_handler(struct k_timer *timer) {
return;
}

k_work_submit(&underglow_work);
k_work_submit_to_queue(zmk_workqueue_lowprio_work_q(), &underglow_work);
}

K_TIMER_DEFINE(underglow_tick, zmk_rgb_underglow_tick_handler, NULL);
Expand Down
27 changes: 27 additions & 0 deletions app/src/workqueue.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2023 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/

#include <zephyr/kernel.h>
#include <zephyr/device.h>

#include <zmk/workqueue.h>

K_THREAD_STACK_DEFINE(lowprio_q_stack, CONFIG_ZMK_LOW_PRIORITY_THREAD_STACK_SIZE);

static struct k_work_q lowprio_work_q;

struct k_work_q *zmk_workqueue_lowprio_work_q() {
return &lowprio_work_q;
}

static int workqueue_init() {
static const struct k_work_queue_config queue_config = {.name = "Low Priority Work Queue"};
k_work_queue_start(&lowprio_work_q, lowprio_q_stack, K_THREAD_STACK_SIZEOF(lowprio_q_stack),
CONFIG_ZMK_LOW_PRIORITY_THREAD_PRIORITY, &queue_config);
return 0;
}

SYS_INIT(workqueue_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);

0 comments on commit 9a963ab

Please sign in to comment.