source: rtems/testsuites/sptests/spthreadlife01/init.c @ a38ced2

4.115
Last change on this file since a38ced2 was a38ced2, checked in by Sebastian Huber <sebastian.huber@…>, on 10/10/14 at 07:09:19

score: Rework global construction

Ensure that the global construction is performed in the context of the
first initialization thread. On SMP this was not guaranteed in the
previous implementation.

  • Property mode set to 100644
File size: 9.1 KB
Line 
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 <rtems.h>
20#include <rtems/libcsupport.h>
21
22#include <rtems/score/threadimpl.h>
23
24#include "tmacros.h"
25
26#define PRIO_INIT 1
27#define PRIO_HIGH 2
28#define PRIO_MID 3
29#define PRIO_LOW 4
30
31const char rtems_test_name[] = "SPTHREADLIFE 1";
32
33typedef enum {
34  INIT,
35  SET_PRIO,
36  SET_PRIO_DONE,
37  DO_OBTAIN_0,
38  OBTAIN_DONE_0,
39  DO_RELEASE_0,
40  RELEASE_DONE_0,
41  DO_OBTAIN_1,
42  OBTAIN_DONE_1,
43  RESTART_0,
44  RESTART_1,
45  RESTART_2,
46  RESTART_3,
47  DO_RELEASE_1,
48  RELEASE_DONE_1,
49  DELETE_0,
50  DELETE_1,
51  DELETE_2,
52  DELETE_3,
53  SET_PROTECTION,
54  SET_PROTECTION_DONE,
55  CLEAR_PROTECTION,
56  DELETE_4,
57  DELETE_5,
58  DELETE_6,
59  INVALID
60} test_state;
61
62typedef struct {
63  rtems_id main_task_id;
64  rtems_id worker_task_id;
65  rtems_id sema_id;
66  test_state current;
67  test_state next;
68} test_context;
69
70static test_context test_instance;
71
72static void wake_up_main(const test_context *ctx)
73{
74  rtems_status_code sc;
75
76  sc = rtems_event_transient_send(ctx->main_task_id);
77  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
78}
79
80static void wait(void)
81{
82  rtems_status_code sc;
83
84  sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
85  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
86}
87
88static void change_state(
89  test_context *ctx,
90  test_state expected,
91  test_state current,
92  test_state next
93)
94{
95  rtems_test_assert(ctx->current == expected);
96  ctx->current = current;
97  ctx->next = next;
98}
99
100static void change_state_and_wait(
101  test_context *ctx,
102  test_state expected,
103  test_state current,
104  test_state next
105)
106{
107  change_state(ctx, expected, current, next);
108  wait();
109}
110
111static void set_priority(rtems_task_priority prio)
112{
113  rtems_status_code sc;
114
115  sc = rtems_task_set_priority(RTEMS_SELF, prio, &prio);
116  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
117}
118
119static void assert_priority(rtems_task_priority expected)
120{
121  rtems_status_code sc;
122  rtems_task_priority prio;
123
124  sc = rtems_task_set_priority(RTEMS_SELF, RTEMS_CURRENT_PRIORITY, &prio);
125  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
126
127  rtems_test_assert(prio == expected);
128}
129
130static void restart_extension(
131  Thread_Control *executing,
132  Thread_Control *restarted
133)
134{
135  test_context *ctx = &test_instance;
136  rtems_status_code sc;
137
138  rtems_test_assert(executing == restarted);
139
140  switch (ctx->current) {
141    case RESTART_0:
142      rtems_test_assert(ctx->worker_task_id == rtems_task_self());
143      ctx->current = RESTART_1;
144      sc = rtems_task_restart(RTEMS_SELF, 0);
145      rtems_test_assert(sc == RTEMS_SUCCESSFUL);
146      break;
147    case RESTART_1:
148      rtems_test_assert(ctx->worker_task_id == rtems_task_self());
149      ctx->current = RESTART_2;
150      break;
151    case INIT:
152      /* Restart via _Thread_Global_construction() */
153      break;
154    default:
155      rtems_test_assert(0);
156      break;
157  }
158}
159
160static void delete_extension(
161  Thread_Control *executing,
162  Thread_Control *deleted
163)
164{
165  test_context *ctx = &test_instance;
166
167  rtems_test_assert(executing != deleted);
168  rtems_test_assert(ctx->main_task_id == rtems_task_self());
169
170  assert_priority(PRIO_INIT);
171
172  switch (ctx->current) {
173    case DELETE_2:
174      ctx->current = DELETE_3;
175      break;
176    case DELETE_5:
177      ctx->current = DELETE_6;
178      break;
179    default:
180      rtems_test_assert(0);
181      break;
182  }
183}
184
185static void terminate_extension(Thread_Control *executing)
186{
187  test_context *ctx = &test_instance;
188  rtems_status_code sc;
189
190  rtems_test_assert(ctx->worker_task_id == rtems_task_self());
191
192  assert_priority(PRIO_INIT);
193
194  switch (ctx->current) {
195    case DELETE_0:
196      ctx->current = DELETE_1;
197      sc = rtems_task_delete(RTEMS_SELF);
198      rtems_test_assert(sc == RTEMS_SUCCESSFUL);
199      break;
200    case DELETE_1:
201      ctx->current = DELETE_2;
202      break;
203    case DELETE_4:
204      ctx->current = DELETE_5;
205      break;
206    default:
207      rtems_test_assert(0);
208      break;
209  }
210}
211
212static void worker_task(rtems_task_argument arg)
213{
214  test_context *ctx = &test_instance;
215
216  while (true) {
217    test_state state = ctx->current;
218    rtems_status_code sc;
219    bool previous_thread_life_protection;
220
221    switch (state) {
222      case SET_PRIO:
223        assert_priority(PRIO_LOW);
224        set_priority(PRIO_MID);
225        break;
226      case DO_OBTAIN_0:
227      case DO_OBTAIN_1:
228        assert_priority(PRIO_MID);
229        sc = rtems_semaphore_obtain(
230          ctx->sema_id,
231          RTEMS_WAIT,
232          RTEMS_NO_TIMEOUT
233        );
234        rtems_test_assert(sc == RTEMS_SUCCESSFUL);
235        assert_priority(PRIO_HIGH);
236        break;
237      case DO_RELEASE_0:
238      case DO_RELEASE_1:
239        assert_priority(PRIO_HIGH);
240        sc = rtems_semaphore_release(ctx->sema_id);
241        rtems_test_assert(sc == RTEMS_SUCCESSFUL);
242
243        switch (state) {
244          case DO_RELEASE_0:
245            assert_priority(PRIO_MID);
246            break;
247          case DO_RELEASE_1:
248            assert_priority(PRIO_LOW);
249            break;
250          default:
251            rtems_test_assert(0);
252            break;
253        }
254
255        break;
256      case RESTART_2:
257        assert_priority(PRIO_HIGH);
258        break;
259      case SET_PROTECTION:
260        _Thread_Disable_dispatch();
261        previous_thread_life_protection = _Thread_Set_life_protection(true);
262        rtems_test_assert(!previous_thread_life_protection);
263        _Thread_Enable_dispatch();
264        break;
265      case CLEAR_PROTECTION:
266        _Thread_Disable_dispatch();
267        previous_thread_life_protection = _Thread_Set_life_protection(false);
268        rtems_test_assert(previous_thread_life_protection);
269        ctx->current = DELETE_4;
270        _Thread_Enable_dispatch();
271        break;
272      default:
273        rtems_test_assert(0);
274        break;
275    }
276
277    ctx->current = ctx->next;
278    wake_up_main(ctx);
279  }
280}
281
282static void create_sema(test_context *ctx)
283{
284  rtems_status_code sc;
285
286  sc = rtems_semaphore_create(
287    rtems_build_name('S', 'E', 'M', 'A'),
288    1,
289    RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_PRIORITY_CEILING,
290    PRIO_HIGH,
291    &ctx->sema_id
292  );
293  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
294}
295
296static void create_and_start_worker(test_context *ctx)
297{
298  rtems_status_code sc;
299
300  sc = rtems_task_create(
301    rtems_build_name('W', 'O', 'R', 'K'),
302    PRIO_LOW,
303    RTEMS_MINIMUM_STACK_SIZE,
304    RTEMS_DEFAULT_MODES,
305    RTEMS_DEFAULT_ATTRIBUTES,
306    &ctx->worker_task_id
307  );
308  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
309
310  sc = rtems_task_start(ctx->worker_task_id, worker_task, 0);
311  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
312}
313
314static void test(void)
315{
316  test_context *ctx = &test_instance;
317  rtems_status_code sc;
318  rtems_resource_snapshot snapshot;
319
320  ctx->main_task_id = rtems_task_self();
321
322  rtems_resource_snapshot_take(&snapshot);
323
324  create_sema(ctx);
325  create_and_start_worker(ctx);
326
327  change_state_and_wait(ctx, INIT, SET_PRIO, SET_PRIO_DONE);
328  change_state_and_wait(ctx, SET_PRIO_DONE, DO_OBTAIN_0, OBTAIN_DONE_0);
329
330  sc = rtems_semaphore_delete(ctx->sema_id);
331  rtems_test_assert(sc == RTEMS_RESOURCE_IN_USE);
332
333  change_state_and_wait(ctx, OBTAIN_DONE_0, DO_RELEASE_0, RELEASE_DONE_0);
334
335  sc = rtems_semaphore_delete(ctx->sema_id);
336  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
337
338  create_sema(ctx);
339
340  change_state_and_wait(ctx, RELEASE_DONE_0, DO_OBTAIN_1, OBTAIN_DONE_1);
341
342  sc = rtems_semaphore_delete(ctx->sema_id);
343  rtems_test_assert(sc == RTEMS_RESOURCE_IN_USE);
344
345  sc = rtems_task_restart(ctx->worker_task_id, 0);
346  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
347
348  change_state_and_wait(ctx, OBTAIN_DONE_1, RESTART_0, RESTART_3);
349  change_state_and_wait(ctx, RESTART_3, DO_RELEASE_1, RELEASE_DONE_1);
350
351  sc = rtems_semaphore_delete(ctx->sema_id);
352  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
353
354  change_state(ctx, RELEASE_DONE_1, DELETE_0, INVALID);
355
356  sc = rtems_task_delete(ctx->worker_task_id);
357  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
358
359  rtems_test_assert(ctx->current == DELETE_2);
360
361  rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
362
363  create_and_start_worker(ctx);
364
365  change_state_and_wait(ctx, DELETE_3, SET_PROTECTION, SET_PROTECTION_DONE);
366  change_state(ctx, SET_PROTECTION_DONE, CLEAR_PROTECTION, INVALID);
367
368  sc = rtems_task_delete(ctx->worker_task_id);
369  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
370
371  rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
372
373  rtems_test_assert(ctx->current == DELETE_6);
374}
375
376static void Init(rtems_task_argument arg)
377{
378  TEST_BEGIN();
379
380  test();
381
382  TEST_END();
383  rtems_test_exit(0);
384}
385
386#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
387#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
388
389#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
390
391#define CONFIGURE_MAXIMUM_TASKS 2
392#define CONFIGURE_MAXIMUM_SEMAPHORES 1
393
394#define CONFIGURE_INITIAL_EXTENSIONS \
395  { \
396    .thread_restart = restart_extension, \
397    .thread_delete = delete_extension, \
398    .thread_terminate = terminate_extension \
399  }, \
400  RTEMS_TEST_INITIAL_EXTENSION
401
402#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
403
404#define CONFIGURE_INIT
405
406#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.