source: rtems/testsuites/sptests/spextensions01/init.c @ 6f6da82c

5
Last change on this file since 6f6da82c was 6f6da82c, checked in by Sebastian Huber <sebastian.huber@…>, on 01/26/17 at 10:06:50

score: Fix user extensions order

Use forward and reverse order for initial and dynamic extensions. This
is the behaviour documented in the C Users Guide. Change thread
terminate order to backward to be in line with the thread delete order.
Change fatal error order to forward to ensure that initial extensions
are called first due the peculiar execution context of fatal error
extensions, see _Terminate() documentation.

Update #2692.

  • Property mode set to 100644
File size: 10.7 KB
Line 
1/*
2 * Copyright (c) 2016, 2017 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.com/license/LICENSE.
13 */
14
15#ifdef HAVE_CONFIG_H
16  #include "config.h"
17#endif
18
19#define TESTS_USE_PRINTK
20#include "tmacros.h"
21
22#include <assert.h>
23#include <limits.h>
24#include <stdlib.h>
25
26#include <bsp.h>
27
28#include <rtems/score/apimutex.h>
29#include <rtems/score/sysstate.h>
30#include <rtems/score/threaddispatch.h>
31
32const char rtems_test_name[] = "SPEXTENSIONS 1";
33
34static int counter;
35
36static int active_extensions = 2;
37
38static rtems_id master_task;
39
40static bool before_multitasking(void)
41{
42  return _System_state_Is_before_multitasking(_System_state_Get());
43}
44
45static bool life_protected(void)
46{
47  Thread_Control *executing;
48
49  executing = _Thread_Get_executing();
50
51  return executing == NULL
52    || (executing->Life.state & THREAD_LIFE_PROTECTED) != 0;
53}
54
55static void assert_normal_thread_context(void)
56{
57  assert(_Thread_Dispatch_is_enabled());
58  assert(!_RTEMS_Allocator_is_owner());
59  assert(!life_protected());
60}
61
62static void assert_life_protected_thread_context(void)
63{
64  assert(_Thread_Dispatch_is_enabled() || before_multitasking());
65  assert(!_RTEMS_Allocator_is_owner());
66  assert(life_protected() || before_multitasking());
67}
68
69static void assert_allocator_protected_thread_context(void)
70{
71  assert(_Thread_Dispatch_is_enabled() || before_multitasking());
72  assert(_RTEMS_Allocator_is_owner());
73  assert(life_protected() || before_multitasking());
74}
75
76static void assert_thread_dispatch_disabled_context(void)
77{
78  assert(!_Thread_Dispatch_is_enabled());
79  assert(!_RTEMS_Allocator_is_owner());
80  assert(!life_protected());
81}
82
83static void assert_forward_order(int index)
84{
85  assert((counter % active_extensions) == index);
86  ++counter;
87}
88
89static void assert_reverse_order(int index)
90{
91  assert((counter % active_extensions) == (active_extensions - 1 - index));
92  ++counter;
93}
94
95static bool zero_thread_create(rtems_tcb *a, rtems_tcb *b)
96{
97  assert_forward_order(0);
98  assert_allocator_protected_thread_context();
99  return true;
100}
101
102static void zero_thread_start(rtems_tcb *a, rtems_tcb *b)
103{
104  assert_forward_order(0);
105  assert_thread_dispatch_disabled_context();
106}
107
108static void zero_thread_restart(rtems_tcb *a, rtems_tcb *b)
109{
110  assert_forward_order(0);
111  assert_life_protected_thread_context();
112}
113
114static void zero_thread_delete(rtems_tcb *a, rtems_tcb *b)
115{
116  assert_reverse_order(0);
117  assert_allocator_protected_thread_context();
118}
119
120static void zero_thread_switch(rtems_tcb *a, rtems_tcb *b)
121{
122  assert_forward_order(0);
123}
124
125static void zero_thread_begin(rtems_tcb *a)
126{
127  assert_forward_order(0);
128  assert_normal_thread_context();
129}
130
131static void zero_thread_exitted(rtems_tcb *a)
132{
133  assert_forward_order(0);
134  assert_normal_thread_context();
135}
136
137static void zero_fatal(
138  rtems_fatal_source source,
139  bool always_set_to_false,
140  rtems_fatal_code code
141)
142{
143  if (source == RTEMS_FATAL_SOURCE_EXIT) {
144    assert_forward_order(0);
145  }
146}
147
148static void zero_thread_terminate(rtems_tcb *a)
149{
150  assert_reverse_order(0);
151  assert_life_protected_thread_context();
152}
153
154static bool one_thread_create(rtems_tcb *a, rtems_tcb *b)
155{
156  assert_forward_order(1);
157  assert_allocator_protected_thread_context();
158  return true;
159}
160
161static void one_thread_start(rtems_tcb *a, rtems_tcb *b)
162{
163  assert_forward_order(1);
164  assert_thread_dispatch_disabled_context();
165}
166
167static void one_thread_restart(rtems_tcb *a, rtems_tcb *b)
168{
169  assert_forward_order(1);
170  assert_life_protected_thread_context();
171}
172
173static void one_thread_delete(rtems_tcb *a, rtems_tcb *b)
174{
175  assert_reverse_order(1);
176  assert_allocator_protected_thread_context();
177}
178
179static void one_thread_switch(rtems_tcb *a, rtems_tcb *b)
180{
181  assert_forward_order(1);
182}
183
184static void one_thread_begin(rtems_tcb *a)
185{
186  assert_forward_order(1);
187  assert_normal_thread_context();
188}
189
190static void one_thread_exitted(rtems_tcb *a)
191{
192  assert_forward_order(1);
193  assert_normal_thread_context();
194}
195
196static void one_fatal(
197  rtems_fatal_source source,
198  bool always_set_to_false,
199  rtems_fatal_code code
200)
201{
202  if (source == RTEMS_FATAL_SOURCE_EXIT) {
203    assert_forward_order(1);
204  }
205}
206
207static void one_thread_terminate(rtems_tcb *a)
208{
209  assert_reverse_order(1);
210  assert_life_protected_thread_context();
211}
212
213static bool two_thread_create(rtems_tcb *a, rtems_tcb *b)
214{
215  assert_forward_order(2);
216  assert_allocator_protected_thread_context();
217  return true;
218}
219
220static void two_thread_start(rtems_tcb *a, rtems_tcb *b)
221{
222  assert_forward_order(2);
223  assert_thread_dispatch_disabled_context();
224}
225
226static void two_thread_restart(rtems_tcb *a, rtems_tcb *b)
227{
228  assert_forward_order(2);
229  assert_life_protected_thread_context();
230}
231
232static void two_thread_delete(rtems_tcb *a, rtems_tcb *b)
233{
234  assert_reverse_order(2);
235  assert_allocator_protected_thread_context();
236}
237
238static void two_thread_switch(rtems_tcb *a, rtems_tcb *b)
239{
240  assert_forward_order(2);
241}
242
243static void two_thread_begin(rtems_tcb *a)
244{
245  assert_forward_order(2);
246  assert_normal_thread_context();
247}
248
249static void two_thread_exitted(rtems_tcb *a)
250{
251  assert_forward_order(2);
252  assert_normal_thread_context();
253}
254
255static void two_fatal(
256  rtems_fatal_source source,
257  bool always_set_to_false,
258  rtems_fatal_code code
259)
260{
261  if (source == RTEMS_FATAL_SOURCE_EXIT) {
262    assert_forward_order(2);
263  }
264}
265
266static void two_thread_terminate(rtems_tcb *a)
267{
268  assert_reverse_order(2);
269  assert_life_protected_thread_context();
270}
271
272static bool three_thread_create(rtems_tcb *a, rtems_tcb *b)
273{
274  assert_forward_order(3);
275  assert_allocator_protected_thread_context();
276  return true;
277}
278
279static void three_thread_start(rtems_tcb *a, rtems_tcb *b)
280{
281  assert_forward_order(3);
282  assert_thread_dispatch_disabled_context();
283}
284
285static void three_thread_restart(rtems_tcb *a, rtems_tcb *b)
286{
287  assert_forward_order(3);
288  assert_life_protected_thread_context();
289}
290
291static void three_thread_delete(rtems_tcb *a, rtems_tcb *b)
292{
293  assert_reverse_order(3);
294  assert_allocator_protected_thread_context();
295}
296
297static void three_thread_switch(rtems_tcb *a, rtems_tcb *b)
298{
299  assert_forward_order(3);
300}
301
302static void three_thread_begin(rtems_tcb *a)
303{
304  assert_forward_order(3);
305  assert_normal_thread_context();
306}
307
308static void three_thread_exitted(rtems_tcb *a)
309{
310  assert_forward_order(3);
311  assert_normal_thread_context();
312}
313
314static void three_fatal(
315  rtems_fatal_source source,
316  bool always_set_to_false,
317  rtems_fatal_code code
318)
319{
320  if (source == RTEMS_FATAL_SOURCE_EXIT) {
321    assert_forward_order(3);
322    assert(counter == 72);
323    TEST_END();
324  }
325}
326
327static void three_thread_terminate(rtems_tcb *a)
328{
329  assert_reverse_order(3);
330  assert_life_protected_thread_context();
331}
332
333#define ZERO \
334  { \
335    .thread_create = zero_thread_create, \
336    .thread_start = zero_thread_start, \
337    .thread_restart = zero_thread_restart, \
338    .thread_delete = zero_thread_delete, \
339    .thread_switch = zero_thread_switch, \
340    .thread_begin = zero_thread_begin, \
341    .thread_exitted = zero_thread_exitted, \
342    .fatal = zero_fatal, \
343    .thread_terminate = zero_thread_terminate \
344  }
345
346#define ONE \
347  { \
348    .thread_create = one_thread_create, \
349    .thread_start = one_thread_start, \
350    .thread_restart = one_thread_restart, \
351    .thread_delete = one_thread_delete, \
352    .thread_switch = one_thread_switch, \
353    .thread_begin = one_thread_begin, \
354    .thread_exitted = one_thread_exitted, \
355    .fatal = one_fatal, \
356    .thread_terminate = one_thread_terminate \
357  }
358
359static const rtems_extensions_table two = {
360  .thread_create = two_thread_create,
361  .thread_start = two_thread_start,
362  .thread_restart = two_thread_restart,
363  .thread_delete = two_thread_delete,
364  .thread_switch = two_thread_switch,
365  .thread_begin = two_thread_begin,
366  .thread_exitted = two_thread_exitted,
367  .fatal = two_fatal,
368  .thread_terminate = two_thread_terminate
369};
370
371static const rtems_extensions_table three = {
372  .thread_create = three_thread_create,
373  .thread_start = three_thread_start,
374  .thread_restart = three_thread_restart,
375  .thread_delete = three_thread_delete,
376  .thread_switch = three_thread_switch,
377  .thread_begin = three_thread_begin,
378  .thread_exitted = three_thread_exitted,
379  .fatal = three_fatal,
380  .thread_terminate = three_thread_terminate
381};
382
383static const rtems_extensions_table initial_test =
384  RTEMS_TEST_INITIAL_EXTENSION;
385
386#ifdef BSP_INITIAL_EXTENSION
387static const rtems_extensions_table initial_bsp =
388  BSP_INITIAL_EXTENSION;
389#endif
390
391static void wake_up_master(void)
392{
393  rtems_status_code sc;
394
395  sc = rtems_event_transient_send(master_task);
396  assert(sc == RTEMS_SUCCESSFUL);
397}
398
399static void wait_for_worker(void)
400{
401  rtems_status_code sc;
402
403  sc = rtems_event_transient_receive(
404    RTEMS_WAIT,
405    RTEMS_NO_TIMEOUT
406  );
407  assert(sc == RTEMS_SUCCESSFUL);
408}
409
410static void worker(rtems_task_argument arg)
411{
412  wake_up_master();
413
414  (void) rtems_task_suspend(RTEMS_SELF);
415  assert(false);
416}
417
418static void test(void)
419{
420  rtems_status_code sc;
421  rtems_id id;
422
423  master_task = rtems_task_self();
424
425#ifdef BSP_INITIAL_EXTENSION
426  sc = rtems_extension_create(
427    rtems_build_name(' ', 'B', 'S', 'P'),
428    &initial_bsp,
429    &id
430  );
431  assert(sc == RTEMS_SUCCESSFUL);
432#undef BSP_INITIAL_EXTENSION
433#endif
434
435  sc = rtems_extension_create(
436    rtems_build_name('T', 'E', 'S', 'T'),
437    &initial_test,
438    &id
439  );
440  assert(sc == RTEMS_SUCCESSFUL);
441
442  sc = rtems_extension_create(
443    rtems_build_name('2', ' ', ' ', ' '),
444    &two,
445    &id
446  );
447  assert(sc == RTEMS_SUCCESSFUL);
448
449  sc = rtems_extension_create(
450    rtems_build_name('3', ' ', ' ', ' '),
451    &three,
452    &id
453  );
454  assert(sc == RTEMS_SUCCESSFUL);
455
456  active_extensions = 4;
457  assert(counter == 14);
458  counter = 16;
459
460  sc = rtems_task_create(
461    rtems_build_name('W', 'O', 'R', 'K'),
462    2,
463    RTEMS_MINIMUM_STACK_SIZE,
464    RTEMS_DEFAULT_MODES,
465    RTEMS_DEFAULT_ATTRIBUTES,
466    &id
467  );
468  assert(sc == RTEMS_SUCCESSFUL);
469
470  sc = rtems_task_start(id, worker, 0);
471  assert(sc == RTEMS_SUCCESSFUL);
472
473  wait_for_worker();
474
475  sc = rtems_task_restart(id, 0);
476  assert(sc == RTEMS_SUCCESSFUL);
477
478  wait_for_worker();
479
480  sc = rtems_task_delete(id);
481  assert(sc == RTEMS_SUCCESSFUL);
482
483  /* Process zombies to trigger delete extensions */
484  sc = rtems_task_create(
485    rtems_build_name('N', 'U', 'L', 'L'),
486    2,
487    SIZE_MAX,
488    RTEMS_DEFAULT_MODES,
489    RTEMS_DEFAULT_ATTRIBUTES,
490    &id
491  );
492  assert(sc == RTEMS_UNSATISFIED);
493}
494
495static void Init(rtems_task_argument arg)
496{
497  TEST_BEGIN();
498
499  test();
500
501  exit(0);
502}
503
504#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
505#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
506
507#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 4
508
509#define CONFIGURE_MAXIMUM_TASKS 2
510
511#define CONFIGURE_INITIAL_EXTENSIONS ZERO, ONE
512
513#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
514
515#define CONFIGURE_INIT
516
517#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.