1 /*
2  * Copyright (c) 2017 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/ztest.h>
8 #include <zephyr/kernel.h>
9 #include <errno.h>
10 #include <zephyr/sys/errno_private.h>
11 
12 
13 #define N_THREADS 2
14 #define STACK_SIZE (384 + CONFIG_TEST_EXTRA_STACK_SIZE)
15 
16 static K_THREAD_STACK_ARRAY_DEFINE(stacks, N_THREADS, STACK_SIZE);
17 static struct k_thread threads[N_THREADS];
18 
19 K_THREAD_STACK_DEFINE(eno_stack, STACK_SIZE);
20 struct k_thread eno_thread;
21 
22 static int errno_values[N_THREADS + 1] = {
23 	0xbabef00d,
24 	0xdeadbeef,
25 	0xabad1dea,
26 };
27 
28 struct result {
29 	void *q;
30 	int pass;
31 };
32 
33 struct result result[N_THREADS];
34 
35 struct k_fifo fifo;
36 
errno_thread(void * _n,void * _my_errno,void * _unused)37 static void errno_thread(void *_n, void *_my_errno, void *_unused)
38 {
39 	int n = POINTER_TO_INT(_n);
40 	int my_errno = POINTER_TO_INT(_my_errno);
41 
42 	errno = my_errno;
43 
44 	k_msleep(30 - (n * 10));
45 	if (errno == my_errno) {
46 		result[n].pass = TC_PASS;
47 	}
48 
49 	zassert_equal(errno, my_errno);
50 
51 	k_fifo_put(&fifo, &result[n]);
52 }
53 /**
54  * @defgroup kernel_errno_tests Error Number
55  * @ingroup all_tests
56  * @{
57  * @}
58  *
59  * @addtogroup kernel_errno_tests
60  * @{
61  */
62 /**
63  * @brief Verify thread context
64  *
65  * @details Check whether variable value per-thread are saved during
66  *	context switch
67  */
ZTEST(common_errno,test_thread_context)68 ZTEST(common_errno, test_thread_context)
69 {
70 	int rv = TC_PASS, test_errno;
71 
72 	k_fifo_init(&fifo);
73 
74 	errno = errno_values[N_THREADS];
75 	test_errno = errno;
76 
77 	for (int ii = 0; ii < N_THREADS; ii++) {
78 		result[ii].pass = TC_FAIL;
79 	}
80 
81 	/**TESTPOINT: thread- threads stacks are separate */
82 	for (int ii = 0; ii < N_THREADS; ii++) {
83 		k_thread_create(&threads[ii], stacks[ii], STACK_SIZE,
84 				errno_thread, INT_TO_POINTER(ii),
85 				INT_TO_POINTER(errno_values[ii]), NULL,
86 				K_PRIO_PREEMPT(ii + 5), 0, K_NO_WAIT);
87 	}
88 
89 	for (int ii = 0; ii < N_THREADS; ii++) {
90 		struct result *p = k_fifo_get(&fifo, K_MSEC(100));
91 
92 		if (!p || (p->pass != TC_PASS)) {
93 			rv = TC_FAIL;
94 		}
95 	}
96 
97 	zassert_equal(errno, test_errno);
98 
99 	if (errno != errno_values[N_THREADS]) {
100 		rv = TC_FAIL;
101 	}
102 
103 	/* Make sure all the test thread end. */
104 	for (int ii = 0; ii < N_THREADS; ii++) {
105 		k_thread_join(&threads[ii], K_FOREVER);
106 	}
107 
108 	if (rv != TC_PASS) {
109 		ztest_test_fail();
110 	}
111 }
112 
113 
114 #define ERROR_ANY 0xfc
115 
thread_entry_user(void * p1,void * p2,void * p3)116 void thread_entry_user(void *p1, void *p2, void *p3)
117 {
118 #ifdef CONFIG_NATIVE_LIBC
119 	/* The errno when using the host C library will be handled by it, so we skip it.
120 	 */
121 	ztest_test_skip();
122 #else
123 	int got_errno;
124 
125 	/* assign the error number to C standard errno */
126 	errno = ERROR_ANY;
127 
128 	/* got errno zephyr stored */
129 	got_errno = *(z_errno());
130 
131 	zassert_equal(errno, got_errno, "errno is not corresponding.");
132 #endif
133 }
134 
135 /**
136  * @brief Verify errno works well
137  *
138  * @details Check whether a C standard errno can be stored successfully,
139  *  no matter it is using tls or not.
140  */
ZTEST_USER(common_errno,test_errno)141 ZTEST_USER(common_errno, test_errno)
142 {
143 	k_tid_t tid;
144 	uint32_t perm = K_INHERIT_PERMS;
145 
146 	if (k_is_user_context()) {
147 		perm = perm | K_USER;
148 	}
149 
150 	tid = k_thread_create(&eno_thread, eno_stack, STACK_SIZE,
151 				thread_entry_user, NULL, NULL, NULL,
152 				K_PRIO_PREEMPT(1), perm,
153 				K_NO_WAIT);
154 
155 	k_thread_join(tid, K_FOREVER);
156 }
157 
158 /**
159  * @}
160  */
161 extern void *common_setup(void);
162 ZTEST_SUITE(common_errno, NULL, common_setup, NULL, NULL, NULL);
163