diff --git a/lib/posix/options/semaphore.c b/lib/posix/options/semaphore.c index 55ac57c5cfd3f..2ab884eccca3d 100644 --- a/lib/posix/options/semaphore.c +++ b/lib/posix/options/semaphore.c @@ -13,6 +13,7 @@ #include #include #include +#include struct nsem_obj { sys_snode_t snode; @@ -90,7 +91,7 @@ int sem_destroy(sem_t *semaphore) return -1; } - if (k_sem_count_get(semaphore)) { + if (z_waitq_head(&semaphore->wait_q) != NULL) { errno = EBUSY; return -1; } diff --git a/tests/posix/semaphores/src/main.c b/tests/posix/semaphores/src/main.c index c8b566349a644..855bb850e82df 100644 --- a/tests/posix/semaphores/src/main.c +++ b/tests/posix/semaphores/src/main.c @@ -21,7 +21,7 @@ BUILD_ASSERT(WAIT_TIME_MS > 0, "WAIT_TIME_MS must be posistive"); /* based on the current structure of this unit test */ BUILD_ASSERT(CONFIG_DYNAMIC_THREAD_POOL_SIZE >= 2, "CONFIG_DYNAMIC_THREAD_POOL_SIZE must be >= 2"); -static void *child_func(void *p1) +static void *child_func_sem_post(void *p1) { sem_t *sem = (sem_t *)p1; @@ -29,9 +29,17 @@ static void *child_func(void *p1) return NULL; } +static void *child_func_sem_wait(void *p1) +{ + sem_t *sem = (sem_t *)p1; + + zassert_equal(sem_wait(sem), 0, "sem_wait failed"); + return NULL; +} + static void semaphore_test(sem_t *sem) { - pthread_t thread1, thread2; + pthread_t thread1, thread2, thread3; int val, ret; struct timespec abstime; @@ -54,7 +62,7 @@ static void semaphore_test(sem_t *sem) zassert_equal(sem_trywait(sem), -1); zassert_equal(errno, EAGAIN); - ret = pthread_create(&thread1, NULL, child_func, sem); + ret = pthread_create(&thread1, NULL, child_func_sem_post, sem); zassert_equal(ret, 0, "Thread creation failed"); zassert_equal(clock_gettime(CLOCK_REALTIME, &abstime), 0, "clock_gettime failed"); @@ -74,24 +82,44 @@ static void semaphore_test(sem_t *sem) zassert_equal(sem_destroy(sem), 0, "semaphore is not destroyed"); /* TESTPOINT: Initialize sema with 1 */ - zassert_equal(sem_init(sem, 0, 1), 0, "sem_init failed"); - zassert_equal(sem_getvalue(sem, &val), 0); - zassert_equal(val, 1); + zassert_equal(sem_init(sem, 0, 0), 0, "sem_init failed"); + + ret = pthread_create(&thread2, NULL, child_func_sem_wait, sem); + zassert_equal(ret, 0, "Thread creation failed"); + /* Switch to the child_func_sem_wait thread */ + ret = sched_yield(); + zassert_equal(ret, 0, "yielding thread failed"); + + /* TESTPOINT: Other thread is waiting for the semaphore, + * check if sem_destroy fails with EBUSY + */ zassert_equal(sem_destroy(sem), -1, "acquired semaphore is destroyed"); zassert_equal(errno, EBUSY); + zassert_equal(sem_post(sem), 0, "sem_post failed"); + zassert_ok(pthread_join(thread2, NULL)); + + /* TESTPOINT: Other thread is no longer waiting for the semaphore, + * sem_destroy should no longer fail with EBUSY + */ + zassert_equal(sem_destroy(sem), 0, "semaphore is not destroyed"); + + /* TESTPOINT: Initialize sema with 1 */ + zassert_equal(sem_init(sem, 0, 1), 0, "sem_init failed"); + /* TESTPOINT: take semaphore which is initialized with 1 */ zassert_equal(sem_trywait(sem), 0); - zassert_equal(pthread_create(&thread2, NULL, child_func, sem), 0, "Thread creation failed"); + zassert_equal(pthread_create(&thread3, NULL, child_func_sem_post, sem), 0, + "Thread creation failed"); /* TESTPOINT: Wait and acquire semaphore till thread2 gives */ zassert_equal(sem_wait(sem), 0, "sem_wait failed"); /* Make sure the threads are terminated */ zassert_ok(pthread_join(thread1, NULL)); - zassert_ok(pthread_join(thread2, NULL)); + zassert_ok(pthread_join(thread3, NULL)); } ZTEST(posix_semaphores, test_semaphore)