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 #include <semaphore.h>
11 
12 #define STACK_SIZE 1024
13 
14 sem_t sema;
15 void *dummy_sem;
16 
17 struct sched_param schedparam;
18 int schedpolicy = SCHED_FIFO;
19 
20 static K_THREAD_STACK_DEFINE(stack, STACK_SIZE);
21 
child_func(void * p1)22 static void *child_func(void *p1)
23 {
24 	zassert_equal(sem_post(&sema), 0, "sem_post failed");
25 	return NULL;
26 }
27 
initialize_thread_attr(pthread_attr_t * attr)28 void initialize_thread_attr(pthread_attr_t *attr)
29 {
30 	int ret;
31 
32 	schedparam.sched_priority = 1;
33 
34 	ret = pthread_attr_init(attr);
35 	if (ret != 0) {
36 		zassert_equal(pthread_attr_destroy(attr), 0,
37 			      "Unable to destroy pthread object attrib");
38 		zassert_equal(pthread_attr_init(attr), 0,
39 			      "Unable to create pthread object attrib");
40 	}
41 
42 	pthread_attr_setstack(attr, &stack, STACK_SIZE);
43 	pthread_attr_setschedpolicy(attr, schedpolicy);
44 	pthread_attr_setschedparam(attr, &schedparam);
45 }
46 
test_posix_semaphore(void)47 void test_posix_semaphore(void)
48 {
49 	pthread_t thread1, thread2;
50 	pthread_attr_t attr1, attr2;
51 	int val, ret;
52 	struct timespec abstime;
53 
54 	initialize_thread_attr(&attr1);
55 
56 	/* TESTPOINT: Check if sema value is less than
57 	 * CONFIG_SEM_VALUE_MAX
58 	 */
59 	zassert_equal(sem_init(&sema, 0, (CONFIG_SEM_VALUE_MAX + 1)), -1,
60 		      "value larger than %d\n", CONFIG_SEM_VALUE_MAX);
61 	zassert_equal(errno, EINVAL, NULL);
62 
63 	zassert_equal(sem_init(&sema, 0, 0), 0, "sem_init failed");
64 
65 	/* TESTPOINT: Call sem_post with invalid kobject */
66 	zassert_equal(sem_post(dummy_sem), -1, "sem_post of"
67 		      " invalid semaphore object didn't fail");
68 	zassert_equal(errno, EINVAL, NULL);
69 
70 	/* TESTPOINT: Check if semaphore value is as set */
71 	zassert_equal(sem_getvalue(&sema, &val), 0, NULL);
72 	zassert_equal(val, 0, NULL);
73 
74 	/* TESTPOINT: Check if sema is acquired when it
75 	 * is not available
76 	 */
77 	zassert_equal(sem_trywait(&sema), -1, NULL);
78 	zassert_equal(errno, EAGAIN, NULL);
79 
80 	ret = pthread_create(&thread1, &attr1, child_func, NULL);
81 	zassert_equal(ret, 0, "Thread creation failed");
82 
83 	zassert_equal(clock_gettime(CLOCK_REALTIME, &abstime), 0,
84 		      "clock_gettime failed");
85 
86 	abstime.tv_sec += 5;
87 
88 	/* TESPOINT: Wait for 5 seconds and acquire sema given
89 	 * by thread1
90 	 */
91 	zassert_equal(sem_timedwait(&sema, &abstime), 0, NULL);
92 
93 	/* TESTPOINT: Semaphore is already acquired, check if
94 	 * no semaphore is available
95 	 */
96 	zassert_equal(sem_timedwait(&sema, &abstime), -1, NULL);
97 	zassert_equal(errno, ETIMEDOUT, NULL);
98 
99 	/* TESTPOINT: sem_destroy with invalid kobject */
100 	zassert_equal(sem_destroy(dummy_sem), -1, "invalid"
101 		      " semaphore is destroyed");
102 	zassert_equal(errno, EINVAL, NULL);
103 
104 	zassert_equal(sem_destroy(&sema), 0, "semaphore is not destroyed");
105 
106 	zassert_equal(pthread_attr_destroy(&attr1), 0,
107 		      "Unable to destroy pthread object attrib");
108 
109 	/* TESTPOINT: Initialize sema with 1 */
110 	zassert_equal(sem_init(&sema, 0, 1), 0, "sem_init failed");
111 	zassert_equal(sem_getvalue(&sema, &val), 0, NULL);
112 	zassert_equal(val, 1, NULL);
113 
114 	zassert_equal(sem_destroy(&sema), -1, "acquired semaphore"
115 		      " is destroyed");
116 	zassert_equal(errno, EBUSY, NULL);
117 
118 	/* TESTPOINT: take semaphore which is initialized with 1 */
119 	zassert_equal(sem_trywait(&sema), 0, NULL);
120 
121 	initialize_thread_attr(&attr2);
122 
123 	zassert_equal(pthread_create(&thread2, &attr2, child_func, NULL), 0,
124 		      "Thread creation failed");
125 
126 	/* TESTPOINT: Wait and acquire semaphore till thread2 gives */
127 	zassert_equal(sem_wait(&sema), 0, "sem_wait failed");
128 }
129