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