1 /*
2  * Copyright (c) 2018 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <ztest.h>
8 #include <errno.h>
9 #include <pthread.h>
10 
11 #define STACK_SIZE (1024 + CONFIG_TEST_EXTRA_STACKSIZE)
12 
13 static K_THREAD_STACK_DEFINE(stack, STACK_SIZE);
14 
15 #define SLEEP_MS 100
16 
17 pthread_mutex_t mutex1;
18 pthread_mutex_t mutex2;
19 
normal_mutex_entry(void * p1)20 void *normal_mutex_entry(void *p1)
21 {
22 	int i, rc;
23 
24 	/* Sleep for maximum 300 ms as main thread is sleeping for 100 ms */
25 
26 	for (i = 0; i < 3; i++) {
27 		rc = pthread_mutex_trylock(&mutex1);
28 		if (rc == 0) {
29 			break;
30 		}
31 		k_msleep(SLEEP_MS);
32 	}
33 
34 	zassert_false(rc, "try lock failed");
35 	TC_PRINT("mutex lock is taken\n");
36 	zassert_false(pthread_mutex_unlock(&mutex1),
37 		      "mutex unlock is falied");
38 	return NULL;
39 }
40 
recursive_mutex_entry(void * p1)41 void *recursive_mutex_entry(void *p1)
42 {
43 	zassert_false(pthread_mutex_lock(&mutex2), "mutex is not taken");
44 	zassert_false(pthread_mutex_lock(&mutex2),
45 		      "mutex is not taken 2nd time");
46 	TC_PRINT("recrusive mutex lock is taken\n");
47 	zassert_false(pthread_mutex_unlock(&mutex2),
48 		      "mutex is not unlocked");
49 	zassert_false(pthread_mutex_unlock(&mutex2),
50 		      "mutex is not unlocked");
51 	return NULL;
52 }
53 
54 /**
55  * @brief Test to demonstrate PTHREAD_MUTEX_NORMAL
56  *
57  * @details Mutex type is setup as normal. pthread_mutex_trylock
58  *	    and pthread_mutex_lock are tested with mutex type being
59  *	    normal.
60  */
test_posix_normal_mutex(void)61 void test_posix_normal_mutex(void)
62 {
63 	pthread_t thread_1;
64 	pthread_attr_t attr;
65 	pthread_mutexattr_t mut_attr;
66 	struct sched_param schedparam;
67 	int schedpolicy = SCHED_FIFO;
68 	int ret, type, protocol, temp;
69 
70 	schedparam.sched_priority = 2;
71 	ret = pthread_attr_init(&attr);
72 	if (ret != 0) {
73 		zassert_false(pthread_attr_destroy(&attr),
74 			      "Unable to destroy pthread object attrib");
75 		zassert_false(pthread_attr_init(&attr),
76 			      "Unable to create pthread object attrib");
77 	}
78 
79 	pthread_attr_setstack(&attr, &stack, STACK_SIZE);
80 	pthread_attr_setschedpolicy(&attr, schedpolicy);
81 	pthread_attr_setschedparam(&attr, &schedparam);
82 
83 	temp = pthread_mutexattr_settype(&mut_attr, PTHREAD_MUTEX_NORMAL);
84 	zassert_false(temp, "setting mutex type is failed");
85 	temp = pthread_mutex_init(&mutex1, &mut_attr);
86 	zassert_false(temp, "mutex initialization is failed");
87 
88 	temp = pthread_mutexattr_gettype(&mut_attr, &type);
89 	zassert_false(temp, "reading mutex type is failed");
90 	temp = pthread_mutexattr_getprotocol(&mut_attr, &protocol);
91 	zassert_false(temp, "reading mutex protocol is failed");
92 
93 	pthread_mutex_lock(&mutex1);
94 
95 	zassert_equal(type, PTHREAD_MUTEX_NORMAL,
96 		      "mutex type is not normal");
97 
98 	zassert_equal(protocol, PTHREAD_PRIO_NONE,
99 		      "mutex protocol is not prio_none");
100 	ret = pthread_create(&thread_1, &attr, &normal_mutex_entry, NULL);
101 
102 	if (ret) {
103 		TC_PRINT("Thread1 creation failed %d", ret);
104 	}
105 	k_msleep(SLEEP_MS);
106 	pthread_mutex_unlock(&mutex1);
107 
108 	pthread_join(thread_1, NULL);
109 	temp = pthread_mutex_destroy(&mutex1);
110 	zassert_false(temp, "Destroying mutex is failed");
111 }
112 
113 /**
114  * @brief Test to demonstrate PTHREAD_MUTEX_RECURSIVE
115  *
116  * @details Mutex type is setup as recursive. mutex will be locked
117  *	    twice and unlocked for the same number of time.
118  *
119  */
test_posix_recursive_mutex(void)120 void test_posix_recursive_mutex(void)
121 {
122 	pthread_t thread_2;
123 	pthread_attr_t attr2;
124 	pthread_mutexattr_t mut_attr2;
125 	struct sched_param schedparam2;
126 	int schedpolicy = SCHED_FIFO;
127 	int ret, type, protocol, temp;
128 
129 	schedparam2.sched_priority = 2;
130 	ret = pthread_attr_init(&attr2);
131 	if (ret != 0) {
132 		zassert_false(pthread_attr_destroy(&attr2),
133 			      "Unable to destroy pthread object attrib");
134 		zassert_false(pthread_attr_init(&attr2),
135 			      "Unable to create pthread object attrib");
136 	}
137 
138 	pthread_attr_setstack(&attr2, &stack, STACK_SIZE);
139 	pthread_attr_setschedpolicy(&attr2, schedpolicy);
140 	pthread_attr_setschedparam(&attr2, &schedparam2);
141 
142 	temp = pthread_mutexattr_settype(&mut_attr2, PTHREAD_MUTEX_RECURSIVE);
143 	zassert_false(temp, "setting mutex2 type is failed");
144 	temp = pthread_mutex_init(&mutex2, &mut_attr2);
145 	zassert_false(temp, "mutex2 initialization is failed");
146 
147 	temp = pthread_mutexattr_gettype(&mut_attr2, &type);
148 	zassert_false(temp, "reading mutex2 type is failed");
149 	temp = pthread_mutexattr_getprotocol(&mut_attr2, &protocol);
150 	zassert_false(temp, "reading mutex2 protocol is failed");
151 
152 	zassert_equal(type, PTHREAD_MUTEX_RECURSIVE,
153 		      "mutex2 type is not recursive");
154 
155 	zassert_equal(protocol, PTHREAD_PRIO_NONE,
156 		      "mutex2 protocol is not prio_none");
157 	ret = pthread_create(&thread_2, &attr2, &recursive_mutex_entry, NULL);
158 
159 	zassert_false(ret, "Thread2 creation failed");
160 
161 	pthread_join(thread_2, NULL);
162 	temp = pthread_mutex_destroy(&mutex2);
163 	zassert_false(temp, "Destroying mutex2 is failed");
164 }
165