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

5
Last change on this file since c4b8b147 was c4b8b147, checked in by Sebastian Huber <sebastian.huber@…>, on 11/03/17 at 07:35:38

tests: Use simple console driver

Update #3170.
Update #3199.

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