tests: kernel: semaphore: better explain test failures

Debugging long-tail semaphore test failures currently is rather
annoying, both because many semaphore test failures do not print
their failing values, and because some semaphore tests do not
check return codes, leading to test failures well after the actual
failure.

Redo the semaphore tests to at least give consistent failure
messages including the actual return code and consistently check
return codes of k_sem_* APIs.

Also driveby-fix several places that used an insufficiently-
sized type to store k_uptime.

Signed-off-by: James Harris <james.harris@intel.com>
This commit is contained in:
James Harris 2021-03-04 13:51:33 -08:00 committed by Anas Nashif
commit 269794878c

View file

@ -22,6 +22,33 @@
#define SEC2MS(s) ((s) * 1000) #define SEC2MS(s) ((s) * 1000)
#define expect_k_sem_take(sem, timeout, exp, str) do { \
int _act = k_sem_take((sem), (timeout)); \
int _exp = (exp); \
zassert_equal(_act, _exp, (str), _act, _exp); \
} while (0)
#define expect_k_sem_init(sem, init, max, exp, str) do { \
int _act = k_sem_init((sem), (init), (max)); \
int _exp = (exp); \
zassert_equal(_act, _exp, (str), _act, _exp); \
} while (0)
#define expect_k_sem_count_get(sem, exp, str) do { \
unsigned int _act = k_sem_count_get(sem); \
unsigned int _exp = (exp); \
zassert_equal(_act, _exp, (str), _act, _exp); \
} while (0)
#define expect_k_sem_take_nomsg(sem, timeout, exp) \
expect_k_sem_take((sem), (timeout), (exp), "k_sem_take incorrect return value: %d != %d")
#define expect_k_sem_init_nomsg(sem, init, max, exp) \
expect_k_sem_init((sem), (init), (max), (exp), \
"k_sem_init incorrect return value: %d != %d")
#define expect_k_sem_count_get_nomsg(sem, exp) \
expect_k_sem_count_get((sem), (exp), "k_sem_count_get incorrect return value: %u != %u")
extern void test_sem_give_null(void); extern void test_sem_give_null(void);
extern void test_sem_init_null(void); extern void test_sem_init_null(void);
extern void test_sem_take_null(void); extern void test_sem_take_null(void);
@ -82,7 +109,7 @@ static void tsema_thread_thread(struct k_sem *psem)
K_PRIO_PREEMPT(0), K_PRIO_PREEMPT(0),
K_USER | K_INHERIT_PERMS, K_NO_WAIT); K_USER | K_INHERIT_PERMS, K_NO_WAIT);
zassert_false(k_sem_take(psem, K_FOREVER), NULL); expect_k_sem_take_nomsg(psem, K_FOREVER, 0);
/*clean the spawn thread avoid side effect in next TC*/ /*clean the spawn thread avoid side effect in next TC*/
k_thread_abort(tid); k_thread_abort(tid);
@ -92,13 +119,18 @@ static void tsema_thread_isr(struct k_sem *psem)
{ {
/**TESTPOINT: thread-isr sync via sema*/ /**TESTPOINT: thread-isr sync via sema*/
irq_offload(isr_sem_give, (const void *)psem); irq_offload(isr_sem_give, (const void *)psem);
zassert_false(k_sem_take(psem, K_FOREVER), NULL);
expect_k_sem_take_nomsg(psem, K_FOREVER, 0);
} }
void isr_sem_take(const void *semaphore) void isr_sem_take(const void *semaphore)
{ {
k_sem_take((struct k_sem *)semaphore, K_NO_WAIT); int ret = k_sem_take((struct k_sem *)semaphore, K_NO_WAIT);
if (ret != 0 && ret != -EBUSY) {
zassert_true(false, "incorrect k_sem_take return: %d", ret);
}
} }
@ -116,45 +148,25 @@ void sem_take_timeout_isr_helper(void *p1, void *p2, void *p3)
void sem_take_multiple_low_prio_helper(void *p1, void *p2, void *p3) void sem_take_multiple_low_prio_helper(void *p1, void *p2, void *p3)
{ {
int32_t ret_value; expect_k_sem_take_nomsg(&low_prio_sem, K_FOREVER, 0);
expect_k_sem_take_nomsg(&multiple_thread_sem, K_FOREVER, 0);
ret_value = k_sem_take(&low_prio_sem, K_FOREVER);
zassert_true(ret_value == 0, "k_sem_take failed with returned %d",
ret_value);
ret_value = k_sem_take(&multiple_thread_sem, K_FOREVER);
zassert_true(ret_value == 0, "k_sem_take failed with returned %d",
ret_value);
k_sem_give(&low_prio_sem); k_sem_give(&low_prio_sem);
} }
void sem_take_multiple_mid_prio_helper(void *p1, void *p2, void *p3) void sem_take_multiple_mid_prio_helper(void *p1, void *p2, void *p3)
{ {
int32_t ret_value; expect_k_sem_take_nomsg(&mid_prio_sem, K_FOREVER, 0);
expect_k_sem_take_nomsg(&multiple_thread_sem, K_FOREVER, 0);
ret_value = k_sem_take(&mid_prio_sem, K_FOREVER);
zassert_true(ret_value == 0, "k_sem_take failed with returned %d",
ret_value);
ret_value = k_sem_take(&multiple_thread_sem, K_FOREVER);
zassert_true(ret_value == 0, "k_sem_take failed with returned %d",
ret_value);
k_sem_give(&mid_prio_sem); k_sem_give(&mid_prio_sem);
} }
void sem_take_multiple_high_prio_helper(void *p1, void *p2, void *p3) void sem_take_multiple_high_prio_helper(void *p1, void *p2, void *p3)
{ {
int32_t ret_value;
ret_value = k_sem_take(&high_prio_sem, K_FOREVER); expect_k_sem_take_nomsg(&high_prio_sem, K_FOREVER, 0);
zassert_true(ret_value == 0, "k_sem_take failed with returned %d", expect_k_sem_take_nomsg(&multiple_thread_sem, K_FOREVER, 0);
ret_value);
ret_value = k_sem_take(&multiple_thread_sem, K_FOREVER);
zassert_true(ret_value == 0, "k_sem_take failed with returned %d",
ret_value);
k_sem_give(&high_prio_sem); k_sem_give(&high_prio_sem);
} }
@ -163,7 +175,7 @@ void sem_take_multiple_high_prio_helper(void *p1, void *p2, void *p3)
void sem_queue_mutual_exclusion1(void *p1, void *p2, void *p3) void sem_queue_mutual_exclusion1(void *p1, void *p2, void *p3)
{ {
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
k_sem_take(&mut_sem, K_FOREVER); expect_k_sem_take_nomsg(&mut_sem, K_FOREVER, 0);
/* in that function critical section makes critical var +1 */ /* in that function critical section makes critical var +1 */
critical_var += 1; critical_var += 1;
@ -181,7 +193,7 @@ void sem_queue_mutual_exclusion1(void *p1, void *p2, void *p3)
void sem_queue_mutual_exclusion2(void *p1, void *p2, void *p3) void sem_queue_mutual_exclusion2(void *p1, void *p2, void *p3)
{ {
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
k_sem_take(&mut_sem, K_FOREVER); expect_k_sem_take_nomsg(&mut_sem, K_FOREVER, 0);
/* in that function critical section makes critical var 0 */ /* in that function critical section makes critical var 0 */
critical_var -= 1; critical_var -= 1;
@ -197,15 +209,8 @@ void sem_queue_mutual_exclusion2(void *p1, void *p2, void *p3)
void sem_take_multiple_high_prio_long_helper(void *p1, void *p2, void *p3) void sem_take_multiple_high_prio_long_helper(void *p1, void *p2, void *p3)
{ {
int32_t ret_value; expect_k_sem_take_nomsg(&high_prio_long_sem, K_FOREVER, 0);
expect_k_sem_take_nomsg(&multiple_thread_sem, K_FOREVER, 0);
ret_value = k_sem_take(&high_prio_long_sem, K_FOREVER);
zassert_true(ret_value == 0, "k_sem_take failed with returned %d",
ret_value);
ret_value = k_sem_take(&multiple_thread_sem, K_FOREVER);
zassert_true(ret_value == 0, "k_sem_take failed with returned %d",
ret_value);
k_sem_give(&high_prio_long_sem); k_sem_give(&high_prio_long_sem);
} }
@ -226,16 +231,10 @@ void sem_take_multiple_high_prio_long_helper(void *p1, void *p2, void *p3)
*/ */
void test_k_sem_define(void) void test_k_sem_define(void)
{ {
uint32_t signal_count;
/* get the semaphore count */
signal_count = k_sem_count_get(&simple_sem);
/* verify the semaphore count equals to initialized value */ /* verify the semaphore count equals to initialized value */
zassert_true(signal_count == SEM_INIT_VAL, expect_k_sem_count_get(&simple_sem, SEM_INIT_VAL,
"semaphore initialized failed at compile time" "semaphore initialized failed at compile time"
"- expected count %d, got %d", "- got %u, expected %u");
SEM_INIT_VAL, signal_count);
} }
/** /**
@ -244,12 +243,8 @@ void test_k_sem_define(void)
*/ */
void test_sem_thread2thread(void) void test_sem_thread2thread(void)
{ {
int ret;
/**TESTPOINT: test k_sem_init sema*/ /**TESTPOINT: test k_sem_init sema*/
ret = k_sem_init(&sema, SEM_INIT_VAL, SEM_MAX_VAL); expect_k_sem_init_nomsg(&sema, SEM_INIT_VAL, SEM_MAX_VAL, 0);
zassert_equal(ret, 0, NULL);
tsema_thread_thread(&sema); tsema_thread_thread(&sema);
@ -263,12 +258,9 @@ void test_sem_thread2thread(void)
*/ */
void test_sem_thread2isr(void) void test_sem_thread2isr(void)
{ {
int ret;
/**TESTPOINT: test k_sem_init sema*/ /**TESTPOINT: test k_sem_init sema*/
ret = k_sem_init(&sema, SEM_INIT_VAL, SEM_MAX_VAL); expect_k_sem_init_nomsg(&sema, SEM_INIT_VAL, SEM_MAX_VAL, 0);
zassert_equal(ret, 0, NULL);
tsema_thread_isr(&sema); tsema_thread_isr(&sema);
/**TESTPOINT: test K_SEM_DEFINE sema*/ /**TESTPOINT: test K_SEM_DEFINE sema*/
@ -285,22 +277,16 @@ void test_sem_thread2isr(void)
*/ */
void test_k_sem_init(void) void test_k_sem_init(void)
{ {
int ret;
/* initialize a semaphore with valid count and max limit */ /* initialize a semaphore with valid count and max limit */
ret = k_sem_init(&sema, SEM_INIT_VAL, SEM_MAX_VAL); expect_k_sem_init_nomsg(&sema, SEM_INIT_VAL, SEM_MAX_VAL, 0);
zassert_equal(ret, 0, "k_sem_init() failed");
k_sem_reset(&sema); k_sem_reset(&sema);
/* initialize a semaphore with invalid max limit */ /* initialize a semaphore with invalid max limit */
ret = k_sem_init(&sema, SEM_INIT_VAL, 0); expect_k_sem_init_nomsg(&sema, SEM_INIT_VAL, 0, -EINVAL);
zassert_equal(ret, -EINVAL, "k_sem_init() with invalid max limit");
/* initialize a semaphore with invalid count */ /* initialize a semaphore with invalid count */
ret = k_sem_init(&sema, SEM_MAX_VAL + 1, SEM_MAX_VAL); expect_k_sem_init_nomsg(&sema, SEM_MAX_VAL + 1, SEM_MAX_VAL, -EINVAL);
zassert_equal(ret, -EINVAL, "k_sem_init with invalid count");
} }
@ -310,20 +296,27 @@ void test_k_sem_init(void)
*/ */
void test_sem_reset(void) void test_sem_reset(void)
{ {
int ret; expect_k_sem_init_nomsg(&sema, SEM_INIT_VAL, SEM_MAX_VAL, 0);
expect_k_sem_count_get_nomsg(&sema, 0);
ret = k_sem_init(&sema, SEM_INIT_VAL, SEM_MAX_VAL);
zassert_equal(ret, 0, NULL);
k_sem_give(&sema); k_sem_give(&sema);
expect_k_sem_count_get_nomsg(&sema, 1);
k_sem_reset(&sema); k_sem_reset(&sema);
zassert_false(k_sem_count_get(&sema), NULL); expect_k_sem_count_get_nomsg(&sema, 0);
/**TESTPOINT: semaphore take return -EBUSY*/ /**TESTPOINT: semaphore take return -EBUSY*/
zassert_equal(k_sem_take(&sema, K_NO_WAIT), -EBUSY, NULL); expect_k_sem_take_nomsg(&sema, K_NO_WAIT, -EBUSY);
expect_k_sem_count_get_nomsg(&sema, 0);
/**TESTPOINT: semaphore take return -EAGAIN*/ /**TESTPOINT: semaphore take return -EAGAIN*/
zassert_equal(k_sem_take(&sema, SEM_TIMEOUT), -EAGAIN, NULL); expect_k_sem_take_nomsg(&sema, SEM_TIMEOUT, -EAGAIN);
expect_k_sem_count_get_nomsg(&sema, 0);
k_sem_give(&sema); k_sem_give(&sema);
zassert_false(k_sem_take(&sema, K_FOREVER), NULL); expect_k_sem_count_get_nomsg(&sema, 1);
expect_k_sem_take_nomsg(&sema, K_FOREVER, 0);
expect_k_sem_count_get_nomsg(&sema, 0);
} }
/** /**
@ -332,25 +325,22 @@ void test_sem_reset(void)
*/ */
void test_sem_count_get(void) void test_sem_count_get(void)
{ {
int ret; expect_k_sem_init_nomsg(&sema, SEM_INIT_VAL, SEM_MAX_VAL, 0);
ret = k_sem_init(&sema, SEM_INIT_VAL, SEM_MAX_VAL);
zassert_equal(ret, 0, NULL);
/**TESTPOINT: semaphore count get upon init*/ /**TESTPOINT: semaphore count get upon init*/
zassert_equal(k_sem_count_get(&sema), SEM_INIT_VAL, NULL); expect_k_sem_count_get_nomsg(&sema, SEM_INIT_VAL);
k_sem_give(&sema); k_sem_give(&sema);
/**TESTPOINT: sem count get after give*/ /**TESTPOINT: sem count get after give*/
zassert_equal(k_sem_count_get(&sema), SEM_INIT_VAL + 1, NULL); expect_k_sem_count_get_nomsg(&sema, SEM_INIT_VAL + 1);
k_sem_take(&sema, K_FOREVER); expect_k_sem_take_nomsg(&sema, K_FOREVER, 0);
/**TESTPOINT: sem count get after take*/ /**TESTPOINT: sem count get after take*/
for (int i = 0; i < SEM_MAX_VAL; i++) { for (int i = 0; i < SEM_MAX_VAL; i++) {
zassert_equal(k_sem_count_get(&sema), SEM_INIT_VAL + i, NULL); expect_k_sem_count_get_nomsg(&sema, SEM_INIT_VAL + i);
k_sem_give(&sema); k_sem_give(&sema);
} }
/**TESTPOINT: semaphore give above limit*/ /**TESTPOINT: semaphore give above limit*/
k_sem_give(&sema); k_sem_give(&sema);
zassert_equal(k_sem_count_get(&sema), SEM_MAX_VAL, NULL); expect_k_sem_count_get_nomsg(&sema, SEM_MAX_VAL);
} }
@ -367,24 +357,19 @@ void test_sem_count_get(void)
*/ */
void test_sem_give_from_isr(void) void test_sem_give_from_isr(void)
{ {
uint32_t signal_count;
/* /*
* Signal the semaphore several times from an ISR. After each signal, * Signal the semaphore several times from an ISR. After each signal,
* check the signal count. * check the signal count.
*/ */
k_sem_reset(&simple_sem); k_sem_reset(&simple_sem);
expect_k_sem_count_get_nomsg(&simple_sem, 0);
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
sem_give_from_isr(&simple_sem); sem_give_from_isr(&simple_sem);
signal_count = k_sem_count_get(&simple_sem); expect_k_sem_count_get_nomsg(&simple_sem, i + 1);
zassert_true(signal_count == (i + 1),
"signal count missmatch - expected %d, got %d",
(i + 1), signal_count);
} }
} }
/** /**
@ -400,22 +385,18 @@ void test_sem_give_from_isr(void)
*/ */
void test_sem_give_from_thread(void) void test_sem_give_from_thread(void)
{ {
uint32_t signal_count;
/* /*
* Signal the semaphore several times from a task. After each signal, * Signal the semaphore several times from a task. After each signal,
* check the signal count. * check the signal count.
*/ */
k_sem_reset(&simple_sem); k_sem_reset(&simple_sem);
expect_k_sem_count_get_nomsg(&simple_sem, 0);
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
k_sem_give(&simple_sem); k_sem_give(&simple_sem);
signal_count = k_sem_count_get(&simple_sem); expect_k_sem_count_get_nomsg(&simple_sem, i + 1);
zassert_true(signal_count == (i + 1),
"signal count missmatch - expected %d, got %d",
(i + 1), signal_count);
} }
} }
@ -426,9 +407,6 @@ void test_sem_give_from_thread(void)
*/ */
void test_sem_take_no_wait(void) void test_sem_take_no_wait(void)
{ {
uint32_t signal_count;
int32_t ret_value;
/* /*
* Test the semaphore without wait. Check the signal count after each * Test the semaphore without wait. Check the signal count after each
* attempt (it should be decrementing by 1 each time). * attempt (it should be decrementing by 1 each time).
@ -440,17 +418,9 @@ void test_sem_take_no_wait(void)
} }
for (int i = 4; i >= 0; i--) { for (int i = 4; i >= 0; i--) {
ret_value = k_sem_take(&simple_sem, K_NO_WAIT); expect_k_sem_take_nomsg(&simple_sem, K_NO_WAIT, 0);
zassert_true(ret_value == 0, expect_k_sem_count_get_nomsg(&simple_sem, i);
"unable to do k_sem_take which returned %d",
ret_value);
signal_count = k_sem_count_get(&simple_sem);
zassert_true(signal_count == i,
"signal count missmatch - expected %d, got %d",
i, signal_count);
} }
} }
/** /**
@ -459,25 +429,16 @@ void test_sem_take_no_wait(void)
*/ */
void test_sem_take_no_wait_fails(void) void test_sem_take_no_wait_fails(void)
{ {
uint32_t signal_count;
int32_t ret_value;
/* /*
* Test the semaphore without wait. Check the signal count after each * Test the semaphore without wait. Check the signal count after each
* attempt (it should be decrementing by 1 each time). * attempt (it should be always zero).
*/ */
k_sem_reset(&simple_sem); k_sem_reset(&simple_sem);
for (int i = 4; i >= 0; i--) { for (int i = 4; i >= 0; i--) {
ret_value = k_sem_take(&simple_sem, K_NO_WAIT); expect_k_sem_take_nomsg(&simple_sem, K_NO_WAIT, -EBUSY);
zassert_true(ret_value == -EBUSY, expect_k_sem_count_get_nomsg(&simple_sem, 0);
"k_sem_take returned when not possible");
signal_count = k_sem_count_get(&simple_sem);
zassert_true(signal_count == 0U,
"signal count missmatch - expected 0, got %d",
signal_count);
} }
} }
@ -495,20 +456,12 @@ void test_sem_take_timeout_fails(void)
/* /*
* Test the semaphore with timeout without a k_sem_give. * Test the semaphore with timeout without a k_sem_give.
*/ */
int32_t ret_value;
uint32_t signal_count;
k_sem_reset(&simple_sem); k_sem_reset(&simple_sem);
expect_k_sem_count_get_nomsg(&simple_sem, 0);
signal_count = k_sem_count_get(&simple_sem);
zassert_true(signal_count == 0U, "k_sem_reset failed");
/* take an unavailable semaphore and wait it until timeout */ /* take an unavailable semaphore and wait it until timeout */
for (int i = 4; i >= 0; i--) { for (int i = 4; i >= 0; i--) {
ret_value = k_sem_take(&simple_sem, SEM_TIMEOUT); expect_k_sem_take_nomsg(&simple_sem, SEM_TIMEOUT, -EAGAIN);
zassert_true(ret_value == -EAGAIN,
"k_sem_take succeeded when it's not possible");
} }
} }
@ -523,9 +476,6 @@ void test_sem_take_timeout_fails(void)
*/ */
void test_sem_take_timeout(void) void test_sem_take_timeout(void)
{ {
int32_t ret_value;
uint32_t signal_count;
/* /*
* Signal the semaphore upon which the other thread is waiting. * Signal the semaphore upon which the other thread is waiting.
* The thread (which is at a lower priority) will cause simple_sem * The thread (which is at a lower priority) will cause simple_sem
@ -540,15 +490,12 @@ void test_sem_take_timeout(void)
k_sem_reset(&simple_sem); k_sem_reset(&simple_sem);
signal_count = k_sem_count_get(&simple_sem); expect_k_sem_count_get_nomsg(&simple_sem, 0);
zassert_true(signal_count == 0U, "k_sem_reset failed");
/* Take semaphore and wait it given by other threads /* Take semaphore and wait it given by other threads
* in specified timeout * in specified timeout
*/ */
ret_value = k_sem_take(&simple_sem, SEM_TIMEOUT); expect_k_sem_take_nomsg(&simple_sem, SEM_TIMEOUT, 0);
zassert_true(ret_value == 0, "k_sem_take failed with returned %d",
ret_value);
k_thread_abort(&sem_tid_1); k_thread_abort(&sem_tid_1);
} }
@ -564,9 +511,6 @@ void test_sem_take_timeout(void)
*/ */
void test_sem_take_timeout_forever(void) void test_sem_take_timeout_forever(void)
{ {
int32_t ret_value;
uint32_t signal_count;
/* /*
* Signal the semaphore upon which the another thread is waiting. The * Signal the semaphore upon which the another thread is waiting. The
* thread (which is at a lower priority) will cause simple_sem * thread (which is at a lower priority) will cause simple_sem
@ -580,17 +524,13 @@ void test_sem_take_timeout_forever(void)
k_sem_reset(&simple_sem); k_sem_reset(&simple_sem);
signal_count = k_sem_count_get(&simple_sem); expect_k_sem_count_get_nomsg(&simple_sem, 0);
zassert_true(signal_count == 0U, "k_sem_reset failed");
/* Take semaphore and wait it given by /* Take semaphore and wait it given by
* other threads forever until it's available * other threads forever until it's available
*/ */
ret_value = k_sem_take(&simple_sem, K_FOREVER); expect_k_sem_take_nomsg(&simple_sem, K_FOREVER, 0);
zassert_true(ret_value == 0, "k_sem_take failed with returned %d",
ret_value);
k_thread_abort(&sem_tid_1); k_thread_abort(&sem_tid_1);
} }
/** /**
@ -599,8 +539,6 @@ void test_sem_take_timeout_forever(void)
*/ */
void test_sem_take_timeout_isr(void) void test_sem_take_timeout_isr(void)
{ {
int32_t ret_value;
/* /*
* Signal the semaphore upon which the another thread is waiting. The * Signal the semaphore upon which the another thread is waiting. The
* thread (which is at a lower priority) will cause simple_sem * thread (which is at a lower priority) will cause simple_sem
@ -613,9 +551,7 @@ void test_sem_take_timeout_isr(void)
k_sem_reset(&simple_sem); k_sem_reset(&simple_sem);
ret_value = k_sem_take(&simple_sem, SEM_TIMEOUT); expect_k_sem_take_nomsg(&simple_sem, SEM_TIMEOUT, 0);
zassert_true(ret_value == 0, "k_sem_take failed");
} }
/** /**
@ -625,11 +561,8 @@ void test_sem_take_timeout_isr(void)
*/ */
void test_sem_take_multiple(void) void test_sem_take_multiple(void)
{ {
uint32_t signal_count;
k_sem_reset(&multiple_thread_sem); k_sem_reset(&multiple_thread_sem);
signal_count = k_sem_count_get(&multiple_thread_sem); expect_k_sem_count_get_nomsg(&multiple_thread_sem, 0);
zassert_true(signal_count == 0U, "k_sem_reset failed");
/* /*
* Signal the semaphore upon which the another thread is waiting. * Signal the semaphore upon which the another thread is waiting.
@ -691,83 +624,69 @@ void test_sem_take_multiple(void)
k_sleep(K_MSEC(200)); k_sleep(K_MSEC(200));
/* check which threads completed */ /* check which threads completed */
signal_count = k_sem_count_get(&high_prio_long_sem); expect_k_sem_count_get(&high_prio_long_sem, 1,
zassert_true(signal_count == 1U,
"High priority and long waiting thread " "High priority and long waiting thread "
"don't get the sem"); "don't get the sem: %u != %u");
signal_count = k_sem_count_get(&high_prio_sem); expect_k_sem_count_get(&high_prio_sem, 0U,
zassert_true(signal_count == 0U, "High priority thread shouldn't get the sem: %u != %u");
"High priority thread shouldn't get the sem");
signal_count = k_sem_count_get(&mid_prio_sem); expect_k_sem_count_get(&mid_prio_sem, 0U,
zassert_true(signal_count == 0U, "Medium priority threads shouldn't have executed: %u != %u");
"Medium priority threads shouldn't have executed");
signal_count = k_sem_count_get(&low_prio_sem); expect_k_sem_count_get(&low_prio_sem, 0U,
zassert_true(signal_count == 0U, "Low priority threads shouldn't have executed: %u != %u");
"Low priority threads shouldn't have executed");
/* enable the high prio thread sem_tid_4 to run */ /* enable the high prio thread sem_tid_4 to run */
k_sem_give(&multiple_thread_sem); k_sem_give(&multiple_thread_sem);
k_sleep(K_MSEC(200)); k_sleep(K_MSEC(200));
/* check which threads completed */ /* check which threads completed */
signal_count = k_sem_count_get(&high_prio_long_sem); expect_k_sem_count_get(&high_prio_long_sem, 1U,
zassert_true(signal_count == 1U, "High priority and long waiting thread" "High priority and long waiting thread executed again: %u != %u");
" executed again");
signal_count = k_sem_count_get(&high_prio_sem); expect_k_sem_count_get(&high_prio_sem, 1U,
zassert_true(signal_count == 1U, "Higher priority thread did not get the sem: %u != %u");
"Higher priority thread did not get the sem");
signal_count = k_sem_count_get(&mid_prio_sem); expect_k_sem_count_get(&mid_prio_sem, 0U,
zassert_true(signal_count == 0U, "Medium priority thread shouldn't get the sem: %u != %u");
"Medium priority thread shouldn't get the sem");
signal_count = k_sem_count_get(&low_prio_sem); expect_k_sem_count_get(&low_prio_sem, 0U,
zassert_true(signal_count == 0U, "Low priority thread shouldn't get the sem: %u != %u");
"Low priority thread shouldn't get the sem");
/* enable the mid prio thread sem_tid_2 to run */ /* enable the mid prio thread sem_tid_2 to run */
k_sem_give(&multiple_thread_sem); k_sem_give(&multiple_thread_sem);
k_sleep(K_MSEC(200)); k_sleep(K_MSEC(200));
/* check which threads completed */ /* check which threads completed */
signal_count = k_sem_count_get(&high_prio_long_sem); expect_k_sem_count_get(&high_prio_long_sem, 1U,
zassert_true(signal_count == 1U, "High priority and long waiting thread" "High priority and long waiting thread executed again: %u != %u");
" executed again");
signal_count = k_sem_count_get(&high_prio_sem); expect_k_sem_count_get(&high_prio_sem, 1U,
zassert_true(signal_count == 1U, "High priority thread executed again: %u != %u");
"High priority thread executed again");
signal_count = k_sem_count_get(&mid_prio_sem); expect_k_sem_count_get(&mid_prio_sem, 1U,
zassert_true(signal_count == 1U, "Medium priority thread did not get the sem: %u != %u");
"Medium priority thread did not get the sem");
signal_count = k_sem_count_get(&low_prio_sem); expect_k_sem_count_get(&low_prio_sem, 0U,
zassert_true(signal_count == 0U, "Low priority thread did not get the sem: %u != %u");
"Low priority thread did not get the sem");
/* enable the low prio thread(thread_1) to run */ /* enable the low prio thread(thread_1) to run */
k_sem_give(&multiple_thread_sem); k_sem_give(&multiple_thread_sem);
k_sleep(K_MSEC(200)); k_sleep(K_MSEC(200));
/* check the thread completed */ /* check the thread completed */
signal_count = k_sem_count_get(&high_prio_long_sem); expect_k_sem_count_get(&high_prio_long_sem, 1U,
zassert_true(signal_count == 1U, "High priority and long waiting thread" "High priority and long waiting thread executed again: %u != %u");
" executed again");
signal_count = k_sem_count_get(&high_prio_sem); expect_k_sem_count_get(&high_prio_sem, 1U,
zassert_true(signal_count == 1U, "High priority thread executed again"); "High priority thread executed again: %u != %u");
signal_count = k_sem_count_get(&mid_prio_sem); expect_k_sem_count_get(&mid_prio_sem, 1U,
zassert_true(signal_count == 1U, "Mid priority thread executed again"); "Mid priority thread executed again: %u != %u");
signal_count = k_sem_count_get(&low_prio_sem); expect_k_sem_count_get(&low_prio_sem, 1U,
zassert_true(signal_count == 1U, "Low priority thread did not get the sem: %u != %u");
"Low priority thread did not get the sem");
} }
/** /**
@ -785,23 +704,17 @@ void test_sem_take_multiple(void)
*/ */
void test_k_sem_correct_count_limit(void) void test_k_sem_correct_count_limit(void)
{ {
uint32_t signal_count;
int32_t ret;
/* reset an initialized semaphore's count to zero */ /* reset an initialized semaphore's count to zero */
k_sem_reset(&simple_sem); k_sem_reset(&simple_sem);
signal_count = k_sem_count_get(&simple_sem); expect_k_sem_count_get(&simple_sem, 0U, "k_sem_reset failed: %u != %u");
zassert_true(signal_count == 0U, "k_sem_reset failed");
/* Give the semaphore by a thread and verify the semaphore's /* Give the semaphore by a thread and verify the semaphore's
* count is as expected * count is as expected
*/ */
for (int i = 1; i <= SEM_MAX_VAL; i++) { for (int i = 1; i <= SEM_MAX_VAL; i++) {
k_sem_give(&simple_sem); k_sem_give(&simple_sem);
signal_count = k_sem_count_get(&simple_sem); expect_k_sem_count_get_nomsg(&simple_sem, i);
zassert_true(signal_count == i,
"semaphore count mismatch - expected %d, got %d",
i, signal_count);
} }
/* Verify the max count a semaphore can reach /* Verify the max count a semaphore can reach
@ -810,24 +723,15 @@ void test_k_sem_correct_count_limit(void)
*/ */
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
k_sem_give(&simple_sem); k_sem_give(&simple_sem);
signal_count = k_sem_count_get(&simple_sem); expect_k_sem_count_get_nomsg(&simple_sem, SEM_MAX_VAL);
zassert_true(signal_count == SEM_MAX_VAL,
"semaphore count mismatch - expected %d, got %d",
SEM_MAX_VAL, signal_count);
} }
/* Take the semaphore by a thread and verify the semaphore's /* Take the semaphore by a thread and verify the semaphore's
* count is as expected * count is as expected
*/ */
for (int i = SEM_MAX_VAL - 1; i >= 0; i--) { for (int i = SEM_MAX_VAL - 1; i >= 0; i--) {
ret = k_sem_take(&simple_sem, K_NO_WAIT); expect_k_sem_take_nomsg(&simple_sem, K_NO_WAIT, 0);
zassert_true(ret == 0, "k_sem_take failed with returned %d", expect_k_sem_count_get_nomsg(&simple_sem, i);
ret);
signal_count = k_sem_count_get(&simple_sem);
zassert_true(signal_count == i,
"semaphore count mismatch - expected %d, got %d",
i, signal_count);
} }
/* Verify the max times a semaphore can be taken /* Verify the max times a semaphore can be taken
@ -835,14 +739,9 @@ void test_k_sem_correct_count_limit(void)
* it's count will be zero * it's count will be zero
*/ */
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
ret = k_sem_take(&simple_sem, K_NO_WAIT); expect_k_sem_take_nomsg(&simple_sem, K_NO_WAIT, -EBUSY);
zassert_true(ret == -EBUSY,
"k_sem_take failed with returned %d", ret);
signal_count = k_sem_count_get(&simple_sem); expect_k_sem_count_get_nomsg(&simple_sem, 0U);
zassert_true(signal_count == 0U,
"semaphore count mismatch - expected %d, got %d",
0, signal_count);
} }
} }
@ -852,30 +751,20 @@ void test_k_sem_correct_count_limit(void)
*/ */
void test_sem_give_take_from_isr(void) void test_sem_give_take_from_isr(void)
{ {
uint32_t signal_count;
k_sem_reset(&simple_sem); k_sem_reset(&simple_sem);
signal_count = k_sem_count_get(&simple_sem); expect_k_sem_count_get_nomsg(&simple_sem, 0U);
zassert_true(signal_count == 0U, "k_sem_reset failed");
/* give semaphore from an isr and do a check for the count */ /* give semaphore from an isr and do a check for the count */
for (int i = 0; i < SEM_MAX_VAL; i++) { for (int i = 0; i < SEM_MAX_VAL; i++) {
sem_give_from_isr(&simple_sem); sem_give_from_isr(&simple_sem);
expect_k_sem_count_get_nomsg(&simple_sem, i + 1);
signal_count = k_sem_count_get(&simple_sem);
zassert_true(signal_count == i + 1,
"signal count missmatch - expected %d, got %d",
i + 1, signal_count);
} }
/* take semaphore from an isr and do a check for the count */ /* take semaphore from an isr and do a check for the count */
for (int i = SEM_MAX_VAL; i > 0; i--) { for (int i = SEM_MAX_VAL; i > 0; i--) {
sem_take_from_isr(&simple_sem); sem_take_from_isr(&simple_sem);
signal_count = k_sem_count_get(&simple_sem); expect_k_sem_count_get_nomsg(&simple_sem, i - 1);
zassert_true(signal_count == (i - 1),
"signal count missmatch - expected %d, got %d",
(i - 1), signal_count);
} }
} }
@ -886,7 +775,7 @@ void test_sem_give_take_from_isr(void)
void sem_multiple_threads_wait_helper(void *p1, void *p2, void *p3) void sem_multiple_threads_wait_helper(void *p1, void *p2, void *p3)
{ {
/* get blocked until the test thread gives the semaphore */ /* get blocked until the test thread gives the semaphore */
k_sem_take(&multiple_thread_sem, K_FOREVER); expect_k_sem_take_nomsg(&multiple_thread_sem, K_FOREVER, 0);
/* inform the test thread that this thread has got multiple_thread_sem*/ /* inform the test thread that this thread has got multiple_thread_sem*/
k_sem_give(&simple_sem); k_sem_give(&simple_sem);
@ -900,14 +789,13 @@ void sem_multiple_threads_wait_helper(void *p1, void *p2, void *p3)
*/ */
void test_sem_multiple_threads_wait(void) void test_sem_multiple_threads_wait(void)
{ {
uint32_t signal_count;
int32_t ret_value;
uint32_t repeat_count = 0U;
k_sem_reset(&simple_sem); k_sem_reset(&simple_sem);
k_sem_reset(&multiple_thread_sem); k_sem_reset(&multiple_thread_sem);
do { /* Verify a wait q that has been emptied / reset
* correctly by running twice.
*/
for (int repeat_count = 0; repeat_count < 2; repeat_count++) {
for (int i = 0; i < TOTAL_THREADS_WAITING; i++) { for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
k_thread_create(&multiple_tid[i], k_thread_create(&multiple_tid[i],
multiple_stack[i], STACK_SIZE, multiple_stack[i], STACK_SIZE,
@ -930,27 +818,14 @@ void test_sem_multiple_threads_wait(void)
/* check if all the threads are done. */ /* check if all the threads are done. */
for (int i = 0; i < TOTAL_THREADS_WAITING; i++) { for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
ret_value = k_sem_take(&simple_sem, K_FOREVER); expect_k_sem_take(&simple_sem, K_FOREVER, 0,
zassert_true(ret_value == 0, "Some of the threads did not get multiple_thread_sem: %d != %d");
"Some of the threads did not get multiple_thread_sem"
);
} }
signal_count = k_sem_count_get(&simple_sem); expect_k_sem_count_get_nomsg(&simple_sem, 0U);
zassert_true(signal_count == 0U, expect_k_sem_count_get_nomsg(&multiple_thread_sem, 0U);
"signal count missmatch - expected 0, got %d",
signal_count);
signal_count = k_sem_count_get(&multiple_thread_sem); }
zassert_true(signal_count == 0U,
"signal count missmatch - expected 0, got %d",
signal_count);
/* Verify a wait q that has been emptied / reset
* correctly by running again.
*/
repeat_count++;
} while (repeat_count < 2);
} }
/** /**
@ -960,37 +835,45 @@ void test_sem_multiple_threads_wait(void)
*/ */
void test_sem_measure_timeouts(void) void test_sem_measure_timeouts(void)
{ {
int32_t ret_value; int64_t start_ticks, end_ticks, diff_ticks;
uint32_t start_ticks, end_ticks;
k_sem_reset(&simple_sem); k_sem_reset(&simple_sem);
/* with timeout of 1 sec */ /* with timeout of 1 sec */
start_ticks = k_uptime_get(); start_ticks = k_uptime_get();
ret_value = k_sem_take(&simple_sem, K_SECONDS(1)); expect_k_sem_take_nomsg(&simple_sem, K_SECONDS(1), -EAGAIN);
end_ticks = k_uptime_get(); end_ticks = k_uptime_get();
zassert_true(ret_value == -EAGAIN, "k_sem_take failed"); diff_ticks = end_ticks - start_ticks;
zassert_true((end_ticks - start_ticks >= SEC2MS(1)), zassert_true((diff_ticks >= SEC2MS(1)),
"time missmatch - expected %d, got %d", "k_sem_take returned too early: %lld < %d",
SEC2MS(1), end_ticks - start_ticks); diff_ticks, SEC2MS(1));
/* with 0 as the timeout */ /* This subtest could fail spuriously if we happened to run the below right as
* a tick occurred. Unfortunately, we cannot actually fix this, because on some
* emulated platforms time does not advance while running the cpu, so
* if we spin and wait for a tick boundary we'll spin forever.
* The best we can do is hope that k_busy_wait finishes just after a tick boundary.
*/
k_busy_wait(1);
start_ticks = k_uptime_get(); start_ticks = k_uptime_get();
ret_value = k_sem_take(&simple_sem, K_NO_WAIT); expect_k_sem_take_nomsg(&simple_sem, K_NO_WAIT, -EBUSY);
end_ticks = k_uptime_get(); end_ticks = k_uptime_get();
zassert_true(ret_value == -EBUSY, "k_sem_take failed"); diff_ticks = end_ticks - start_ticks;
zassert_true((end_ticks - start_ticks < 1), zassert_true(end_ticks >= start_ticks,
"time missmatch - expected %d, got %d", "time went backwards: %lld -> %lld",
1, end_ticks - start_ticks); start_ticks, end_ticks);
zassert_true(diff_ticks >= 0,
"k_sem_take took too long: %lld != 0",
diff_ticks);
} }
void sem_measure_timeout_from_thread_helper(void *p1, void *p2, void *p3) void sem_measure_timeout_from_thread_helper(void *p1, void *p2, void *p3)
@ -1000,7 +883,6 @@ void sem_measure_timeout_from_thread_helper(void *p1, void *p2, void *p3)
/* give the semaphore */ /* give the semaphore */
k_sem_give(&multiple_thread_sem); k_sem_give(&multiple_thread_sem);
} }
@ -1011,8 +893,7 @@ void sem_measure_timeout_from_thread_helper(void *p1, void *p2, void *p3)
*/ */
void test_sem_measure_timeout_from_thread(void) void test_sem_measure_timeout_from_thread(void)
{ {
int32_t ret_value; int64_t start_ticks, end_ticks, diff_ticks;
uint32_t start_ticks, end_ticks;
k_sem_reset(&simple_sem); k_sem_reset(&simple_sem);
k_sem_reset(&multiple_thread_sem); k_sem_reset(&multiple_thread_sem);
@ -1025,39 +906,40 @@ void test_sem_measure_timeout_from_thread(void)
/* first sync the 2 threads */ /* first sync the 2 threads */
k_sem_take(&simple_sem, K_FOREVER); expect_k_sem_take_nomsg(&simple_sem, K_FOREVER, 0);
/* with timeout of 1 sec */ /* with timeout of 1 sec */
start_ticks = k_uptime_get(); start_ticks = k_uptime_get();
ret_value = k_sem_take(&multiple_thread_sem, K_SECONDS(1)); expect_k_sem_take_nomsg(&multiple_thread_sem, K_SECONDS(1), 0);
end_ticks = k_uptime_get(); end_ticks = k_uptime_get();
zassert_true(ret_value == 0, "k_sem_take failed"); diff_ticks = end_ticks - start_ticks;
zassert_true((end_ticks - start_ticks <= SEC2MS(1)), zassert_true((diff_ticks < SEC2MS(1)),
"time missmatch - expected less than%d ,got %d", "k_sem_take took too long: %d >= %d",
SEC2MS(1), end_ticks - start_ticks); diff_ticks, SEC2MS(1));
} }
void sem_multiple_take_and_timeouts_helper(void *p1, void *p2, void *p3) void sem_multiple_take_and_timeouts_helper(void *p1, void *p2, void *p3)
{ {
int timeout = POINTER_TO_INT(p1); int timeout = POINTER_TO_INT(p1);
uint32_t start_ticks, end_ticks; int64_t start_ticks, end_ticks, diff_ticks;
size_t bytes_written; size_t bytes_written;
start_ticks = k_uptime_get(); start_ticks = k_uptime_get();
k_sem_take(&simple_sem, K_MSEC(timeout)); expect_k_sem_take_nomsg(&simple_sem, K_MSEC(timeout), -EAGAIN);
end_ticks = k_uptime_get(); end_ticks = k_uptime_get();
zassert_true((end_ticks - start_ticks >= timeout), diff_ticks = end_ticks - start_ticks;
"time missmatch - expected less than %d ,got %d",
timeout, end_ticks - start_ticks);
zassert_true(diff_ticks >= timeout,
"time mismatch - expected at least %d, got %lld",
timeout, diff_ticks);
k_pipe_put(&timeout_info_pipe, &timeout, sizeof(int), k_pipe_put(&timeout_info_pipe, &timeout, sizeof(int),
&bytes_written, sizeof(int), K_FOREVER); &bytes_written, sizeof(int), K_FOREVER);
@ -1090,8 +972,9 @@ void test_sem_multiple_take_and_timeouts(void)
for (int i = 0; i < TOTAL_THREADS_WAITING; i++) { for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
k_pipe_get(&timeout_info_pipe, &timeout, sizeof(int), k_pipe_get(&timeout_info_pipe, &timeout, sizeof(int),
&bytes_read, sizeof(int), K_FOREVER); &bytes_read, sizeof(int), K_FOREVER);
zassert_true(timeout == SEC2MS(i + 1), zassert_equal(timeout, SEC2MS(i + 1),
"timeout did not occur properly"); "timeout did not occur properly: %d != %d",
timeout, SEC2MS(i + 1));
} }
/* cleanup */ /* cleanup */
@ -1105,8 +988,7 @@ void sem_multi_take_timeout_diff_sem_helper(void *p1, void *p2, void *p3)
{ {
int timeout = POINTER_TO_INT(p1); int timeout = POINTER_TO_INT(p1);
struct k_sem *sema = p2; struct k_sem *sema = p2;
uint32_t start_ticks, end_ticks; int64_t start_ticks, end_ticks, diff_ticks;
int32_t ret_value;
size_t bytes_written; size_t bytes_written;
struct timeout_info info = { struct timeout_info info = {
.timeout = timeout, .timeout = timeout,
@ -1115,18 +997,18 @@ void sem_multi_take_timeout_diff_sem_helper(void *p1, void *p2, void *p3)
start_ticks = k_uptime_get(); start_ticks = k_uptime_get();
ret_value = k_sem_take(sema, K_MSEC(timeout)); expect_k_sem_take_nomsg(sema, K_MSEC(timeout), -EAGAIN);
end_ticks = k_uptime_get(); end_ticks = k_uptime_get();
zassert_true((end_ticks - start_ticks >= timeout), diff_ticks = end_ticks - start_ticks;
"time missmatch - expected less than %d, got %d",
timeout, end_ticks - start_ticks);
zassert_true(diff_ticks >= timeout,
"time mismatch - expected at least %d, got %lld",
timeout, diff_ticks);
k_pipe_put(&timeout_info_pipe, &info, sizeof(struct timeout_info), k_pipe_put(&timeout_info_pipe, &info, sizeof(struct timeout_info),
&bytes_written, sizeof(struct timeout_info), K_FOREVER); &bytes_written, sizeof(struct timeout_info), K_FOREVER);
} }
/** /**
@ -1154,7 +1036,6 @@ void test_sem_multi_take_timeout_diff_sem(void)
* in which it times out is pushed into a pipe and checked later on. * in which it times out is pushed into a pipe and checked later on.
*/ */
for (int i = 0; i < TOTAL_THREADS_WAITING; i++) { for (int i = 0; i < TOTAL_THREADS_WAITING; i++) {
k_thread_create(&multiple_tid[i], k_thread_create(&multiple_tid[i],
multiple_stack[i], STACK_SIZE, multiple_stack[i], STACK_SIZE,
sem_multi_take_timeout_diff_sem_helper, sem_multi_take_timeout_diff_sem_helper,
@ -1190,7 +1071,7 @@ void test_sem_queue_mutual_exclusion(void)
{ {
critical_var = 0; critical_var = 0;
k_sem_init(&mut_sem, 0, 1); expect_k_sem_init_nomsg(&mut_sem, 0, 1, 0);
k_thread_create(&sem_tid_1, stack_1, STACK_SIZE, k_thread_create(&sem_tid_1, stack_1, STACK_SIZE,
sem_queue_mutual_exclusion1, NULL, NULL, sem_queue_mutual_exclusion1, NULL, NULL,