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>
This commit is contained in:
parent
790d9dad59
commit
48939cb44b
1 changed files with 26 additions and 16 deletions
|
@ -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
|
|||
/* 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
|
|||
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
|
|||
|
||||
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_msgq, put, msgq, timeout, result);
|
||||
|
||||
z_reschedule(&msgq->lock, key);
|
||||
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)
|
|||
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)
|
|||
/* 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)
|
|||
|
||||
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_msgq, get, msgq, timeout, result);
|
||||
|
||||
k_spin_unlock(&msgq->lock, key);
|
||||
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)
|
|||
{
|
||||
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;
|
||||
pending_thread = z_unpend_first_thread(&msgq->wait_q)) {
|
||||
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;
|
||||
|
||||
z_reschedule(&msgq->lock, key);
|
||||
if (resched) {
|
||||
z_reschedule(&msgq->lock, key);
|
||||
} else {
|
||||
k_spin_unlock(&msgq->lock, key);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue