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

4.115
Last change on this file since f0b4fd9 was f0b4fd9, checked in by Sebastian Huber <sebastian.huber@…>, on 03/28/14 at 08:29:51

score: Do not reset resource count during restart

This fixes an integer underflow problem in case resources are released
after a thread restart.

Add new test sptests/spthreadlife01.

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