blob: 67fc45016672ab9c953a318ba950decd8fc0c7f5 [file] [log] [blame]
/*
* Copyright (c) 2018 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/ztest.h>
#include <pthread.h>
#include <zephyr/sys/util.h>
#define N_THR 3
#define STACKSZ (1024 + CONFIG_TEST_EXTRA_STACK_SIZE)
K_THREAD_STACK_ARRAY_DEFINE(stack, N_THR, STACKSZ);
pthread_rwlock_t rwlock;
static void *thread_top(void *p1)
{
pthread_t pthread;
uint32_t policy, ret = 0U;
struct sched_param param;
int id = POINTER_TO_INT(p1);
pthread = (pthread_t) pthread_self();
pthread_getschedparam(pthread, &policy, &param);
printk("Thread %d scheduling policy = %d & priority %d started\n",
id, policy, param.sched_priority);
ret = pthread_rwlock_tryrdlock(&rwlock);
if (ret) {
printk("Not able to get RD lock on trying, try again\n");
zassert_false(pthread_rwlock_rdlock(&rwlock),
"Failed to acquire write lock");
}
printk("Thread %d got RD lock\n", id);
usleep(USEC_PER_MSEC);
printk("Thread %d releasing RD lock\n", id);
zassert_false(pthread_rwlock_unlock(&rwlock), "Failed to unlock");
printk("Thread %d acquiring WR lock\n", id);
ret = pthread_rwlock_trywrlock(&rwlock);
if (ret != 0U) {
zassert_false(pthread_rwlock_wrlock(&rwlock),
"Failed to acquire WR lock");
}
printk("Thread %d acquired WR lock\n", id);
usleep(USEC_PER_MSEC);
printk("Thread %d releasing WR lock\n", id);
zassert_false(pthread_rwlock_unlock(&rwlock), "Failed to unlock");
pthread_exit(NULL);
return NULL;
}
ZTEST(posix_apis, test_posix_rw_lock)
{
int32_t i, ret;
pthread_attr_t attr[N_THR];
struct sched_param schedparam;
pthread_t newthread[N_THR];
struct timespec time;
void *status;
time.tv_sec = 1;
time.tv_nsec = 0;
zassert_equal(pthread_rwlock_destroy(&rwlock), EINVAL);
zassert_equal(pthread_rwlock_rdlock(&rwlock), EINVAL);
zassert_equal(pthread_rwlock_wrlock(&rwlock), EINVAL);
zassert_equal(pthread_rwlock_trywrlock(&rwlock), EINVAL);
zassert_equal(pthread_rwlock_tryrdlock(&rwlock), EINVAL);
zassert_equal(pthread_rwlock_timedwrlock(&rwlock, &time), EINVAL);
zassert_equal(pthread_rwlock_timedrdlock(&rwlock, &time), EINVAL);
zassert_equal(pthread_rwlock_unlock(&rwlock), EINVAL);
zassert_false(pthread_rwlock_init(&rwlock, NULL),
"Failed to create rwlock");
printk("\nmain acquire WR lock and 3 threads acquire RD lock\n");
zassert_false(pthread_rwlock_timedwrlock(&rwlock, &time),
"Failed to acquire write lock");
/* Creating N preemptive threads in increasing order of priority */
for (i = 0; i < N_THR; i++) {
zassert_equal(pthread_attr_init(&attr[i]), 0,
"Unable to create pthread object attrib");
/* Setting scheduling priority */
schedparam.sched_priority = i + 1;
pthread_attr_setschedparam(&attr[i], &schedparam);
/* Setting stack */
pthread_attr_setstack(&attr[i], &stack[i][0], STACKSZ);
ret = pthread_create(&newthread[i], &attr[i], thread_top,
INT_TO_POINTER(i));
zassert_false(ret, "Low memory to thread new thread");
}
/* Delay to give change to child threads to run */
usleep(USEC_PER_MSEC);
printk("Parent thread releasing WR lock\n");
zassert_false(pthread_rwlock_unlock(&rwlock), "Failed to unlock");
/* Let child threads acquire RD Lock */
usleep(USEC_PER_MSEC);
printk("Parent thread acquiring WR lock again\n");
time.tv_sec = 2;
time.tv_nsec = 0;
ret = pthread_rwlock_timedwrlock(&rwlock, &time);
if (ret) {
zassert_false(pthread_rwlock_wrlock(&rwlock),
"Failed to acquire write lock");
}
printk("Parent thread acquired WR lock again\n");
usleep(USEC_PER_MSEC);
printk("Parent thread releasing WR lock again\n");
zassert_false(pthread_rwlock_unlock(&rwlock), "Failed to unlock");
printk("\n3 threads acquire WR lock\n");
printk("Main thread acquiring RD lock\n");
ret = pthread_rwlock_timedrdlock(&rwlock, &time);
if (ret != 0) {
zassert_false(pthread_rwlock_rdlock(&rwlock), "Failed to lock");
}
printk("Main thread acquired RD lock\n");
usleep(USEC_PER_MSEC);
printk("Main thread releasing RD lock\n");
zassert_false(pthread_rwlock_unlock(&rwlock), "Failed to unlock");
for (i = 0; i < N_THR; i++) {
zassert_false(pthread_join(newthread[i], &status),
"Failed to join");
}
zassert_false(pthread_rwlock_destroy(&rwlock),
"Failed to destroy rwlock");
}