diff --git a/include/kernel.h b/include/kernel.h index 546bd924334..835a99fe1db 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -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; }; }; diff --git a/kernel/msg_q.c b/kernel/msg_q.c index cf0f661f947..f888fde72e6 100644 --- a/kernel/msg_q.c +++ b/kernel/msg_q.c @@ -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)) { diff --git a/kernel/poll.c b/kernel/poll.c index 376f51b2c66..231bc83f629 100644 --- a/kernel/poll.c +++ b/kernel/poll.c @@ -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;