source: rtems/testsuites/smptests/smpmutex01/init.c @ 3995e6d

Last change on this file since 3995e6d was 3995e6d, checked in by Sebastian Huber <sebastian.huber@…>, on Sep 2, 2015 at 9:58:54 AM

score: Implement SMP-specific priority queue

  • Property mode set to 100644
File size: 7.5 KB
Line 
1/*
2 * Copyright (c) 2015 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 "tmacros.h"
20
21const char rtems_test_name[] = "SMPMUTEX 1";
22
23#define SCHED_A rtems_build_name(' ', ' ', ' ', 'A')
24
25#define SCHED_B rtems_build_name(' ', ' ', ' ', 'B')
26
27#define PART_COUNT 2
28
29#define TASK_COUNT 8
30
31typedef enum {
32  REQ_WAKE_UP_MASTER = RTEMS_EVENT_0,
33  REQ_WAKE_UP_HELPER = RTEMS_EVENT_1,
34  REQ_MTX_OBTAIN = RTEMS_EVENT_2,
35  REQ_MTX_RELEASE = RTEMS_EVENT_3
36} request_id;
37
38typedef enum {
39  A_1,
40  A_2_0,
41  A_2_1,
42  M,
43  B_4,
44  B_5_0,
45  B_5_1,
46  H,
47  NONE
48} task_id;
49
50typedef struct {
51  rtems_id mtx;
52  rtems_id tasks[TASK_COUNT];
53  int generation[TASK_COUNT];
54  int expected_generation[TASK_COUNT];
55} test_context;
56
57static test_context test_instance;
58
59static void start_task(
60  test_context *ctx,
61  task_id id,
62  rtems_task_entry entry,
63  rtems_task_priority prio,
64  rtems_name scheduler
65)
66{
67  rtems_status_code sc;
68  rtems_id scheduler_id;
69
70  sc = rtems_task_create(
71    rtems_build_name('T', 'A', 'S', 'K'),
72    prio,
73    RTEMS_MINIMUM_STACK_SIZE,
74    RTEMS_DEFAULT_MODES,
75    RTEMS_DEFAULT_ATTRIBUTES,
76    &ctx->tasks[id]
77  );
78  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
79
80  sc = rtems_scheduler_ident(scheduler, &scheduler_id);
81  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
82
83  sc = rtems_task_set_scheduler(ctx->tasks[id], scheduler_id);
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 rtems_event_set wait_for_events(void)
99{
100  rtems_event_set events;
101  rtems_status_code sc;
102
103  sc = rtems_event_receive(
104    RTEMS_ALL_EVENTS,
105    RTEMS_EVENT_ANY | RTEMS_WAIT,
106    RTEMS_NO_TIMEOUT,
107    &events
108  );
109  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
110
111  return events;
112}
113
114static void sync_with_helper(test_context *ctx)
115{
116  rtems_event_set events;
117
118  send_event(ctx, H, REQ_WAKE_UP_HELPER);
119  events = wait_for_events();
120  rtems_test_assert(events == REQ_WAKE_UP_MASTER);
121}
122
123static void request(test_context *ctx, task_id id, request_id req)
124{
125  send_event(ctx, id, req);
126  sync_with_helper(ctx);
127}
128
129static void obtain(test_context *ctx)
130{
131  rtems_status_code sc;
132
133  sc = rtems_semaphore_obtain(ctx->mtx, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
134  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
135}
136
137static void release(test_context *ctx)
138{
139  rtems_status_code sc;
140
141  sc = rtems_semaphore_release(ctx->mtx);
142  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
143}
144
145static void check_generations(test_context *ctx, task_id a, task_id b)
146{
147  size_t i;
148
149  if (a != NONE) {
150    ++ctx->expected_generation[a];
151  }
152
153  if (b != NONE) {
154    ++ctx->expected_generation[b];
155  }
156
157  for (i = 0; i < TASK_COUNT; ++i) {
158    rtems_test_assert(ctx->generation[i] == ctx->expected_generation[i]);
159  }
160}
161
162static void helper(rtems_task_argument arg)
163{
164  test_context *ctx = &test_instance;
165
166  while (true) {
167    rtems_event_set events = wait_for_events();
168    rtems_test_assert(events == REQ_WAKE_UP_HELPER);
169    send_event(ctx, M, REQ_WAKE_UP_MASTER);
170  }
171}
172
173static void worker(rtems_task_argument arg)
174{
175  test_context *ctx = &test_instance;
176  task_id id = arg;
177
178  while (true) {
179    rtems_event_set events = wait_for_events();
180
181    if ((events & REQ_MTX_OBTAIN) != 0) {
182      obtain(ctx);
183      ++ctx->generation[id];
184    }
185
186    if ((events & REQ_MTX_RELEASE) != 0) {
187      release(ctx);
188      ++ctx->generation[id];
189    }
190  }
191}
192
193static void test(void)
194{
195  test_context *ctx = &test_instance;
196  rtems_status_code sc;
197
198  ctx->tasks[M] = rtems_task_self();
199  start_task(ctx, A_1, worker, 1, SCHED_A);
200  start_task(ctx, A_2_0, worker, 2, SCHED_A);
201  start_task(ctx, A_2_1, worker, 2, SCHED_A);
202  start_task(ctx, B_4, worker, 4, SCHED_B);
203  start_task(ctx, B_5_0, worker, 5, SCHED_B);
204  start_task(ctx, B_5_1, worker, 5, SCHED_B);
205  start_task(ctx, H, helper, 6, SCHED_B);
206
207  sc = rtems_semaphore_create(
208    rtems_build_name(' ', 'M', 'T', 'X'),
209    1,
210    RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY,
211    0,
212    &ctx->mtx
213  );
214  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
215
216  obtain(ctx);
217  request(ctx, A_1, REQ_MTX_OBTAIN);
218  check_generations(ctx, NONE, NONE);
219  release(ctx);
220  check_generations(ctx, A_1, NONE);
221  request(ctx, A_1, REQ_MTX_RELEASE);
222  check_generations(ctx, A_1, NONE);
223
224  obtain(ctx);
225  request(ctx, A_2_0, REQ_MTX_OBTAIN);
226  request(ctx, A_1, REQ_MTX_OBTAIN);
227  request(ctx, A_2_1, REQ_MTX_OBTAIN);
228  check_generations(ctx, NONE, NONE);
229  release(ctx);
230  check_generations(ctx, A_1, NONE);
231  request(ctx, A_1, REQ_MTX_RELEASE);
232  check_generations(ctx, A_1, A_2_0);
233  request(ctx, A_2_0, REQ_MTX_RELEASE);
234  check_generations(ctx, A_2_0, A_2_1);
235  request(ctx, A_2_1, REQ_MTX_RELEASE);
236  check_generations(ctx, A_2_1, NONE);
237
238  obtain(ctx);
239  request(ctx, B_5_0, REQ_MTX_OBTAIN);
240  request(ctx, B_4, REQ_MTX_OBTAIN);
241  request(ctx, B_5_1, REQ_MTX_OBTAIN);
242  check_generations(ctx, NONE, NONE);
243  release(ctx);
244  sync_with_helper(ctx);
245  check_generations(ctx, B_4, NONE);
246  request(ctx, B_4, REQ_MTX_RELEASE);
247  check_generations(ctx, B_4, B_5_0);
248  request(ctx, B_5_0, REQ_MTX_RELEASE);
249  check_generations(ctx, B_5_0, B_5_1);
250  request(ctx, B_5_1, REQ_MTX_RELEASE);
251  check_generations(ctx, B_5_1, NONE);
252
253  obtain(ctx);
254  request(ctx, A_2_0, REQ_MTX_OBTAIN);
255  request(ctx, B_5_0, REQ_MTX_OBTAIN);
256  request(ctx, B_5_1, REQ_MTX_OBTAIN);
257  request(ctx, B_4, REQ_MTX_OBTAIN);
258  request(ctx, A_2_1, REQ_MTX_OBTAIN);
259  request(ctx, A_1, REQ_MTX_OBTAIN);
260  check_generations(ctx, NONE, NONE);
261  release(ctx);
262  check_generations(ctx, A_1, NONE);
263  request(ctx, A_1, REQ_MTX_RELEASE);
264  check_generations(ctx, A_1, B_4);
265  request(ctx, B_4, REQ_MTX_RELEASE);
266  check_generations(ctx, B_4, A_2_0);
267  request(ctx, A_2_0, REQ_MTX_RELEASE);
268  check_generations(ctx, A_2_0, B_5_0);
269  request(ctx, B_5_0, REQ_MTX_RELEASE);
270  check_generations(ctx, B_5_0, A_2_1);
271  request(ctx, A_2_1, REQ_MTX_RELEASE);
272  check_generations(ctx, A_2_1, B_5_1);
273  request(ctx, B_5_1, REQ_MTX_RELEASE);
274  check_generations(ctx, B_5_1, NONE);
275}
276
277static void Init(rtems_task_argument arg)
278{
279  TEST_BEGIN();
280
281  if (rtems_get_processor_count() >= PART_COUNT) {
282    test();
283  }
284
285  TEST_END();
286  rtems_test_exit(0);
287}
288
289#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
290#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
291
292#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
293
294#define CONFIGURE_SMP_APPLICATION
295
296#define CONFIGURE_SMP_MAXIMUM_PROCESSORS PART_COUNT
297
298#define CONFIGURE_SCHEDULER_SIMPLE_SMP
299
300#include <rtems/scheduler.h>
301
302RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(a);
303
304RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(b);
305
306#define CONFIGURE_SCHEDULER_CONTROLS \
307  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(a, SCHED_A), \
308  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(b, SCHED_B)
309
310#define CONFIGURE_SMP_SCHEDULER_ASSIGNMENTS \
311  RTEMS_SCHEDULER_ASSIGN(0, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_MANDATORY), \
312  RTEMS_SCHEDULER_ASSIGN(1, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL)
313
314#define CONFIGURE_MAXIMUM_TASKS TASK_COUNT
315
316#define CONFIGURE_MAXIMUM_SEMAPHORES 1
317
318#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
319
320#define CONFIGURE_INIT_TASK_PRIORITY 3
321
322#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
323
324#define CONFIGURE_INIT
325
326#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.