source: rtems/testsuites/smptests/smpthreadlife01/init.c @ 98c6d50

5
Last change on this file since 98c6d50 was 98c6d50, checked in by Chris Johns <chrisj@…>, on 10/19/17 at 05:39:16

testsuite: Use printk for all test output where possible.

  • Remove the printf support leaving the direct printk support configured with TESTS_USE_PRINTK and all other output goes via a buffered vsniprintf call to printk.
  • Control the test's single init for functions and global data with TEST_INIT and not CONFIGURE_INIT. They are now separate.

Updates #3170.

  • Property mode set to 100644
File size: 11.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#define TEST_INIT
20
21#include "tmacros.h"
22
23#include <rtems.h>
24#include <rtems/counter.h>
25#include <rtems/libcsupport.h>
26#include <rtems/score/profiling.h>
27#include <rtems/score/smpbarrier.h>
28#include <rtems/score/threadimpl.h>
29
30const char rtems_test_name[] = "SMPTHREADLIFE 1";
31
32#define CPU_COUNT 2
33
34typedef struct {
35  volatile rtems_task_argument main_arg;
36  volatile rtems_task_argument worker_arg;
37  volatile bool terminated;
38  SMP_barrier_Control barrier;
39  SMP_barrier_State main_barrier_state;
40  SMP_barrier_State worker_barrier_state;
41  Thread_Control *delay_switch_for_executing;
42  rtems_id worker_id;
43} test_context;
44
45static test_context test_instance = {
46  .barrier = SMP_BARRIER_CONTROL_INITIALIZER,
47  .main_barrier_state = SMP_BARRIER_STATE_INITIALIZER,
48  .worker_barrier_state = SMP_BARRIER_STATE_INITIALIZER
49};
50
51static void barrier(test_context *ctx, SMP_barrier_State *state)
52{
53  _SMP_barrier_Wait(&ctx->barrier, state, CPU_COUNT);
54}
55
56static void restart_extension(
57  Thread_Control *executing,
58  Thread_Control *restarted
59)
60{
61  rtems_test_assert(executing == restarted);
62}
63
64static void delete_extension(
65  Thread_Control *executing,
66  Thread_Control *deleted
67)
68{
69  rtems_test_assert(executing != deleted);
70}
71
72static void terminate_extension(Thread_Control *executing)
73{
74  test_context *ctx = &test_instance;
75
76  ctx->terminated = true;
77}
78
79static void switch_extension(Thread_Control *executing, Thread_Control *heir)
80{
81  test_context *ctx = &test_instance;
82
83  if (ctx->delay_switch_for_executing == executing) {
84    ctx->delay_switch_for_executing = NULL;
85
86    /* (A) */
87    barrier(ctx, &ctx->worker_barrier_state);
88
89    rtems_counter_delay_nanoseconds(100000000);
90
91    /* Avoid bad profiling statisitics */
92    _Profiling_Thread_dispatch_disable( _Per_CPU_Get(), 0 );
93  }
94}
95
96static void worker_task(rtems_task_argument arg)
97{
98  test_context *ctx = &test_instance;
99
100  rtems_test_assert(arg == ctx->main_arg);
101
102  ctx->worker_arg = arg;
103
104  /* (B) */
105  barrier(ctx, &ctx->worker_barrier_state);
106
107  while (true) {
108    /* Do nothing */
109  }
110}
111
112static void test_restart(void)
113{
114  test_context *ctx = &test_instance;
115  rtems_status_code sc;
116  rtems_id id;
117  rtems_task_argument arg;
118  rtems_resource_snapshot snapshot;
119
120  rtems_resource_snapshot_take(&snapshot);
121
122  sc = rtems_task_create(
123    rtems_build_name('W', 'O', 'R', 'K'),
124    1,
125    RTEMS_MINIMUM_STACK_SIZE,
126    RTEMS_DEFAULT_MODES,
127    RTEMS_DEFAULT_ATTRIBUTES,
128    &id
129  );
130  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
131
132  sc = rtems_task_start(id, worker_task, 0);
133  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
134
135  /* (B) */
136  barrier(ctx, &ctx->main_barrier_state);
137
138  for (arg = 1; arg < 23; ++arg) {
139    ctx->main_arg = arg;
140    ctx->worker_arg = 0;
141
142    sc = rtems_task_restart(id, arg);
143    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
144
145    /* (B) */
146    barrier(ctx, &ctx->main_barrier_state);
147
148    rtems_test_assert(ctx->worker_arg == arg);
149  }
150
151  sc = rtems_task_delete(id);
152  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
153
154  rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
155}
156
157static void test_delete(void)
158{
159  test_context *ctx = &test_instance;
160  rtems_status_code sc;
161  rtems_id id;
162  rtems_task_argument arg;
163  rtems_resource_snapshot snapshot;
164
165  rtems_resource_snapshot_take(&snapshot);
166
167  for (arg = 31; arg < 57; ++arg) {
168    ctx->main_arg = arg;
169    ctx->worker_arg = 0;
170    ctx->terminated = false;
171
172    sc = rtems_task_create(
173      rtems_build_name('W', 'O', 'R', 'K'),
174      1,
175      RTEMS_MINIMUM_STACK_SIZE,
176      RTEMS_DEFAULT_MODES,
177      RTEMS_DEFAULT_ATTRIBUTES,
178      &id
179    );
180    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
181
182    sc = rtems_task_start(id, worker_task, arg);
183    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
184
185    /* (B) */
186    barrier(ctx, &ctx->main_barrier_state);
187
188    rtems_test_assert(ctx->worker_arg == arg);
189    rtems_test_assert(!ctx->terminated);
190
191    sc = rtems_task_delete(id);
192    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
193
194    rtems_test_assert(ctx->terminated);
195
196    rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
197  }
198}
199
200static void delay_ipi_task(rtems_task_argument variant)
201{
202  test_context *ctx = &test_instance;
203  ISR_Level level;
204
205  _ISR_Local_disable(level);
206
207  /* (C) */
208  barrier(ctx, &ctx->worker_barrier_state);
209
210  /*
211   * Interrupts are disabled, so the inter-processor interrupt deleting us will
212   * be delayed a bit.
213   */
214  rtems_counter_delay_nanoseconds(100000000);
215
216  if (variant != 0) {
217    _Thread_Dispatch_disable();
218  }
219
220  _ISR_Local_enable(level);
221
222  /*
223   * We get deleted as a side effect of enabling the thread life protection or
224   * later if we enable the thread dispatching.
225   */
226  _Thread_Set_life_protection( THREAD_LIFE_PROTECTED );
227
228  if (variant != 0) {
229    _Thread_Dispatch_enable( _Per_CPU_Get() );
230  }
231
232  rtems_test_assert(0);
233}
234
235static void test_set_life_protection(rtems_task_argument variant)
236{
237  test_context *ctx = &test_instance;
238  rtems_status_code sc;
239  rtems_id id;
240  rtems_resource_snapshot snapshot;
241
242  rtems_resource_snapshot_take(&snapshot);
243
244  sc = rtems_task_create(
245    rtems_build_name('D', 'E', 'L', 'Y'),
246    1,
247    RTEMS_MINIMUM_STACK_SIZE,
248    RTEMS_DEFAULT_MODES,
249    RTEMS_DEFAULT_ATTRIBUTES,
250    &id
251  );
252  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
253
254  sc = rtems_task_start(id, delay_ipi_task, variant);
255  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
256
257  /* (C) */
258  barrier(ctx, &ctx->main_barrier_state);
259
260  sc = rtems_task_delete(id);
261  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
262
263  rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
264}
265
266static void delay_switch_task(rtems_task_argument arg)
267{
268  test_context *ctx = &test_instance;
269  rtems_status_code sc;
270
271  ctx->delay_switch_for_executing = _Thread_Get_executing();
272
273  /* (D) */
274  barrier(ctx, &ctx->worker_barrier_state);
275
276  sc = rtems_task_delete(RTEMS_SELF);
277  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
278}
279
280static void test_wait_for_execution_stop(void)
281{
282  test_context *ctx = &test_instance;
283  rtems_status_code sc;
284  rtems_id id;
285  rtems_resource_snapshot snapshot;
286
287  rtems_resource_snapshot_take(&snapshot);
288
289  sc = rtems_task_create(
290    rtems_build_name('S', 'W', 'I', 'T'),
291    1,
292    RTEMS_MINIMUM_STACK_SIZE,
293    RTEMS_DEFAULT_MODES,
294    RTEMS_DEFAULT_ATTRIBUTES,
295    &id
296  );
297  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
298
299  sc = rtems_task_start(id, delay_switch_task, 0);
300  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
301
302  /* (D) */
303  barrier(ctx, &ctx->main_barrier_state);
304
305  /* (A) */
306  barrier(ctx, &ctx->main_barrier_state);
307
308  sc = rtems_task_create(
309    rtems_build_name('W', 'A', 'I', 'T'),
310    1,
311    RTEMS_MINIMUM_STACK_SIZE,
312    RTEMS_DEFAULT_MODES,
313    RTEMS_DEFAULT_ATTRIBUTES,
314    &id
315  );
316  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
317
318  sc = rtems_task_delete(id);
319  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
320
321  rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
322}
323
324typedef enum {
325  TEST_OP_SUSPEND,
326  TEST_OP_EVENT,
327  TEST_OP_EVENT_SYSTEM
328} test_op;
329
330static void op_begin_suspend(void)
331{
332  rtems_status_code sc;
333
334  sc = rtems_task_suspend(RTEMS_SELF);
335  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
336}
337
338static void op_begin_event(void)
339{
340  rtems_status_code sc;
341  rtems_event_set events;
342
343  events = 0;
344  sc = rtems_event_receive(
345    RTEMS_EVENT_0,
346    RTEMS_EVENT_ALL | RTEMS_WAIT,
347    RTEMS_NO_TIMEOUT,
348    &events
349  );
350  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
351  rtems_test_assert(events == RTEMS_EVENT_0);
352}
353
354static void op_begin_event_system(void)
355{
356  rtems_status_code sc;
357  rtems_event_set events;
358
359  events = 0;
360  sc = rtems_event_system_receive(
361    RTEMS_EVENT_0,
362    RTEMS_EVENT_ALL | RTEMS_WAIT,
363    RTEMS_NO_TIMEOUT,
364    &events
365  );
366  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
367  rtems_test_assert(events == RTEMS_EVENT_0);
368}
369
370static void (*const test_ops_begin[])(void) = {
371  op_begin_suspend,
372  op_begin_event,
373  op_begin_event_system
374};
375
376static void op_end_suspend(test_context *ctx)
377{
378  rtems_status_code sc;
379
380  sc = rtems_task_resume(ctx->worker_id);
381  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
382}
383
384static void op_end_event(test_context *ctx)
385{
386  rtems_status_code sc;
387
388  sc = rtems_event_send(ctx->worker_id, RTEMS_EVENT_0);
389  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
390}
391
392static void op_end_event_system(test_context *ctx)
393{
394  rtems_status_code sc;
395
396  sc = rtems_event_system_send(ctx->worker_id, RTEMS_EVENT_0);
397  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
398}
399
400static void (*const test_ops_end[])(test_context *) = {
401  op_end_suspend,
402  op_end_event,
403  op_end_event_system
404};
405
406static void op_worker_task(rtems_task_argument arg)
407{
408  test_context *ctx = &test_instance;
409  test_op op = arg;
410  Thread_Life_state previous_life_state;
411
412  previous_life_state = _Thread_Set_life_protection(THREAD_LIFE_PROTECTED);
413
414  /* (E) */
415  barrier(ctx, &ctx->worker_barrier_state);
416
417  /* (F) */
418  barrier(ctx, &ctx->worker_barrier_state);
419
420  (*test_ops_begin[op])();
421
422  _Thread_Set_life_protection(previous_life_state);
423  rtems_test_assert(0);
424}
425
426static void help_task(rtems_task_argument arg)
427{
428  test_context *ctx = &test_instance;
429  test_op op = arg;
430
431  /* (F) */
432  barrier(ctx, &ctx->main_barrier_state);
433
434  rtems_counter_delay_nanoseconds(100000000);
435
436  (*test_ops_end[op])(ctx);
437
438  rtems_task_suspend(RTEMS_SELF);
439  rtems_test_assert(0);
440}
441
442static void test_operation_with_delete_in_progress(test_op op)
443{
444  test_context *ctx = &test_instance;
445  rtems_status_code sc;
446  rtems_id help_id;
447  rtems_resource_snapshot snapshot;
448
449  rtems_resource_snapshot_take(&snapshot);
450
451  sc = rtems_task_create(
452    rtems_build_name('W', 'O', 'R', 'K'),
453    1,
454    RTEMS_MINIMUM_STACK_SIZE,
455    RTEMS_DEFAULT_MODES,
456    RTEMS_DEFAULT_ATTRIBUTES,
457    &ctx->worker_id
458  );
459  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
460
461  sc = rtems_task_start(ctx->worker_id, op_worker_task, op);
462  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
463
464  /* (E) */
465  barrier(ctx, &ctx->main_barrier_state);
466
467  sc = rtems_task_create(
468    rtems_build_name('H', 'E', 'L', 'P'),
469    2,
470    RTEMS_MINIMUM_STACK_SIZE,
471    RTEMS_DEFAULT_MODES,
472    RTEMS_DEFAULT_ATTRIBUTES,
473    &help_id
474  );
475  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
476
477  sc = rtems_task_start(help_id, help_task, op);
478  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
479
480  sc = rtems_task_delete(ctx->worker_id);
481  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
482
483  sc = rtems_task_delete(help_id);
484  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
485
486  rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
487}
488
489static void Init(rtems_task_argument arg)
490{
491  TEST_BEGIN();
492
493  if (rtems_get_processor_count() >= CPU_COUNT) {
494    test_restart();
495    test_delete();
496    test_set_life_protection(0);
497    test_set_life_protection(1);
498    test_wait_for_execution_stop();
499    test_operation_with_delete_in_progress(TEST_OP_SUSPEND);
500    test_operation_with_delete_in_progress(TEST_OP_EVENT);
501    test_operation_with_delete_in_progress(TEST_OP_EVENT_SYSTEM);
502  }
503
504  TEST_END();
505  rtems_test_exit(0);
506}
507
508#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
509#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
510
511#define CONFIGURE_MAXIMUM_PROCESSORS CPU_COUNT
512
513#define CONFIGURE_MAXIMUM_TASKS (CPU_COUNT + 1)
514
515#define CONFIGURE_INITIAL_EXTENSIONS \
516  { \
517    .thread_restart = restart_extension, \
518    .thread_delete = delete_extension, \
519    .thread_terminate = terminate_extension, \
520    .thread_switch = switch_extension \
521  }, \
522  RTEMS_TEST_INITIAL_EXTENSION
523
524#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
525
526#define CONFIGURE_INIT
527
528#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.