1 /*
2 * Copyright (c) 2018 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <pthread.h>
8
9 #include <zephyr/sys/util.h>
10 #include <zephyr/ztest.h>
11
12 #define N_THR 3
13 #define STACKSZ (1024 + CONFIG_TEST_EXTRA_STACK_SIZE)
14
15 K_THREAD_STACK_ARRAY_DEFINE(stack, N_THR, STACKSZ);
16 pthread_rwlock_t rwlock;
17
thread_top(void * p1)18 static void *thread_top(void *p1)
19 {
20 pthread_t pthread;
21 uint32_t policy, ret = 0U;
22 struct sched_param param;
23 int id = POINTER_TO_INT(p1);
24
25 pthread = (pthread_t) pthread_self();
26 pthread_getschedparam(pthread, &policy, ¶m);
27 printk("Thread %d scheduling policy = %d & priority %d started\n",
28 id, policy, param.sched_priority);
29
30 ret = pthread_rwlock_tryrdlock(&rwlock);
31 if (ret) {
32 printk("Not able to get RD lock on trying, try again\n");
33 zassert_false(pthread_rwlock_rdlock(&rwlock),
34 "Failed to acquire write lock");
35 }
36
37 printk("Thread %d got RD lock\n", id);
38 usleep(USEC_PER_MSEC);
39 printk("Thread %d releasing RD lock\n", id);
40 zassert_false(pthread_rwlock_unlock(&rwlock), "Failed to unlock");
41
42 printk("Thread %d acquiring WR lock\n", id);
43 ret = pthread_rwlock_trywrlock(&rwlock);
44 if (ret != 0U) {
45 zassert_false(pthread_rwlock_wrlock(&rwlock),
46 "Failed to acquire WR lock");
47 }
48
49 printk("Thread %d acquired WR lock\n", id);
50 usleep(USEC_PER_MSEC);
51 printk("Thread %d releasing WR lock\n", id);
52 zassert_false(pthread_rwlock_unlock(&rwlock), "Failed to unlock");
53 pthread_exit(NULL);
54 return NULL;
55 }
56
ZTEST(posix_apis,test_rw_lock)57 ZTEST(posix_apis, test_rw_lock)
58 {
59 int32_t i, ret;
60 pthread_attr_t attr[N_THR];
61 struct sched_param schedparam;
62 pthread_t newthread[N_THR];
63 struct timespec time;
64 void *status;
65
66 time.tv_sec = 1;
67 time.tv_nsec = 0;
68
69 zassert_equal(pthread_rwlock_destroy(&rwlock), EINVAL);
70 zassert_equal(pthread_rwlock_rdlock(&rwlock), EINVAL);
71 zassert_equal(pthread_rwlock_wrlock(&rwlock), EINVAL);
72 zassert_equal(pthread_rwlock_trywrlock(&rwlock), EINVAL);
73 zassert_equal(pthread_rwlock_tryrdlock(&rwlock), EINVAL);
74 zassert_equal(pthread_rwlock_timedwrlock(&rwlock, &time), EINVAL);
75 zassert_equal(pthread_rwlock_timedrdlock(&rwlock, &time), EINVAL);
76 zassert_equal(pthread_rwlock_unlock(&rwlock), EINVAL);
77
78 zassert_false(pthread_rwlock_init(&rwlock, NULL),
79 "Failed to create rwlock");
80 printk("\nmain acquire WR lock and 3 threads acquire RD lock\n");
81 zassert_false(pthread_rwlock_timedwrlock(&rwlock, &time),
82 "Failed to acquire write lock");
83
84 /* Creating N preemptive threads in increasing order of priority */
85 for (i = 0; i < N_THR; i++) {
86 zassert_equal(pthread_attr_init(&attr[i]), 0,
87 "Unable to create pthread object attrib");
88
89 /* Setting scheduling priority */
90 schedparam.sched_priority = i + 1;
91 pthread_attr_setschedparam(&attr[i], &schedparam);
92
93 /* Setting stack */
94 pthread_attr_setstack(&attr[i], &stack[i][0], STACKSZ);
95
96 ret = pthread_create(&newthread[i], &attr[i], thread_top,
97 INT_TO_POINTER(i));
98 zassert_false(ret, "Low memory to thread new thread");
99
100 }
101
102 /* Delay to give change to child threads to run */
103 usleep(USEC_PER_MSEC);
104 printk("Parent thread releasing WR lock\n");
105 zassert_false(pthread_rwlock_unlock(&rwlock), "Failed to unlock");
106
107 /* Let child threads acquire RD Lock */
108 usleep(USEC_PER_MSEC);
109 printk("Parent thread acquiring WR lock again\n");
110
111 time.tv_sec = 2;
112 time.tv_nsec = 0;
113 ret = pthread_rwlock_timedwrlock(&rwlock, &time);
114
115 if (ret) {
116 zassert_false(pthread_rwlock_wrlock(&rwlock),
117 "Failed to acquire write lock");
118 }
119
120 printk("Parent thread acquired WR lock again\n");
121 usleep(USEC_PER_MSEC);
122 printk("Parent thread releasing WR lock again\n");
123 zassert_false(pthread_rwlock_unlock(&rwlock), "Failed to unlock");
124
125 printk("\n3 threads acquire WR lock\n");
126 printk("Main thread acquiring RD lock\n");
127
128 ret = pthread_rwlock_timedrdlock(&rwlock, &time);
129
130 if (ret != 0) {
131 zassert_false(pthread_rwlock_rdlock(&rwlock), "Failed to lock");
132 }
133
134 printk("Main thread acquired RD lock\n");
135 usleep(USEC_PER_MSEC);
136 printk("Main thread releasing RD lock\n");
137 zassert_false(pthread_rwlock_unlock(&rwlock), "Failed to unlock");
138
139 for (i = 0; i < N_THR; i++) {
140 zassert_false(pthread_join(newthread[i], &status),
141 "Failed to join");
142 }
143
144 zassert_false(pthread_rwlock_destroy(&rwlock),
145 "Failed to destroy rwlock");
146 }
147