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