1 | /* |
---|
2 | * Copyright (c) 2014 embedded brains GmbH. All rights reserved. |
---|
3 | * |
---|
4 | * embedded brains GmbH |
---|
5 | * Dornierstr. 4 |
---|
6 | * 82178 Puchheim |
---|
7 | * Germany |
---|
8 | * <rtems@embedded-brains.de> |
---|
9 | * |
---|
10 | * The license and distribution terms for this file may be |
---|
11 | * found in the file LICENSE in this distribution or at |
---|
12 | * http://www.rtems.org/license/LICENSE. |
---|
13 | */ |
---|
14 | |
---|
15 | #ifdef HAVE_CONFIG_H |
---|
16 | #include "config.h" |
---|
17 | #endif |
---|
18 | |
---|
19 | #include <stdio.h> |
---|
20 | #include <stdlib.h> |
---|
21 | |
---|
22 | #include <rtems.h> |
---|
23 | #include <rtems/libcsupport.h> |
---|
24 | |
---|
25 | #define TESTS_USE_PRINTF |
---|
26 | #include "tmacros.h" |
---|
27 | |
---|
28 | const char rtems_test_name[] = "SPTLS 2"; |
---|
29 | |
---|
30 | static thread_local long i123 = 123; |
---|
31 | |
---|
32 | alignas(256) static thread_local long a256 = 256; |
---|
33 | |
---|
34 | static thread_local long i0; |
---|
35 | |
---|
36 | alignas(512) static thread_local long a512; |
---|
37 | |
---|
38 | static void clobber() |
---|
39 | { |
---|
40 | i123 = 0xdead0001; |
---|
41 | a256 = 0xdead0002; |
---|
42 | i0 = 0xdead0003; |
---|
43 | a512 = 0xdead0004; |
---|
44 | } |
---|
45 | |
---|
46 | static long f456(bool clobber) |
---|
47 | { |
---|
48 | static thread_local long fi456 = 456; |
---|
49 | |
---|
50 | if (clobber) { |
---|
51 | fi456 = 0xdead0003; |
---|
52 | } |
---|
53 | |
---|
54 | return fi456; |
---|
55 | } |
---|
56 | |
---|
57 | static long f0(bool clobber) |
---|
58 | { |
---|
59 | static thread_local long fi0; |
---|
60 | |
---|
61 | if (clobber) { |
---|
62 | fi0 = 0xdead0004; |
---|
63 | } |
---|
64 | |
---|
65 | return fi0; |
---|
66 | } |
---|
67 | |
---|
68 | class C { |
---|
69 | public: |
---|
70 | static long c789() |
---|
71 | { |
---|
72 | return ci789; |
---|
73 | } |
---|
74 | |
---|
75 | static long c0() |
---|
76 | { |
---|
77 | return ci0; |
---|
78 | } |
---|
79 | |
---|
80 | static void clobber() |
---|
81 | { |
---|
82 | ci789 = 0xdead0005; |
---|
83 | ci0 = 0xdead0006; |
---|
84 | } |
---|
85 | |
---|
86 | private: |
---|
87 | static thread_local long ci789; |
---|
88 | |
---|
89 | static thread_local long ci0; |
---|
90 | }; |
---|
91 | |
---|
92 | thread_local long C::ci789 = 789; |
---|
93 | |
---|
94 | thread_local long C::ci0; |
---|
95 | |
---|
96 | class A { |
---|
97 | public: |
---|
98 | A(long i) |
---|
99 | : ii(i), c(gc) |
---|
100 | { |
---|
101 | ++gc; |
---|
102 | } |
---|
103 | |
---|
104 | ~A() |
---|
105 | { |
---|
106 | --gc; |
---|
107 | } |
---|
108 | |
---|
109 | long i() const |
---|
110 | { |
---|
111 | return ii; |
---|
112 | } |
---|
113 | |
---|
114 | void clobber() |
---|
115 | { |
---|
116 | ii = ~ii; |
---|
117 | c = ~c; |
---|
118 | } |
---|
119 | |
---|
120 | long counter() const |
---|
121 | { |
---|
122 | return c; |
---|
123 | } |
---|
124 | |
---|
125 | static long globalCounter() |
---|
126 | { |
---|
127 | return gc; |
---|
128 | } |
---|
129 | |
---|
130 | private: |
---|
131 | static long gc; |
---|
132 | |
---|
133 | long ii; |
---|
134 | |
---|
135 | long c; |
---|
136 | }; |
---|
137 | |
---|
138 | long A::gc; |
---|
139 | |
---|
140 | static volatile long mc; |
---|
141 | |
---|
142 | static thread_local A a1(mc + 1); |
---|
143 | static thread_local A a2(mc + 2); |
---|
144 | static thread_local A a3(mc + 3); |
---|
145 | |
---|
146 | static void checkTLSValues() |
---|
147 | { |
---|
148 | rtems_test_assert(i123 == 123); |
---|
149 | rtems_test_assert(a256 == 256); |
---|
150 | rtems_test_assert((a256 & 255) == 0); |
---|
151 | rtems_test_assert(i0 == 0); |
---|
152 | rtems_test_assert(a512 == 0); |
---|
153 | rtems_test_assert((a512 & 511) == 0); |
---|
154 | rtems_test_assert(f456(false) == 456); |
---|
155 | rtems_test_assert(f0(false) == 0); |
---|
156 | rtems_test_assert(C::c789() == 789); |
---|
157 | rtems_test_assert(C::c0() == 0); |
---|
158 | rtems_test_assert(a1.i() == 1); |
---|
159 | rtems_test_assert(a2.i() == 2); |
---|
160 | rtems_test_assert(a3.i() == 3); |
---|
161 | } |
---|
162 | |
---|
163 | static rtems_id masterTask; |
---|
164 | |
---|
165 | static void task(rtems_task_argument arg) |
---|
166 | { |
---|
167 | checkTLSValues(); |
---|
168 | |
---|
169 | const long gc = static_cast<long>(arg); |
---|
170 | |
---|
171 | rtems_test_assert(A::globalCounter() == gc + 3); |
---|
172 | |
---|
173 | rtems_test_assert(a1.counter() == gc + 0); |
---|
174 | rtems_test_assert(a2.counter() == gc + 1); |
---|
175 | rtems_test_assert(a3.counter() == gc + 2); |
---|
176 | |
---|
177 | clobber(); |
---|
178 | f456(true); |
---|
179 | f0(true); |
---|
180 | C::clobber(); |
---|
181 | a1.clobber(); |
---|
182 | a2.clobber(); |
---|
183 | a3.clobber(); |
---|
184 | |
---|
185 | rtems_status_code sc = rtems_event_transient_send(masterTask); |
---|
186 | rtems_test_assert(sc == RTEMS_SUCCESSFUL); |
---|
187 | |
---|
188 | sc = rtems_task_suspend(RTEMS_SELF); |
---|
189 | rtems_test_assert(sc == RTEMS_SUCCESSFUL); |
---|
190 | } |
---|
191 | |
---|
192 | static void testTask() |
---|
193 | { |
---|
194 | checkTLSValues(); |
---|
195 | |
---|
196 | rtems_id id; |
---|
197 | rtems_status_code sc = rtems_task_create( |
---|
198 | rtems_build_name('T', 'A', 'S', 'K'), |
---|
199 | RTEMS_MINIMUM_PRIORITY, |
---|
200 | RTEMS_MINIMUM_STACK_SIZE, |
---|
201 | RTEMS_DEFAULT_MODES, |
---|
202 | RTEMS_DEFAULT_ATTRIBUTES, |
---|
203 | &id |
---|
204 | ); |
---|
205 | rtems_test_assert(sc == RTEMS_SUCCESSFUL); |
---|
206 | |
---|
207 | const long gc = A::globalCounter(); |
---|
208 | |
---|
209 | sc = rtems_task_start(id, task, gc); |
---|
210 | rtems_test_assert(sc == RTEMS_SUCCESSFUL); |
---|
211 | |
---|
212 | sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT); |
---|
213 | rtems_test_assert(sc == RTEMS_SUCCESSFUL); |
---|
214 | |
---|
215 | sc = rtems_task_delete(id); |
---|
216 | rtems_test_assert(sc == RTEMS_SUCCESSFUL); |
---|
217 | |
---|
218 | rtems_test_assert(A::globalCounter() == gc); |
---|
219 | |
---|
220 | checkTLSValues(); |
---|
221 | } |
---|
222 | |
---|
223 | extern "C" void Init(rtems_task_argument arg) |
---|
224 | { |
---|
225 | TEST_BEGIN(); |
---|
226 | |
---|
227 | printf("A::globalCounter() = %li\n", A::globalCounter()); |
---|
228 | |
---|
229 | checkTLSValues(); |
---|
230 | |
---|
231 | printf("A::globalCounter() = %li\n", A::globalCounter()); |
---|
232 | |
---|
233 | masterTask = rtems_task_self(); |
---|
234 | |
---|
235 | testTask(); |
---|
236 | |
---|
237 | rtems_resource_snapshot snapshot; |
---|
238 | rtems_resource_snapshot_take(&snapshot); |
---|
239 | |
---|
240 | testTask(); |
---|
241 | |
---|
242 | rtems_test_assert(rtems_resource_snapshot_check(&snapshot)); |
---|
243 | |
---|
244 | TEST_END(); |
---|
245 | |
---|
246 | exit(0); |
---|
247 | } |
---|
248 | |
---|
249 | #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER |
---|
250 | #define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER |
---|
251 | |
---|
252 | #define CONFIGURE_MAXIMUM_TASKS 2 |
---|
253 | #define CONFIGURE_MAXIMUM_SEMAPHORES 3 |
---|
254 | |
---|
255 | #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION |
---|
256 | |
---|
257 | #define CONFIGURE_RTEMS_INIT_TASKS_TABLE |
---|
258 | |
---|
259 | #define CONFIGURE_MAXIMUM_POSIX_KEYS 2 |
---|
260 | #define CONFIGURE_MAXIMUM_POSIX_KEY_VALUE_PAIRS 2 |
---|
261 | |
---|
262 | #define CONFIGURE_INIT |
---|
263 | |
---|
264 | #include <rtems/confdefs.h> |
---|