shell: exchange k_mutex for k_sem

The mutex is being used as a simple binary semaphore. It is not
recursed so we don't need to track thread ownership nor lock count.

Exchange the mutex for a binary semaphore to save resources and
speed up shell.

Signed-off-by: Bjarki Arge Andreasen <bjarki.andreasen@nordicsemi.no>
This commit is contained in:
Bjarki Arge Andreasen 2025-07-17 00:09:54 +02:00 committed by Fabio Baltieri
parent a90a47b1c9
commit 825dea6832
4 changed files with 34 additions and 19 deletions

View File

@ -963,7 +963,7 @@ struct shell_ctx {
struct k_event signal_event;
struct k_mutex wr_mtx;
struct k_sem lock_sem;
k_tid_t tid;
int ret_val;
};

View File

@ -562,11 +562,11 @@ static int exec_cmd(const struct shell *sh, size_t argc, const char **argv,
/* Unlock thread mutex in case command would like to borrow
* shell context to other thread to avoid mutex deadlock.
*/
k_mutex_unlock(&sh->ctx->wr_mtx);
z_shell_unlock(sh);
ret_val = sh->ctx->active_cmd.handler(sh, argc,
(char **)argv);
/* Bring back mutex to shell thread. */
k_mutex_lock(&sh->ctx->wr_mtx, K_FOREVER);
z_shell_lock(sh);
z_flag_cmd_ctx_set(sh, false);
}
@ -1217,7 +1217,7 @@ static int instance_init(const struct shell *sh,
history_init(sh);
k_event_init(&sh->ctx->signal_event);
k_mutex_init(&sh->ctx->wr_mtx);
k_sem_init(&sh->ctx->lock_sem, 1, 1);
if (IS_ENABLED(CONFIG_SHELL_STATS)) {
sh->stats->log_lost_cnt = 0;
@ -1342,7 +1342,7 @@ void shell_thread(void *shell_handle, void *arg_log_backend,
false,
K_FOREVER);
k_mutex_lock(&sh->ctx->wr_mtx, K_FOREVER);
z_shell_lock(sh);
shell_signal_handle(sh, SHELL_SIGNAL_KILL, kill_handler);
shell_signal_handle(sh, SHELL_SIGNAL_RXRDY, shell_process);
@ -1355,7 +1355,7 @@ void shell_thread(void *shell_handle, void *arg_log_backend,
sh->iface->api->update(sh->iface);
}
k_mutex_unlock(&sh->ctx->wr_mtx);
z_shell_unlock(sh);
}
}
@ -1420,7 +1420,7 @@ int shell_start(const struct shell *sh)
z_shell_log_backend_enable(sh->log_backend, (void *)sh, sh->ctx->log_level);
}
if (k_mutex_lock(&sh->ctx->wr_mtx, SHELL_TX_MTX_TIMEOUT) != 0) {
if (!z_shell_trylock(sh, SHELL_TX_MTX_TIMEOUT)) {
return -EBUSY;
}
@ -1442,7 +1442,7 @@ int shell_start(const struct shell *sh)
*/
z_shell_backend_rx_buffer_flush(sh);
k_mutex_unlock(&sh->ctx->wr_mtx);
z_shell_unlock(sh);
return 0;
}
@ -1524,7 +1524,7 @@ void shell_vfprintf(const struct shell *sh, enum shell_vt100_color color,
return;
}
if (k_mutex_lock(&sh->ctx->wr_mtx, SHELL_TX_MTX_TIMEOUT) != 0) {
if (!z_shell_trylock(sh, SHELL_TX_MTX_TIMEOUT)) {
return;
}
@ -1537,7 +1537,7 @@ void shell_vfprintf(const struct shell *sh, enum shell_vt100_color color,
}
z_transport_buffer_flush(sh);
k_mutex_unlock(&sh->ctx->wr_mtx);
z_shell_unlock(sh);
}
/* These functions mustn't be used from shell context to avoid deadlock:
@ -1664,12 +1664,12 @@ int shell_prompt_change(const struct shell *sh, const char *prompt)
size_t prompt_length = z_shell_strlen(prompt);
if (k_mutex_lock(&sh->ctx->wr_mtx, SHELL_TX_MTX_TIMEOUT) != 0) {
if (!z_shell_trylock(sh, SHELL_TX_MTX_TIMEOUT)) {
return -EBUSY;
}
if ((prompt_length + 1 > CONFIG_SHELL_PROMPT_BUFF_SIZE) || (prompt_length == 0)) {
k_mutex_unlock(&sh->ctx->wr_mtx);
z_shell_unlock(sh);
return -EINVAL;
}
@ -1677,7 +1677,7 @@ int shell_prompt_change(const struct shell *sh, const char *prompt)
sh->ctx->vt100_ctx.cons.name_len = prompt_length;
k_mutex_unlock(&sh->ctx->wr_mtx);
z_shell_unlock(sh);
return 0;
#else
@ -1687,11 +1687,11 @@ int shell_prompt_change(const struct shell *sh, const char *prompt)
void shell_help(const struct shell *sh)
{
if (k_mutex_lock(&sh->ctx->wr_mtx, SHELL_TX_MTX_TIMEOUT) != 0) {
if (!z_shell_trylock(sh, SHELL_TX_MTX_TIMEOUT)) {
return;
}
shell_internal_help_print(sh);
k_mutex_unlock(&sh->ctx->wr_mtx);
z_shell_unlock(sh);
}
int shell_execute_cmd(const struct shell *sh, const char *cmd)
@ -1722,11 +1722,11 @@ int shell_execute_cmd(const struct shell *sh, const char *cmd)
sh->ctx->cmd_buff_len = cmd_len;
sh->ctx->cmd_buff_pos = cmd_len;
if (k_mutex_lock(&sh->ctx->wr_mtx, SHELL_TX_MTX_TIMEOUT) != 0) {
if (!z_shell_trylock(sh, SHELL_TX_MTX_TIMEOUT)) {
return -ENOEXEC;
}
ret_val = execute(sh);
k_mutex_unlock(&sh->ctx->wr_mtx);
z_shell_unlock(sh);
cmd_buffer_clear(sh);

View File

@ -181,7 +181,7 @@ static void process_log_msg(const struct shell *sh,
if (k_is_in_isr()) {
key = irq_lock();
} else {
k_mutex_lock(&sh->ctx->wr_mtx, K_FOREVER);
z_shell_lock(sh);
}
if (!z_flag_cmd_ctx_get(sh)) {
z_shell_cmd_line_erase(sh);
@ -197,7 +197,7 @@ static void process_log_msg(const struct shell *sh,
if (k_is_in_isr()) {
irq_unlock(key);
} else {
k_mutex_unlock(&sh->ctx->wr_mtx);
z_shell_unlock(sh);
}
}
}

View File

@ -381,6 +381,21 @@ void z_shell_vfprintf(const struct shell *sh, enum shell_vt100_color color,
*/
void z_shell_backend_rx_buffer_flush(const struct shell *sh);
static inline bool z_shell_trylock(const struct shell *sh, k_timeout_t timeout)
{
return k_sem_take(&sh->ctx->lock_sem, timeout) == 0;
}
static inline void z_shell_lock(const struct shell *sh)
{
(void)k_sem_take(&sh->ctx->lock_sem, K_FOREVER);
}
static inline void z_shell_unlock(const struct shell *sh)
{
k_sem_give(&sh->ctx->lock_sem);
}
#ifdef __cplusplus
}
#endif