Skip to content

Commit

Permalink
net: lwm2m: Make LwM2M context lists access thread safe
Browse files Browse the repository at this point in the history
System lists are not thread safe, therefore all accesses should be
protected with a mutex. Introduce a LwM2M context specific mutex,
and use it whenever lists defined per-context are acessed.

Signed-off-by: Robert Lubos <[email protected]>
  • Loading branch information
rlubos committed Oct 15, 2024
1 parent c892e00 commit 5e1f05e
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 9 deletions.
1 change: 1 addition & 0 deletions include/zephyr/net/lwm2m.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ struct lwm2m_ctx {
sys_slist_t queued_messages;
#endif
sys_slist_t observer;
struct k_mutex lock;
/** @endcond */

/** A pointer to currently processed request, for internal LwM2M engine
Expand Down
52 changes: 43 additions & 9 deletions subsys/net/lib/lwm2m/lwm2m_engine.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ int lwm2m_push_queued_buffers(struct lwm2m_ctx *client_ctx)
{
#if defined(CONFIG_LWM2M_QUEUE_MODE_ENABLED)
client_ctx->buffer_client_messages = false;
lwm2m_client_lock(client_ctx);
while (!sys_slist_is_empty(&client_ctx->queued_messages)) {
sys_snode_t *msg_node = sys_slist_get(&client_ctx->queued_messages);
struct lwm2m_message *msg;
Expand All @@ -243,6 +244,7 @@ int lwm2m_push_queued_buffers(struct lwm2m_ctx *client_ctx)
msg->pending->t0 = k_uptime_get();
sys_slist_append(&msg->ctx->pending_sends, &msg->node);
}
lwm2m_client_unlock(client_ctx);
#endif
return 0;
}
Expand Down Expand Up @@ -641,17 +643,22 @@ static int64_t check_notifications(struct lwm2m_ctx *ctx, const int64_t timestam
*/
static void hint_socket_state(struct lwm2m_ctx *ctx, struct lwm2m_message *ongoing_tx)
{
bool empty;
size_t pendings;

if (!ctx || !ctx->set_socket_state) {
return;
}

lwm2m_client_lock(ctx);
#if defined(CONFIG_LWM2M_QUEUE_MODE_ENABLED)
bool empty = sys_slist_is_empty(&ctx->pending_sends) &&
sys_slist_is_empty(&ctx->queued_messages);
empty = sys_slist_is_empty(&ctx->pending_sends) &&
sys_slist_is_empty(&ctx->queued_messages);
#else
bool empty = sys_slist_is_empty(&ctx->pending_sends);
empty = sys_slist_is_empty(&ctx->pending_sends);
#endif
size_t pendings = coap_pendings_count(ctx->pendings, ARRAY_SIZE(ctx->pendings));
pendings = coap_pendings_count(ctx->pendings, ARRAY_SIZE(ctx->pendings));
lwm2m_client_unlock(ctx);

if (ongoing_tx) {
/* Check if more than current TX is in pendings list*/
Expand Down Expand Up @@ -710,9 +717,13 @@ static int socket_recv_message(struct lwm2m_ctx *client_ctx)
static int socket_send_message(struct lwm2m_ctx *ctx)
{
int rc;
sys_snode_t *msg_node = sys_slist_get(&ctx->pending_sends);
sys_snode_t *msg_node;
struct lwm2m_message *msg;

lwm2m_client_lock(ctx);
msg_node = sys_slist_get(&ctx->pending_sends);
lwm2m_client_unlock(ctx);

if (!msg_node) {
return 0;
}
Expand Down Expand Up @@ -750,11 +761,17 @@ static int socket_send_message(struct lwm2m_ctx *ctx)
static void socket_reset_pollfd_events(void)
{
for (int i = 0; i < MAX_POLL_FD; ++i) {
bool set_pollout = false;

if (sock_ctx[i] != NULL) {
lwm2m_client_lock(sock_ctx[i]);
set_pollout = !sys_slist_is_empty(&sock_ctx[i]->pending_sends);
lwm2m_client_unlock(sock_ctx[i]);
}

sock_fds[i].events =
ZSOCK_POLLIN |
(!sock_ctx[i] || sys_slist_is_empty(&sock_ctx[i]->pending_sends)
? 0
: ZSOCK_POLLOUT);
(set_pollout ? ZSOCK_POLLOUT : 0);
sock_fds[i].revents = 0;

Check notice on line 775 in subsys/net/lib/lwm2m/lwm2m_engine.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

subsys/net/lib/lwm2m/lwm2m_engine.c:775 - sock_fds[i].events = - ZSOCK_POLLIN | - (set_pollout ? ZSOCK_POLLOUT : 0); + sock_fds[i].events = ZSOCK_POLLIN | (set_pollout ? ZSOCK_POLLOUT : 0);
}
}
Expand Down Expand Up @@ -800,13 +817,20 @@ static void socket_loop(void *p1, void *p2, void *p3)

for (i = 0; i < sock_nfds; ++i) {
struct lwm2m_ctx *ctx = sock_ctx[i];
bool is_empty;

if (ctx == NULL) {
continue;
}
if (!sys_slist_is_empty(&ctx->pending_sends)) {

lwm2m_client_lock(ctx);
is_empty = sys_slist_is_empty(&ctx->pending_sends);
lwm2m_client_unlock(ctx);

if (!is_empty) {
continue;
}

next_tx = retransmit_request(ctx, now);
if (next_tx < next) {
next = next_tx;
Expand Down Expand Up @@ -1285,6 +1309,16 @@ int lwm2m_engine_resume(void)
return 0;
}

void lwm2m_client_lock(struct lwm2m_ctx *ctx)
{
(void)k_mutex_lock(&ctx->lock, K_FOREVER);
}

void lwm2m_client_unlock(struct lwm2m_ctx *ctx)
{
k_mutex_unlock(&ctx->lock);
}

static int lwm2m_engine_init(void)
{
for (int i = 0; i < LWM2M_ENGINE_MAX_OBSERVER_PATH; i++) {
Expand Down
14 changes: 14 additions & 0 deletions subsys/net/lib/lwm2m/lwm2m_engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -375,4 +375,18 @@ int lwm2m_sock_nfds(void);
*/
void lwm2m_engine_wake_up(void);

/**
* @brief Locks the client.
*
* @param[in] client_ctx LwM2M context
*/
void lwm2m_client_lock(struct lwm2m_ctx *ctx);

/**
* @brief Unlocks the client previously locked by lwm2m_client_lock().
*
* @param[in] client_ctx LwM2M context
*/
void lwm2m_client_unlock(struct lwm2m_ctx *ctx);

#endif /* LWM2M_ENGINE_H */
10 changes: 10 additions & 0 deletions subsys/net/lib/lwm2m/lwm2m_message_handling.c
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,7 @@ void lwm2m_engine_context_init(struct lwm2m_ctx *client_ctx)
client_ctx->buffer_client_messages = true;
sys_slist_init(&client_ctx->queued_messages);
#endif
k_mutex_init(&client_ctx->lock);
}
/* utility functions */

Expand Down Expand Up @@ -562,10 +563,12 @@ void lwm2m_reset_message(struct lwm2m_message *msg, bool release)
lm2m_message_clear_allocations(msg);

if (msg->ctx) {
lwm2m_client_lock(msg->ctx);
sys_slist_find_and_remove(&msg->ctx->pending_sends, &msg->node);
#if defined(CONFIG_LWM2M_QUEUE_MODE_ENABLED)
sys_slist_find_and_remove(&msg->ctx->queued_messages, &msg->node);
#endif
lwm2m_client_unlock(msg->ctx);
}

if (release) {
Expand Down Expand Up @@ -702,7 +705,10 @@ int lwm2m_send_message_async(struct lwm2m_message *msg)
return ret;
}
}

lwm2m_client_lock(msg->ctx);
sys_slist_append(&msg->ctx->pending_sends, &msg->node);
lwm2m_client_unlock(msg->ctx);

if (IS_ENABLED(CONFIG_LWM2M_QUEUE_MODE_ENABLED)) {
engine_update_tx_time();
Expand All @@ -723,14 +729,18 @@ int lwm2m_information_interface_send(struct lwm2m_message *msg)
}

if (IS_ENABLED(CONFIG_LWM2M_QUEUE_MODE_NO_MSG_BUFFERING)) {
lwm2m_client_lock(msg->ctx);
sys_slist_append(&msg->ctx->pending_sends, &msg->node);
lwm2m_client_unlock(msg->ctx);
lwm2m_engine_wake_up();
lwm2m_engine_connection_resume(msg->ctx);
return 0;
}

if (msg->ctx->buffer_client_messages) {
lwm2m_client_lock(msg->ctx);
sys_slist_append(&msg->ctx->queued_messages, &msg->node);
lwm2m_client_unlock(msg->ctx);
lwm2m_engine_wake_up();
return 0;
}
Expand Down

0 comments on commit 5e1f05e

Please sign in to comment.