source: rtems/testsuites/sptests/spthreadlife01/init.c @ 82f90743

4.11
Last change on this file since 82f90743 was 82f90743, checked in by Sebastian Huber <sebastian.huber@…>, on May 21, 2014 at 8:30:34 AM

score: _Thread_Set_life_protection()

Enable usage of _Thread_Set_life_protection() in thread dispatch
critical sections. This can be used to enable the thread
life-protection with thread dispatching disabled and then enable thread
dispatching.

  • Property mode set to 100644
File size: 8.9 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  rtems_test_assert(ctx->worker_task_id == rtems_task_self());
140
141  switch (ctx->current) {
142    case RESTART_0:
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      ctx->current = RESTART_2;
149      break;
150    default:
151      rtems_test_assert(0);
152      break;
153  }
154}
155
156static void delete_extension(
157  Thread_Control *executing,
158  Thread_Control *deleted
159)
160{
161  test_context *ctx = &test_instance;
162
163  rtems_test_assert(executing != deleted);
164  rtems_test_assert(ctx->main_task_id == rtems_task_self());
165
166  assert_priority(PRIO_INIT);
167
168  switch (ctx->current) {
169    case DELETE_2:
170      ctx->current = DELETE_3;
171      break;
172    case DELETE_5:
173      ctx->current = DELETE_6;
174      break;
175    default:
176      rtems_test_assert(0);
177      break;
178  }
179}
180
181static void terminate_extension(Thread_Control *executing)
182{
183  test_context *ctx = &test_instance;
184  rtems_status_code sc;
185
186  rtems_test_assert(ctx->worker_task_id == rtems_task_self());
187
188  assert_priority(PRIO_INIT);
189
190  switch (ctx->current) {
191    case DELETE_0:
192      ctx->current = DELETE_1;
193      sc = rtems_task_delete(RTEMS_SELF);
194      rtems_test_assert(sc == RTEMS_SUCCESSFUL);
195      break;
196    case DELETE_1:
197      ctx->current = DELETE_2;
198      break;
199    case DELETE_4:
200      ctx->current = DELETE_5;
201      break;
202    default:
203      rtems_test_assert(0);
204      break;
205  }
206}
207
208static void worker_task(rtems_task_argument arg)
209{
210  test_context *ctx = &test_instance;
211
212  while (true) {
213    test_state state = ctx->current;
214    rtems_status_code sc;
215    bool previous_thread_life_protection;
216
217    switch (state) {
218      case SET_PRIO:
219        assert_priority(PRIO_LOW);
220        set_priority(PRIO_MID);
221        break;
222      case DO_OBTAIN_0:
223      case DO_OBTAIN_1:
224        assert_priority(PRIO_MID);
225        sc = rtems_semaphore_obtain(
226          ctx->sema_id,
227          RTEMS_WAIT,
228          RTEMS_NO_TIMEOUT
229        );
230        rtems_test_assert(sc == RTEMS_SUCCESSFUL);
231        assert_priority(PRIO_HIGH);
232        break;
233      case DO_RELEASE_0:
234      case DO_RELEASE_1:
235        assert_priority(PRIO_HIGH);
236        sc = rtems_semaphore_release(ctx->sema_id);
237        rtems_test_assert(sc == RTEMS_SUCCESSFUL);
238
239        switch (state) {
240          case DO_RELEASE_0:
241            assert_priority(PRIO_MID);
242            break;
243          case DO_RELEASE_1:
244            assert_priority(PRIO_LOW);
245            break;
246          default:
247            rtems_test_assert(0);
248            break;
249        }
250
251        break;
252      case RESTART_2:
253        assert_priority(PRIO_HIGH);
254        break;
255      case SET_PROTECTION:
256        _Thread_Disable_dispatch();
257        previous_thread_life_protection = _Thread_Set_life_protection(true);
258        rtems_test_assert(!previous_thread_life_protection);
259        _Thread_Enable_dispatch();
260        break;
261      case CLEAR_PROTECTION:
262        _Thread_Disable_dispatch();
263        previous_thread_life_protection = _Thread_Set_life_protection(false);
264        rtems_test_assert(previous_thread_life_protection);
265        ctx->current = DELETE_4;
266        _Thread_Enable_dispatch();
267        break;
268      default:
269        rtems_test_assert(0);
270        break;
271    }
272
273    ctx->current = ctx->next;
274    wake_up_main(ctx);
275  }
276}
277
278static void create_sema(test_context *ctx)
279{
280  rtems_status_code sc;
281
282  sc = rtems_semaphore_create(
283    rtems_build_name('S', 'E', 'M', 'A'),
284    1,
285    RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_PRIORITY_CEILING,
286    PRIO_HIGH,
287    &ctx->sema_id
288  );
289  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
290}
291
292static void create_and_start_worker(test_context *ctx)
293{
294  rtems_status_code sc;
295
296  sc = rtems_task_create(
297    rtems_build_name('W', 'O', 'R', 'K'),
298    PRIO_LOW,
299    RTEMS_MINIMUM_STACK_SIZE,
300    RTEMS_DEFAULT_MODES,
301    RTEMS_DEFAULT_ATTRIBUTES,
302    &ctx->worker_task_id
303  );
304  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
305
306  sc = rtems_task_start(ctx->worker_task_id, worker_task, 0);
307  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
308}
309
310static void test(void)
311{
312  test_context *ctx = &test_instance;
313  rtems_status_code sc;
314  rtems_resource_snapshot snapshot;
315
316  ctx->main_task_id = rtems_task_self();
317
318  rtems_resource_snapshot_take(&snapshot);
319
320  create_sema(ctx);
321  create_and_start_worker(ctx);
322
323  change_state_and_wait(ctx, INIT, SET_PRIO, SET_PRIO_DONE);
324  change_state_and_wait(ctx, SET_PRIO_DONE, DO_OBTAIN_0, OBTAIN_DONE_0);
325
326  sc = rtems_semaphore_delete(ctx->sema_id);
327  rtems_test_assert(sc == RTEMS_RESOURCE_IN_USE);
328
329  change_state_and_wait(ctx, OBTAIN_DONE_0, DO_RELEASE_0, RELEASE_DONE_0);
330
331  sc = rtems_semaphore_delete(ctx->sema_id);
332  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
333
334  create_sema(ctx);
335
336  change_state_and_wait(ctx, RELEASE_DONE_0, DO_OBTAIN_1, OBTAIN_DONE_1);
337
338  sc = rtems_semaphore_delete(ctx->sema_id);
339  rtems_test_assert(sc == RTEMS_RESOURCE_IN_USE);
340
341  sc = rtems_task_restart(ctx->worker_task_id, 0);
342  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
343
344  change_state_and_wait(ctx, OBTAIN_DONE_1, RESTART_0, RESTART_3);
345  change_state_and_wait(ctx, RESTART_3, DO_RELEASE_1, RELEASE_DONE_1);
346
347  sc = rtems_semaphore_delete(ctx->sema_id);
348  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
349
350  change_state(ctx, RELEASE_DONE_1, DELETE_0, INVALID);
351
352  sc = rtems_task_delete(ctx->worker_task_id);
353  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
354
355  rtems_test_assert(ctx->current == DELETE_2);
356
357  rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
358
359  create_and_start_worker(ctx);
360
361  change_state_and_wait(ctx, DELETE_3, SET_PROTECTION, SET_PROTECTION_DONE);
362  change_state(ctx, SET_PROTECTION_DONE, CLEAR_PROTECTION, INVALID);
363
364  sc = rtems_task_delete(ctx->worker_task_id);
365  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
366
367  rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
368
369  rtems_test_assert(ctx->current == DELETE_6);
370}
371
372static void Init(rtems_task_argument arg)
373{
374  TEST_BEGIN();
375
376  test();
377
378  TEST_END();
379  rtems_test_exit(0);
380}
381
382#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
383#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
384
385#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
386
387#define CONFIGURE_MAXIMUM_TASKS 2
388#define CONFIGURE_MAXIMUM_SEMAPHORES 1
389
390#define CONFIGURE_INITIAL_EXTENSIONS \
391  { \
392    .thread_restart = restart_extension, \
393    .thread_delete = delete_extension, \
394    .thread_terminate = terminate_extension \
395  }, \
396  RTEMS_TEST_INITIAL_EXTENSION
397
398#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
399
400#define CONFIGURE_INIT
401
402#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.