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