Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/posix/options/semaphore.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <zephyr/posix/fcntl.h>
#include <zephyr/posix/pthread.h>
#include <zephyr/posix/semaphore.h>
#include <wait_q.h>

struct nsem_obj {
sys_snode_t snode;
Expand Down Expand Up @@ -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;
}
Expand Down
44 changes: 36 additions & 8 deletions tests/posix/semaphores/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,25 @@ 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;

zassert_equal(sem_post(sem), 0, "sem_post failed");
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;

Expand All @@ -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");
Expand All @@ -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)
Expand Down
Loading