Browse Source

kernel: msgq: Allow for fast returns

1. Fixes a performance issue in k_msgq_put() to allow for a fast return
path when handling a poll event does nothing.

2. Allows for a fast return path in k_msgq_purge() when no threads were
awakened.

Signed-off-by: Peter Mitsis <peter.mitsis@intel.com>
pull/85097/head
Peter Mitsis 7 months ago committed by Benjamin Cabé
parent
commit
48939cb44b
  1. 34
      kernel/msg_q.c

34
kernel/msg_q.c

@ -132,6 +132,7 @@ int z_impl_k_msgq_put(struct k_msgq *msgq, const void *data, k_timeout_t timeout @@ -132,6 +132,7 @@ int z_impl_k_msgq_put(struct k_msgq *msgq, const void *data, k_timeout_t timeout
struct k_thread *pending_thread;
k_spinlock_key_t key;
int result;
bool resched = false;
key = k_spin_lock(&msgq->lock);
@ -141,16 +142,13 @@ int z_impl_k_msgq_put(struct k_msgq *msgq, const void *data, k_timeout_t timeout @@ -141,16 +142,13 @@ int z_impl_k_msgq_put(struct k_msgq *msgq, const void *data, k_timeout_t timeout
/* message queue isn't full */
pending_thread = z_unpend_first_thread(&msgq->wait_q);
if (unlikely(pending_thread != NULL)) {
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_msgq, put, msgq, timeout, 0);
resched = true;
/* give message to waiting thread */
(void)memcpy(pending_thread->base.swap_data, data,
msgq->msg_size);
(void)memcpy(pending_thread->base.swap_data, data, msgq->msg_size);
/* wake up waiting thread */
arch_thread_return_value_set(pending_thread, 0);
z_ready_thread(pending_thread);
z_reschedule(&msgq->lock, key);
return 0;
} else {
/* put message in queue */
__ASSERT_NO_MSG(msgq->write_ptr >= msgq->buffer_start &&
@ -161,7 +159,7 @@ int z_impl_k_msgq_put(struct k_msgq *msgq, const void *data, k_timeout_t timeout @@ -161,7 +159,7 @@ int z_impl_k_msgq_put(struct k_msgq *msgq, const void *data, k_timeout_t timeout
msgq->write_ptr = msgq->buffer_start;
}
msgq->used_msgs++;
(void)handle_poll_events(msgq);
resched = handle_poll_events(msgq);
}
result = 0;
} else if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
@ -180,7 +178,11 @@ int z_impl_k_msgq_put(struct k_msgq *msgq, const void *data, k_timeout_t timeout @@ -180,7 +178,11 @@ int z_impl_k_msgq_put(struct k_msgq *msgq, const void *data, k_timeout_t timeout
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_msgq, put, msgq, timeout, result);
if (resched) {
z_reschedule(&msgq->lock, key);
} else {
k_spin_unlock(&msgq->lock, key);
}
return result;
}
@ -222,6 +224,7 @@ int z_impl_k_msgq_get(struct k_msgq *msgq, void *data, k_timeout_t timeout) @@ -222,6 +224,7 @@ int z_impl_k_msgq_get(struct k_msgq *msgq, void *data, k_timeout_t timeout)
k_spinlock_key_t key;
struct k_thread *pending_thread;
int result;
bool resched = false;
key = k_spin_lock(&msgq->lock);
@ -255,11 +258,7 @@ int z_impl_k_msgq_get(struct k_msgq *msgq, void *data, k_timeout_t timeout) @@ -255,11 +258,7 @@ int z_impl_k_msgq_get(struct k_msgq *msgq, void *data, k_timeout_t timeout)
/* wake up waiting thread */
arch_thread_return_value_set(pending_thread, 0);
z_ready_thread(pending_thread);
z_reschedule(&msgq->lock, key);
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_msgq, get, msgq, timeout, 0);
return 0;
resched = true;
}
result = 0;
} else if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
@ -278,7 +277,11 @@ int z_impl_k_msgq_get(struct k_msgq *msgq, void *data, k_timeout_t timeout) @@ -278,7 +277,11 @@ int z_impl_k_msgq_get(struct k_msgq *msgq, void *data, k_timeout_t timeout)
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_msgq, get, msgq, timeout, result);
if (resched) {
z_reschedule(&msgq->lock, key);
} else {
k_spin_unlock(&msgq->lock, key);
}
return result;
}
@ -379,22 +382,29 @@ void z_impl_k_msgq_purge(struct k_msgq *msgq) @@ -379,22 +382,29 @@ void z_impl_k_msgq_purge(struct k_msgq *msgq)
{
k_spinlock_key_t key;
struct k_thread *pending_thread;
bool resched = false;
key = k_spin_lock(&msgq->lock);
SYS_PORT_TRACING_OBJ_FUNC(k_msgq, purge, msgq);
/* wake up any threads that are waiting to write */
for (pending_thread = z_unpend_first_thread(&msgq->wait_q); pending_thread != NULL;
for (pending_thread = z_unpend_first_thread(&msgq->wait_q);
pending_thread != NULL;
pending_thread = z_unpend_first_thread(&msgq->wait_q)) {
arch_thread_return_value_set(pending_thread, -ENOMSG);
z_ready_thread(pending_thread);
resched = true;
}
msgq->used_msgs = 0;
msgq->read_ptr = msgq->write_ptr;
if (resched) {
z_reschedule(&msgq->lock, key);
} else {
k_spin_unlock(&msgq->lock, key);
}
}
#ifdef CONFIG_USERSPACE

Loading…
Cancel
Save