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;
|
struct k_thread *pending_thread;
|
||||||
k_spinlock_key_t key;
|
k_spinlock_key_t key;
|
||||||
int result;
|
int result;
|
||||||
|
bool resched = false;
|
||||||
|
|
||||||
key = k_spin_lock(&msgq->lock);
|
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 */
|
/* message queue isn't full */
|
||||||
pending_thread = z_unpend_first_thread(&msgq->wait_q);
|
pending_thread = z_unpend_first_thread(&msgq->wait_q);
|
||||||
if (unlikely(pending_thread != NULL)) {
|
if (unlikely(pending_thread != NULL)) {
|
||||||
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_msgq, put, msgq, timeout, 0);
|
resched = true;
|
||||||
|
|
||||||
/* give message to waiting thread */
|
/* give message to waiting thread */
|
||||||
(void)memcpy(pending_thread->base.swap_data, data,
|
(void)memcpy(pending_thread->base.swap_data, data, msgq->msg_size);
|
||||||
msgq->msg_size);
|
|
||||||
/* wake up waiting thread */
|
/* wake up waiting thread */
|
||||||
arch_thread_return_value_set(pending_thread, 0);
|
arch_thread_return_value_set(pending_thread, 0);
|
||||||
z_ready_thread(pending_thread);
|
z_ready_thread(pending_thread);
|
||||||
z_reschedule(&msgq->lock, key);
|
|
||||||
return 0;
|
|
||||||
} else {
|
} else {
|
||||||
/* put message in queue */
|
/* put message in queue */
|
||||||
__ASSERT_NO_MSG(msgq->write_ptr >= msgq->buffer_start &&
|
__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->write_ptr = msgq->buffer_start;
|
||||||
}
|
}
|
||||||
msgq->used_msgs++;
|
msgq->used_msgs++;
|
||||||
(void)handle_poll_events(msgq);
|
resched = handle_poll_events(msgq);
|
||||||
}
|
}
|
||||||
result = 0;
|
result = 0;
|
||||||
} else if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
|
} 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);
|
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;
|
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;
|
k_spinlock_key_t key;
|
||||||
struct k_thread *pending_thread;
|
struct k_thread *pending_thread;
|
||||||
int result;
|
int result;
|
||||||
|
bool resched = false;
|
||||||
|
|
||||||
key = k_spin_lock(&msgq->lock);
|
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 */
|
/* wake up waiting thread */
|
||||||
arch_thread_return_value_set(pending_thread, 0);
|
arch_thread_return_value_set(pending_thread, 0);
|
||||||
z_ready_thread(pending_thread);
|
z_ready_thread(pending_thread);
|
||||||
z_reschedule(&msgq->lock, key);
|
resched = true;
|
||||||
|
|
||||||
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_msgq, get, msgq, timeout, 0);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
result = 0;
|
result = 0;
|
||||||
} else if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
|
} 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);
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -379,22 +382,29 @@ void z_impl_k_msgq_purge(struct k_msgq *msgq)
|
||||||
{
|
{
|
||||||
k_spinlock_key_t key;
|
k_spinlock_key_t key;
|
||||||
struct k_thread *pending_thread;
|
struct k_thread *pending_thread;
|
||||||
|
bool resched = false;
|
||||||
|
|
||||||
key = k_spin_lock(&msgq->lock);
|
key = k_spin_lock(&msgq->lock);
|
||||||
|
|
||||||
SYS_PORT_TRACING_OBJ_FUNC(k_msgq, purge, msgq);
|
SYS_PORT_TRACING_OBJ_FUNC(k_msgq, purge, msgq);
|
||||||
|
|
||||||
/* wake up any threads that are waiting to write */
|
/* 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 = 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);
|
arch_thread_return_value_set(pending_thread, -ENOMSG);
|
||||||
z_ready_thread(pending_thread);
|
z_ready_thread(pending_thread);
|
||||||
|
resched = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
msgq->used_msgs = 0;
|
msgq->used_msgs = 0;
|
||||||
msgq->read_ptr = msgq->write_ptr;
|
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
|
#ifdef CONFIG_USERSPACE
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue