kernel: Allow k_poll on message queues
This commit adds the ability to use a message queue as a k_poll object. It follows the same pattern as polling on FIFOs. This change has been proven in practice at Samsara. Fixes: #26728 Signed-off-by: Nick Graves <nicholas.graves@samsara.com>
This commit is contained in:
parent
679df67940
commit
b445f13462
3 changed files with 42 additions and 1 deletions
|
@ -4126,6 +4126,8 @@ struct k_msgq {
|
|||
/** Number of used messages */
|
||||
uint32_t used_msgs;
|
||||
|
||||
_POLL_EVENT;
|
||||
|
||||
_OBJECT_TRACING_NEXT_PTR(k_msgq)
|
||||
_OBJECT_TRACING_LINKED_FLAG
|
||||
|
||||
|
@ -4147,6 +4149,7 @@ struct k_msgq {
|
|||
.read_ptr = q_buffer, \
|
||||
.write_ptr = q_buffer, \
|
||||
.used_msgs = 0, \
|
||||
_POLL_EVENT_OBJ_INIT(obj) \
|
||||
_OBJECT_TRACING_INIT \
|
||||
}
|
||||
|
||||
|
@ -5098,6 +5101,9 @@ enum _poll_types_bits {
|
|||
/* queue/FIFO/LIFO data availability */
|
||||
_POLL_TYPE_DATA_AVAILABLE,
|
||||
|
||||
/* msgq data availability */
|
||||
_POLL_TYPE_MSGQ_DATA_AVAILABLE,
|
||||
|
||||
_POLL_NUM_TYPES
|
||||
};
|
||||
|
||||
|
@ -5120,6 +5126,9 @@ enum _poll_states_bits {
|
|||
/* queue/FIFO/LIFO wait was cancelled */
|
||||
_POLL_STATE_CANCELLED,
|
||||
|
||||
/* data is available to read on a message queue */
|
||||
_POLL_STATE_MSGQ_DATA_AVAILABLE,
|
||||
|
||||
_POLL_NUM_STATES
|
||||
};
|
||||
|
||||
|
@ -5150,6 +5159,7 @@ enum _poll_states_bits {
|
|||
#define K_POLL_TYPE_SEM_AVAILABLE Z_POLL_TYPE_BIT(_POLL_TYPE_SEM_AVAILABLE)
|
||||
#define K_POLL_TYPE_DATA_AVAILABLE Z_POLL_TYPE_BIT(_POLL_TYPE_DATA_AVAILABLE)
|
||||
#define K_POLL_TYPE_FIFO_DATA_AVAILABLE K_POLL_TYPE_DATA_AVAILABLE
|
||||
#define K_POLL_TYPE_MSGQ_DATA_AVAILABLE Z_POLL_TYPE_BIT(_POLL_TYPE_MSGQ_DATA_AVAILABLE)
|
||||
|
||||
/* public - polling modes */
|
||||
enum k_poll_modes {
|
||||
|
@ -5165,6 +5175,7 @@ enum k_poll_modes {
|
|||
#define K_POLL_STATE_SEM_AVAILABLE Z_POLL_STATE_BIT(_POLL_STATE_SEM_AVAILABLE)
|
||||
#define K_POLL_STATE_DATA_AVAILABLE Z_POLL_STATE_BIT(_POLL_STATE_DATA_AVAILABLE)
|
||||
#define K_POLL_STATE_FIFO_DATA_AVAILABLE K_POLL_STATE_DATA_AVAILABLE
|
||||
#define K_POLL_STATE_MSGQ_DATA_AVAILABLE Z_POLL_STATE_BIT(_POLL_STATE_MSGQ_DATA_AVAILABLE)
|
||||
#define K_POLL_STATE_CANCELLED Z_POLL_STATE_BIT(_POLL_STATE_CANCELLED)
|
||||
|
||||
/* public - poll signal object */
|
||||
|
@ -5221,6 +5232,7 @@ struct k_poll_event {
|
|||
struct k_sem *sem;
|
||||
struct k_fifo *fifo;
|
||||
struct k_queue *queue;
|
||||
struct k_msgq *msgq;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -46,6 +46,13 @@ SYS_INIT(init_msgq_module, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS);
|
|||
|
||||
#endif /* CONFIG_OBJECT_TRACING */
|
||||
|
||||
#ifdef CONFIG_POLL
|
||||
static inline void handle_poll_events(struct k_msgq *msgq, uint32_t state)
|
||||
{
|
||||
z_handle_obj_poll_events(&msgq->poll_events, state);
|
||||
}
|
||||
#endif /* CONFIG_POLL */
|
||||
|
||||
void k_msgq_init(struct k_msgq *msgq, char *buffer, size_t msg_size,
|
||||
uint32_t max_msgs)
|
||||
{
|
||||
|
@ -59,7 +66,9 @@ void k_msgq_init(struct k_msgq *msgq, char *buffer, size_t msg_size,
|
|||
msgq->flags = 0;
|
||||
z_waitq_init(&msgq->wait_q);
|
||||
msgq->lock = (struct k_spinlock) {};
|
||||
|
||||
#ifdef CONFIG_POLL
|
||||
sys_dlist_init(&msgq->poll_events);
|
||||
#endif /* CONFIG_POLL */
|
||||
SYS_TRACING_OBJ_INIT(k_msgq, msgq);
|
||||
|
||||
z_object_init(msgq);
|
||||
|
@ -143,6 +152,9 @@ 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++;
|
||||
#ifdef CONFIG_POLL
|
||||
handle_poll_events(msgq, K_POLL_STATE_MSGQ_DATA_AVAILABLE);
|
||||
#endif /* CONFIG_POLL */
|
||||
}
|
||||
result = 0;
|
||||
} else if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
|
||||
|
|
|
@ -78,6 +78,12 @@ static inline bool is_condition_met(struct k_poll_event *event, uint32_t *state)
|
|||
return true;
|
||||
}
|
||||
break;
|
||||
case K_POLL_TYPE_MSGQ_DATA_AVAILABLE:
|
||||
if (event->msgq->used_msgs > 0) {
|
||||
*state = K_POLL_STATE_MSGQ_DATA_AVAILABLE;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case K_POLL_TYPE_IGNORE:
|
||||
break;
|
||||
default:
|
||||
|
@ -134,6 +140,10 @@ static inline void register_event(struct k_poll_event *event,
|
|||
__ASSERT(event->signal != NULL, "invalid poll signal\n");
|
||||
add_event(&event->signal->poll_events, event, poller);
|
||||
break;
|
||||
case K_POLL_TYPE_MSGQ_DATA_AVAILABLE:
|
||||
__ASSERT(event->msgq != NULL, "invalid message queue\n");
|
||||
add_event(&event->msgq->poll_events, event, poller);
|
||||
break;
|
||||
case K_POLL_TYPE_IGNORE:
|
||||
/* nothing to do */
|
||||
break;
|
||||
|
@ -165,6 +175,10 @@ static inline void clear_event_registration(struct k_poll_event *event)
|
|||
__ASSERT(event->signal != NULL, "invalid poll signal\n");
|
||||
remove_event = true;
|
||||
break;
|
||||
case K_POLL_TYPE_MSGQ_DATA_AVAILABLE:
|
||||
__ASSERT(event->msgq != NULL, "invalid message queue\n");
|
||||
remove_event = true;
|
||||
break;
|
||||
case K_POLL_TYPE_IGNORE:
|
||||
/* nothing to do */
|
||||
break;
|
||||
|
@ -362,6 +376,9 @@ static inline int z_vrfy_k_poll(struct k_poll_event *events,
|
|||
case K_POLL_TYPE_DATA_AVAILABLE:
|
||||
Z_OOPS(Z_SYSCALL_OBJ(e->queue, K_OBJ_QUEUE));
|
||||
break;
|
||||
case K_POLL_TYPE_MSGQ_DATA_AVAILABLE:
|
||||
Z_OOPS(Z_SYSCALL_OBJ(e->msgq, K_OBJ_MSGQ));
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue