source: rtems/testsuites/sptests/spmutex01/init.c @ 83e6cefa

4.10
Last change on this file since 83e6cefa was 83e6cefa, checked in by Sebastian Huber <sebastian.huber@…>, on 12/20/17 at 18:24:00

sptests/spmutex01: test flush with inherit prio

  • Property mode set to 100644
File size: 11.3 KB
Line 
1/*
2 * Copyright (c) 2015, 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 "tmacros.h"
23
24const char rtems_test_name[] = "SPMUTEX 1";
25
26#define TASK_COUNT 5
27
28#define MTX_COUNT 3
29
30typedef enum {
31  REQ_WAKE_UP_MASTER = RTEMS_EVENT_0,
32  REQ_WAKE_UP_HELPER = RTEMS_EVENT_1,
33  REQ_MTX_0_OBTAIN = RTEMS_EVENT_2,
34  REQ_MTX_0_OBTAIN_UNSATISFIED = RTEMS_EVENT_3,
35  REQ_MTX_0_RELEASE = RTEMS_EVENT_4,
36  REQ_MTX_1_OBTAIN = RTEMS_EVENT_5,
37  REQ_MTX_1_OBTAIN_TIMEOUT = RTEMS_EVENT_6,
38  REQ_MTX_1_RELEASE = RTEMS_EVENT_7,
39  REQ_MTX_2_OBTAIN = RTEMS_EVENT_8,
40  REQ_MTX_2_RELEASE = RTEMS_EVENT_9,
41} request_id;
42
43typedef enum {
44  M,
45  A_1,
46  A_2_0,
47  A_2_1,
48  H,
49  NONE
50} task_id;
51
52typedef enum {
53  MTX_0,
54  MTX_1,
55  MTX_2
56} mutex_id;
57
58typedef struct {
59  rtems_id mtx[MTX_COUNT];
60  rtems_id tasks[TASK_COUNT];
61  int generation[TASK_COUNT];
62  int expected_generation[TASK_COUNT];
63} test_context;
64
65static test_context test_instance;
66
67static void start_task(
68  test_context *ctx,
69  task_id id,
70  rtems_task_entry entry,
71  rtems_task_priority prio
72)
73{
74  rtems_status_code sc;
75
76  sc = rtems_task_create(
77    rtems_build_name('T', 'A', 'S', 'K'),
78    prio,
79    RTEMS_MINIMUM_STACK_SIZE,
80    RTEMS_DEFAULT_MODES,
81    RTEMS_DEFAULT_ATTRIBUTES,
82    &ctx->tasks[id]
83  );
84  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
85
86  sc = rtems_task_start(ctx->tasks[id], entry, id);
87  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
88}
89
90static void send_event(test_context *ctx, task_id id, rtems_event_set events)
91{
92  rtems_status_code sc;
93
94  sc = rtems_event_send(ctx->tasks[id], events);
95  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
96}
97
98static void wait(void)
99{
100  rtems_status_code sc;
101
102  sc = rtems_task_wake_after(4);
103  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
104}
105
106static rtems_event_set wait_for_events(void)
107{
108  rtems_event_set events;
109  rtems_status_code sc;
110
111  sc = rtems_event_receive(
112    RTEMS_ALL_EVENTS,
113    RTEMS_EVENT_ANY | RTEMS_WAIT,
114    RTEMS_NO_TIMEOUT,
115    &events
116  );
117  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
118
119  return events;
120}
121
122static void sync_with_helper(test_context *ctx)
123{
124  rtems_event_set events;
125
126  send_event(ctx, H, REQ_WAKE_UP_HELPER);
127  events = wait_for_events();
128  rtems_test_assert(events == REQ_WAKE_UP_MASTER);
129}
130
131static void request(test_context *ctx, task_id id, request_id req)
132{
133  send_event(ctx, id, req);
134  sync_with_helper(ctx);
135}
136
137static void obtain_timeout(test_context *ctx, mutex_id id)
138{
139  rtems_status_code sc;
140
141  sc = rtems_semaphore_obtain(ctx->mtx[id], RTEMS_WAIT, 2);
142  rtems_test_assert(sc == RTEMS_TIMEOUT);
143}
144
145static void obtain_unsatisfied(test_context *ctx, mutex_id id)
146{
147  rtems_status_code sc;
148
149  sc = rtems_semaphore_obtain(ctx->mtx[id], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
150  rtems_test_assert(sc == RTEMS_UNSATISFIED);
151}
152
153static void obtain(test_context *ctx, mutex_id id)
154{
155  rtems_status_code sc;
156
157  sc = rtems_semaphore_obtain(ctx->mtx[id], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
158  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
159}
160
161static void release(test_context *ctx, mutex_id id)
162{
163  rtems_status_code sc;
164
165  sc = rtems_semaphore_release(ctx->mtx[id]);
166  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
167}
168
169static void flush(test_context *ctx, mutex_id id)
170{
171  rtems_status_code sc;
172
173  sc = rtems_semaphore_flush(ctx->mtx[id]);
174  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
175}
176
177static void check_generations(test_context *ctx, task_id a, task_id b)
178{
179  size_t i;
180
181  if (a != NONE) {
182    ++ctx->expected_generation[a];
183  }
184
185  if (b != NONE) {
186    ++ctx->expected_generation[b];
187  }
188
189  for (i = 0; i < TASK_COUNT; ++i) {
190    rtems_test_assert(ctx->generation[i] == ctx->expected_generation[i]);
191  }
192}
193
194static void assert_prio(
195  test_context *ctx,
196  task_id id,
197  rtems_task_priority expected
198)
199{
200  rtems_task_priority actual;
201  rtems_status_code sc;
202
203  sc = rtems_task_set_priority(
204    ctx->tasks[id],
205    RTEMS_CURRENT_PRIORITY,
206    &actual
207  );
208  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
209  rtems_test_assert(expected == actual);
210}
211
212static void change_prio(
213  test_context *ctx,
214  task_id id,
215  rtems_task_priority prio
216)
217{
218  rtems_status_code sc;
219
220  sc = rtems_task_set_priority(
221    ctx->tasks[id],
222    prio,
223    &prio
224  );
225  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
226}
227
228static void helper(rtems_task_argument arg)
229{
230  test_context *ctx = &test_instance;
231
232  while (true) {
233    rtems_event_set events = wait_for_events();
234    rtems_test_assert(events == REQ_WAKE_UP_HELPER);
235    send_event(ctx, M, REQ_WAKE_UP_MASTER);
236  }
237}
238
239static void worker(rtems_task_argument arg)
240{
241  test_context *ctx = &test_instance;
242  task_id id = arg;
243
244  while (true) {
245    rtems_event_set events = wait_for_events();
246
247    if ((events & REQ_MTX_0_OBTAIN) != 0) {
248      obtain(ctx, MTX_0);
249      ++ctx->generation[id];
250    }
251
252    if ((events & REQ_MTX_0_OBTAIN_UNSATISFIED) != 0) {
253      obtain_unsatisfied(ctx, MTX_0);
254      ++ctx->generation[id];
255    }
256
257    if ((events & REQ_MTX_0_RELEASE) != 0) {
258      release(ctx, MTX_0);
259      ++ctx->generation[id];
260    }
261
262    if ((events & REQ_MTX_1_OBTAIN) != 0) {
263      obtain(ctx, MTX_1);
264      ++ctx->generation[id];
265    }
266
267    if ((events & REQ_MTX_1_OBTAIN_TIMEOUT) != 0) {
268      obtain_timeout(ctx, MTX_1);
269      ++ctx->generation[id];
270    }
271
272    if ((events & REQ_MTX_1_RELEASE) != 0) {
273      release(ctx, MTX_1);
274      ++ctx->generation[id];
275    }
276
277    if ((events & REQ_MTX_2_OBTAIN) != 0) {
278      obtain(ctx, MTX_2);
279      ++ctx->generation[id];
280    }
281
282    if ((events & REQ_MTX_2_RELEASE) != 0) {
283      release(ctx, MTX_2);
284      ++ctx->generation[id];
285    }
286  }
287}
288
289static void set_up(test_context *ctx)
290{
291  rtems_status_code sc;
292  int status;
293  size_t i;
294
295  ctx->tasks[M] = rtems_task_self();
296  start_task(ctx, A_1, worker, 1);
297  start_task(ctx, A_2_0, worker, 2);
298  start_task(ctx, A_2_1, worker, 2);
299  start_task(ctx, H, helper, 3);
300
301  for (i = 0; i < MTX_COUNT; ++i) {
302    sc = rtems_semaphore_create(
303      rtems_build_name(' ', 'M', 'T', 'X'),
304      1,
305      RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY,
306      0,
307      &ctx->mtx[i]
308    );
309    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
310  }
311}
312
313static void test_inherit(test_context *ctx)
314{
315  assert_prio(ctx, M, 3);
316  obtain(ctx, MTX_0);
317  request(ctx, A_1, REQ_MTX_0_OBTAIN);
318  check_generations(ctx, NONE, NONE);
319  assert_prio(ctx, M, 1);
320  change_prio(ctx, A_1, 2);
321  assert_prio(ctx, M, 2);
322  change_prio(ctx, A_1, 3);
323  assert_prio(ctx, M, 3);
324  change_prio(ctx, A_1, 4);
325  assert_prio(ctx, M, 3);
326  change_prio(ctx, A_1, 1);
327  assert_prio(ctx, M, 1);
328  release(ctx, MTX_0);
329  check_generations(ctx, A_1, NONE);
330  assert_prio(ctx, M, 3);
331  request(ctx, A_1, REQ_MTX_0_RELEASE);
332  check_generations(ctx, A_1, NONE);
333}
334
335static void test_inherit_fifo_for_equal_priority(test_context *ctx)
336{
337  assert_prio(ctx, M, 3);
338  obtain(ctx, MTX_0);
339  request(ctx, A_2_0, REQ_MTX_0_OBTAIN);
340  request(ctx, A_1, REQ_MTX_0_OBTAIN);
341  request(ctx, A_2_1, REQ_MTX_0_OBTAIN);
342  check_generations(ctx, NONE, NONE);
343  assert_prio(ctx, M, 1);
344  release(ctx, MTX_0);
345  check_generations(ctx, A_1, NONE);
346  assert_prio(ctx, M, 3);
347  assert_prio(ctx, A_1, 1);
348  request(ctx, A_1, REQ_MTX_0_RELEASE);
349  check_generations(ctx, A_1, A_2_0);
350  request(ctx, A_2_0, REQ_MTX_0_RELEASE);
351  check_generations(ctx, A_2_0, A_2_1);
352  request(ctx, A_2_1, REQ_MTX_0_RELEASE);
353  check_generations(ctx, A_2_1, NONE);
354}
355
356static void test_inherit_nested_vertical(test_context *ctx)
357{
358  assert_prio(ctx, M, 3);
359  obtain(ctx, MTX_0);
360  obtain(ctx, MTX_1);
361  request(ctx, A_1, REQ_MTX_1_OBTAIN);
362  check_generations(ctx, NONE, NONE);
363  assert_prio(ctx, M, 1);
364  release(ctx, MTX_1);
365  check_generations(ctx, A_1, NONE);
366  assert_prio(ctx, M, 3);
367  request(ctx, A_1, REQ_MTX_1_RELEASE);
368  check_generations(ctx, A_1, NONE);
369  release(ctx, MTX_0);
370}
371
372static void test_inherit_nested_vertical_timeout(test_context *ctx)
373{
374  assert_prio(ctx, M, 3);
375  obtain(ctx, MTX_0);
376  obtain(ctx, MTX_1);
377  request(ctx, A_1, REQ_MTX_1_OBTAIN_TIMEOUT);
378  check_generations(ctx, NONE, NONE);
379  assert_prio(ctx, M, 1);
380  wait();
381  check_generations(ctx, A_1, NONE);
382  assert_prio(ctx, M, 3);
383  release(ctx, MTX_1);
384  release(ctx, MTX_0);
385}
386
387static void test_inherit_nested_horizontal(test_context *ctx)
388{
389  assert_prio(ctx, M, 3);
390  obtain(ctx, MTX_0);
391  request(ctx, A_2_0, REQ_MTX_1_OBTAIN);
392  check_generations(ctx, A_2_0, NONE);
393  request(ctx, A_2_0, REQ_MTX_0_OBTAIN);
394  check_generations(ctx, NONE, NONE);
395  assert_prio(ctx, M, 2);
396  request(ctx, A_1, REQ_MTX_1_OBTAIN_TIMEOUT);
397  check_generations(ctx, NONE, NONE);
398  assert_prio(ctx, A_2_0, 1);
399  assert_prio(ctx, M, 1);
400  wait();
401  check_generations(ctx, A_1, NONE);
402  assert_prio(ctx, A_2_0, 2);
403  assert_prio(ctx, M, 2);
404  request(ctx, A_1, REQ_MTX_1_OBTAIN);
405  check_generations(ctx, NONE, NONE);
406  assert_prio(ctx, A_2_0, 1);
407  assert_prio(ctx, M, 1);
408  change_prio(ctx, A_1, 2);
409  assert_prio(ctx, M, 2);
410  change_prio(ctx, A_1, 3);
411  assert_prio(ctx, M, 2);
412  change_prio(ctx, A_2_0, 3);
413  assert_prio(ctx, M, 3);
414  change_prio(ctx, A_2_0, 2);
415  assert_prio(ctx, M, 2);
416  change_prio(ctx, A_1, 1);
417  assert_prio(ctx, M, 1);
418  release(ctx, MTX_0);
419  check_generations(ctx, A_2_0, NONE);
420  assert_prio(ctx, A_2_0, 1);
421  assert_prio(ctx, M, 3);
422  request(ctx, A_2_0, REQ_MTX_0_RELEASE);
423  check_generations(ctx, A_2_0, NONE);
424  assert_prio(ctx, A_2_0, 1);
425  request(ctx, A_2_0, REQ_MTX_1_RELEASE);
426  check_generations(ctx, A_1, A_2_0);
427  assert_prio(ctx, A_2_0, 2);
428  request(ctx, A_1, REQ_MTX_1_RELEASE);
429  check_generations(ctx, A_1, NONE);
430}
431
432static void test_inherit_flush(test_context *ctx)
433{
434  assert_prio(ctx, M, 3);
435  obtain(ctx, MTX_0);
436  request(ctx, A_1, REQ_MTX_0_OBTAIN_UNSATISFIED);
437  check_generations(ctx, NONE, NONE);
438  assert_prio(ctx, M, 1);
439  flush(ctx, MTX_0);
440  check_generations(ctx, A_1, NONE);
441  assert_prio(ctx, M, 3);
442  release(ctx, MTX_0);
443}
444
445static void tear_down(test_context *ctx)
446{
447  rtems_status_code sc;
448  size_t i;
449
450  for (i = 1; i < TASK_COUNT; ++i) {
451    sc = rtems_task_delete(ctx->tasks[i]);
452    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
453  }
454
455  for (i = 0; i < MTX_COUNT; ++i) {
456    sc = rtems_semaphore_delete(ctx->mtx[i]);
457    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
458  }
459}
460
461static void Init(rtems_task_argument arg)
462{
463  test_context *ctx = &test_instance;
464  rtems_resource_snapshot snapshot;
465
466  TEST_BEGIN();
467  rtems_resource_snapshot_take(&snapshot);
468
469  set_up(ctx);
470  test_inherit(ctx);
471  test_inherit_fifo_for_equal_priority(ctx);
472  test_inherit_nested_vertical(ctx);
473  test_inherit_nested_vertical_timeout(ctx);
474  test_inherit_nested_horizontal(ctx);
475  test_inherit_flush(ctx);
476  tear_down(ctx);
477
478  rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
479  TEST_END();
480  rtems_test_exit(0);
481}
482
483#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
484#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
485
486#define CONFIGURE_MAXIMUM_TASKS TASK_COUNT
487
488#define CONFIGURE_MAXIMUM_SEMAPHORES 3
489
490#ifdef RTEMS_POSIX_API
491#define CONFIGURE_MAXIMUM_POSIX_MUTEXES 1
492#endif
493
494#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
495
496#define CONFIGURE_INIT_TASK_PRIORITY 3
497
498#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES
499
500#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
501
502#define CONFIGURE_INIT
503
504#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.