/* * Copyright (c) 2023 Rodrigo Peixoto * SPDX-License-Identifier: Apache-2.0 */ #include "messages.h" #include #include #include #include LOG_MODULE_DECLARE(zbus, CONFIG_ZBUS_LOG_LEVEL); #define STACK_SIZE (CONFIG_MAIN_STACK_SIZE + CONFIG_TEST_EXTRA_STACK_SIZE) static struct k_thread pub_thread; static K_THREAD_STACK_DEFINE(pub_thread_sz, STACK_SIZE); static struct k_thread s1_thread; static K_THREAD_STACK_DEFINE(s1_thread_sz, STACK_SIZE); static struct k_thread ms1_thread; static K_THREAD_STACK_DEFINE(ms1_thread_sz, STACK_SIZE); struct msg_testing_01 { int seq; bool must_detach; }; ZBUS_CHAN_DEFINE(chan_testing_01, /* Name */ struct msg_testing_01, /* Message type */ NULL, /* Validator */ NULL, /* User data */ ZBUS_OBSERVERS(lis1, sub1, msub1), /* observers */ ZBUS_MSG_INIT(0) /* Initial value major 0, minor 1, build 1023 */ ); static void consumer_sub_thread(void *ptr1, void *ptr2, void *ptr3) { ARG_UNUSED(ptr3); zbus_obs_attach_to_thread(ptr1); char *name = ptr2; struct zbus_observer *sub = ptr1; const struct zbus_channel *chan; struct msg_testing_01 msg; while (1) { if (zbus_sub_wait(sub, &chan, K_FOREVER) != 0) { k_oops(); } zbus_chan_read(chan, &msg, K_FOREVER); printk("%s level: %d\n", name, msg.seq); if (msg.must_detach) { zbus_obs_detach_from_thread(sub); } } } ZBUS_SUBSCRIBER_DEFINE(sub1, 4); static void consumer_msg_sub_thread(void *ptr1, void *ptr2, void *ptr3) { ARG_UNUSED(ptr3); zbus_obs_attach_to_thread(ptr1); char *name = ptr2; struct zbus_observer *msub = ptr1; const struct zbus_channel *chan; struct msg_testing_01 msg; while (1) { if (zbus_sub_wait_msg(msub, &chan, &msg, K_FOREVER) != 0) { k_oops(); } printk("%s level: %d\n", name, msg.seq); if (msg.must_detach) { zbus_obs_detach_from_thread(msub); } } } ZBUS_MSG_SUBSCRIBER_DEFINE(msub1); static K_SEM_DEFINE(sync_sem, 1, 1); static K_SEM_DEFINE(done_sem, 0, 1); static struct msg_testing_01 msg = {.seq = 0}; static void publisher_thread(void *ptr1, void *ptr2, void *ptr3) { ARG_UNUSED(ptr1); ARG_UNUSED(ptr2); ARG_UNUSED(ptr3); while (1) { k_sem_take(&sync_sem, K_FOREVER); zbus_chan_pub(&chan_testing_01, &msg, K_FOREVER); k_msleep(100); k_sem_give(&done_sem); } } static inline void _pub_and_sync(void) { k_sem_give(&sync_sem); k_sem_take(&done_sem, K_FOREVER); } static k_tid_t pub_thread_id; static int prio; static void listener_callback(const struct zbus_channel *chan) { prio = k_thread_priority_get(pub_thread_id); } ZBUS_LISTENER_DEFINE(lis1, listener_callback); ZTEST(hlp_priority_boost, test_priority_elevation) { pub_thread_id = k_thread_create(&pub_thread, pub_thread_sz, STACK_SIZE, publisher_thread, NULL, NULL, NULL, K_PRIO_PREEMPT(8), 0, K_NO_WAIT); (void)k_thread_create(&s1_thread, s1_thread_sz, STACK_SIZE, consumer_sub_thread, &sub1, "sub1", NULL, K_PRIO_PREEMPT(3), 0, K_NO_WAIT); (void)k_thread_create(&ms1_thread, ms1_thread_sz, STACK_SIZE, consumer_msg_sub_thread, &msub1, "msub1", NULL, K_PRIO_PREEMPT(2), 0, K_NO_WAIT); _pub_and_sync(); zassert_true(prio == 1, "The priority must be 1, but it is %d", prio); ++msg.seq; zbus_obs_set_enable(&msub1, false); _pub_and_sync(); zassert_true(prio == 2, "The priority must be 2, but it is %d", prio); zbus_obs_set_enable(&msub1, true); ++msg.seq; _pub_and_sync(); zassert_true(prio == 1, "The priority must be 1, but it is %d", prio); ++msg.seq; zbus_obs_set_chan_notification_mask(&msub1, &chan_testing_01, true); bool is_masked; zbus_obs_is_chan_notification_masked(&msub1, &chan_testing_01, &is_masked); zassert_true(is_masked, NULL); _pub_and_sync(); zassert_true(prio == 2, "The priority must be 2, but it is %d", prio); zbus_obs_set_chan_notification_mask(&msub1, &chan_testing_01, false); ++msg.seq; zbus_obs_set_enable(&msub1, false); zbus_obs_set_enable(&sub1, false); _pub_and_sync(); zassert_true(prio == 8, "The priority must be 8, but it is %d", prio); zbus_obs_set_chan_notification_mask(&msub1, &chan_testing_01, false); zbus_obs_set_enable(&msub1, true); zbus_obs_set_enable(&sub1, true); ++msg.seq; msg.must_detach = true; _pub_and_sync(); zassert_true(prio == 1, "The priority must be 1, but it is %d", prio); ++msg.seq; /* Checking if the detach command took effect on both observers */ _pub_and_sync(); zassert_true(prio == 8, "The priority must be 8, but it is %d", prio); } ZTEST_SUITE(hlp_priority_boost, NULL, NULL, NULL, NULL, NULL);