source: rtems/testsuites/smptests/smpmutex02/init.c @ 57a00bc6

5
Last change on this file since 57a00bc6 was 57a00bc6, checked in by Sebastian Huber <sebastian.huber@…>, on 07/05/16 at 09:30:14

smptests/smpmutex02: New test

Update #2765.

  • Property mode set to 100644
File size: 12.6 KB
Line 
1/*
2 * Copyright (c) 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 <inttypes.h>
20#include <string.h>
21#include <stdio.h>
22
23#include <rtems.h>
24#include <rtems/libcsupport.h>
25
26#include "tmacros.h"
27
28const char rtems_test_name[] = "SMPMUTEX 2";
29
30#define MTX_PER_CPU 12
31
32#define WORKER_PER_CPU 4
33
34#define CPU_COUNT 32
35
36#define MTX_COUNT (CPU_COUNT * MTX_PER_CPU)
37
38#define WORKER_COUNT (CPU_COUNT * WORKER_PER_CPU)
39
40typedef struct {
41  uint32_t obtain_counter;
42  uint32_t deadlock_counter;
43  uint32_t timeout_counter;
44  uint32_t release_counter;
45  uint32_t max_nest_level;
46} test_stats;
47
48typedef struct {
49  uint32_t cpu_count;
50  uint32_t mtx_count;
51  rtems_id worker_ids[CPU_COUNT][WORKER_PER_CPU];
52  rtems_id scheduler_ids[CPU_COUNT];
53  rtems_id mtx_ids[MTX_COUNT];
54  rtems_id counting_sem_id;
55  volatile bool stop_worker[WORKER_COUNT];
56  test_stats stats[WORKER_COUNT];
57} test_context;
58
59static test_context test_instance;
60
61static uint32_t simple_random(uint32_t v)
62{
63  v *= 1664525;
64  v += 1013904223;
65
66  return v;
67}
68
69typedef struct {
70  uint32_t guide;
71  size_t mtx_stack[MTX_COUNT];
72  bool mtx_owned[MTX_COUNT];
73  size_t nest_level;
74  test_stats stats;
75} worker_context;
76
77static void release(test_context *ctx, worker_context *wc, size_t nest_level)
78{
79  rtems_status_code sc;
80  size_t i;
81
82  --wc->nest_level;
83  ++wc->stats.release_counter;
84
85  i = wc->mtx_stack[wc->nest_level];
86  wc->mtx_owned[i] = false;
87
88  sc = rtems_semaphore_release(ctx->mtx_ids[i]);
89  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
90}
91
92static void release_all(test_context *ctx, worker_context *wc)
93{
94  while (wc->nest_level > 0) {
95    release(ctx, wc, wc->nest_level);
96  }
97}
98
99static void worker(rtems_task_argument index)
100{
101  test_context *ctx;
102  worker_context wc;
103  rtems_status_code sc;
104
105  ctx = &test_instance;
106  memset(&wc, 0, sizeof(wc));
107  wc.guide = index;
108
109  while (!ctx->stop_worker[index]) {
110    uint32_t action;
111    uint32_t i;
112
113    if (wc.nest_level < ctx->mtx_count) {
114      action = (wc.guide >> 23) % 2;
115    } else {
116      action = UINT32_MAX;
117    }
118
119    i = (wc.guide >> 13) % ctx->mtx_count;
120
121    switch (action) {
122      case 0:
123        if ( !wc.mtx_owned[i] ) {
124          sc = rtems_semaphore_obtain(ctx->mtx_ids[i], RTEMS_WAIT, 1);
125
126          if (sc == RTEMS_SUCCESSFUL) {
127            wc.mtx_owned[i] = true;
128            wc.mtx_stack[wc.nest_level] = i;
129            ++wc.nest_level;
130            ++wc.stats.obtain_counter;
131
132            if (wc.nest_level > wc.stats.max_nest_level) {
133              wc.stats.max_nest_level = wc.nest_level;
134            }
135          } else if (sc == RTEMS_INCORRECT_STATE) {
136            ++wc.stats.deadlock_counter;
137            release_all(ctx, &wc);
138          } else if (sc == RTEMS_TIMEOUT) {
139            ++wc.stats.timeout_counter;
140            release_all(ctx, &wc);
141          } else {
142            rtems_test_assert(0);
143          }
144        }
145
146        break;
147      default:
148        if (wc.nest_level > 0) {
149          release(ctx, &wc, wc.nest_level);
150        }
151
152        break;
153    }
154
155    wc.guide = simple_random(wc.guide);
156  }
157
158  release_all(ctx, &wc);
159
160  ctx->stats[index] = wc.stats;
161
162  sc = rtems_semaphore_release(ctx->counting_sem_id);
163  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
164
165  rtems_task_suspend(RTEMS_SELF);
166  rtems_test_assert(0);
167}
168
169static void set_up(test_context *ctx)
170{
171  rtems_status_code sc;
172  uint32_t i;
173
174  ctx->cpu_count = rtems_get_processor_count();
175  ctx->mtx_count = MTX_PER_CPU * ctx->cpu_count;
176
177  sc = rtems_semaphore_create(
178    rtems_build_name('S', 'Y', 'N', 'C'),
179    0,
180    RTEMS_COUNTING_SEMAPHORE,
181    0,
182    &ctx->counting_sem_id
183  );
184  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
185
186  for (i = 0; i < ctx->mtx_count; ++i) {
187    sc = rtems_semaphore_create(
188      rtems_build_name('M', 'U', 'T', 'X'),
189      1,
190      RTEMS_BINARY_SEMAPHORE
191        | RTEMS_PRIORITY
192        | RTEMS_INHERIT_PRIORITY,
193      0,
194      &ctx->mtx_ids[i]
195    );
196    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
197  }
198
199  for (i = 0; i < ctx->cpu_count; ++i) {
200    size_t j;
201
202    sc = rtems_scheduler_ident(i, &ctx->scheduler_ids[i]);
203    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
204
205    for (j = 0; j < WORKER_PER_CPU; ++j) {
206      sc = rtems_task_create(
207        rtems_build_name('W', 'O', 'R', 'K'),
208        255,
209        RTEMS_MINIMUM_STACK_SIZE,
210        RTEMS_DEFAULT_MODES,
211        RTEMS_DEFAULT_ATTRIBUTES,
212        &ctx->worker_ids[i][j]
213      );
214      rtems_test_assert(sc == RTEMS_SUCCESSFUL);
215
216      sc = rtems_task_set_scheduler(
217        ctx->worker_ids[i][j],
218        ctx->scheduler_ids[i],
219        2 + j
220      );
221      rtems_test_assert(sc == RTEMS_SUCCESSFUL);
222
223      sc = rtems_task_start(
224        ctx->worker_ids[i][j],
225        worker,
226        i * WORKER_PER_CPU + j
227      );
228      rtems_test_assert(sc == RTEMS_SUCCESSFUL);
229    }
230  }
231}
232
233static void run(test_context *ctx)
234{
235  rtems_status_code sc;
236  uint32_t i;
237
238  sc = rtems_task_wake_after(10 * rtems_clock_get_ticks_per_second());
239  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
240
241  for (i = 0; i < WORKER_PER_CPU * ctx->cpu_count; ++i) {
242    ctx->stop_worker[i] = true;
243  }
244
245  for (i = 0; i < WORKER_PER_CPU * ctx->cpu_count; ++i) {
246    sc = rtems_semaphore_obtain(
247      ctx->counting_sem_id,
248      RTEMS_WAIT,
249      RTEMS_NO_TIMEOUT
250    );
251    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
252  }
253}
254
255static void tear_down(test_context *ctx)
256{
257  rtems_status_code sc;
258  uint32_t i;
259
260  for (i = 0; i < ctx->cpu_count; ++i) {
261    size_t j;
262
263    for (j = 0; j < WORKER_PER_CPU; ++j) {
264      sc = rtems_task_delete(ctx->worker_ids[i][j]);
265      rtems_test_assert(sc == RTEMS_SUCCESSFUL);
266    }
267  }
268
269  for (i = 0; i < ctx->mtx_count; ++i) {
270    sc = rtems_semaphore_delete(ctx->mtx_ids[i]);
271    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
272  }
273
274  sc = rtems_semaphore_delete(ctx->counting_sem_id);
275  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
276
277  for (i = 0; i < WORKER_PER_CPU * ctx->cpu_count; ++i) {
278    const test_stats *stats;
279
280    stats = &ctx->stats[i];
281
282    printf("worker[%" PRIu32 "][%" PRIu32 "]\n"
283      "\tobtain counter   = %" PRIu32 "\n"
284      "\tdeadlock counter = %" PRIu32 "\n"
285      "\ttimeout counter  = %" PRIu32 "\n"
286      "\trelease counter  = %" PRIu32 "\n"
287      "\tmax nest level   = %" PRIu32 "\n",
288      i / WORKER_PER_CPU,
289      i % WORKER_PER_CPU,
290      stats->obtain_counter,
291      stats->deadlock_counter,
292      stats->timeout_counter,
293      stats->release_counter,
294      stats->max_nest_level
295    );
296  }
297}
298
299static void Init(rtems_task_argument arg)
300{
301  test_context *ctx;
302  rtems_resource_snapshot snapshot;
303
304  TEST_BEGIN();
305  rtems_resource_snapshot_take(&snapshot);
306  ctx = &test_instance;
307
308  set_up(ctx);
309  run(ctx);
310  tear_down(ctx);
311
312  rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
313  TEST_END();
314  rtems_test_exit(0);
315}
316
317#define CONFIGURE_MICROSECONDS_PER_TICK 1000
318
319#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
320#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
321
322#define CONFIGURE_MAXIMUM_TASKS (1 + WORKER_COUNT)
323#define CONFIGURE_MAXIMUM_SEMAPHORES (1 + MTX_COUNT)
324
325#define CONFIGURE_SMP_APPLICATION
326
327#define CONFIGURE_SMP_MAXIMUM_PROCESSORS CPU_COUNT
328
329#define CONFIGURE_SCHEDULER_SIMPLE_SMP
330
331#include <rtems/scheduler.h>
332
333RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(0);
334RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(1);
335RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(2);
336RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(3);
337RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(4);
338RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(5);
339RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(6);
340RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(7);
341RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(8);
342RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(9);
343RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(10);
344RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(11);
345RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(12);
346RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(13);
347RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(14);
348RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(15);
349RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(16);
350RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(17);
351RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(18);
352RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(19);
353RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(20);
354RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(21);
355RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(22);
356RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(23);
357RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(24);
358RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(25);
359RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(26);
360RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(27);
361RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(28);
362RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(29);
363RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(30);
364RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(31);
365
366#define CONFIGURE_SCHEDULER_CONTROLS \
367  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(0, 0), \
368  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(1, 1), \
369  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(2, 2), \
370  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(3, 3), \
371  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(4, 4), \
372  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(5, 5), \
373  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(6, 6), \
374  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(7, 7), \
375  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(8, 8), \
376  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(9, 9), \
377  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(10, 10), \
378  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(11, 11), \
379  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(12, 12), \
380  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(13, 13), \
381  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(14, 14), \
382  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(15, 15), \
383  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(16, 16), \
384  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(17, 17), \
385  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(18, 18), \
386  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(19, 19), \
387  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(20, 20), \
388  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(21, 21), \
389  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(22, 22), \
390  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(23, 23), \
391  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(24, 24), \
392  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(25, 25), \
393  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(26, 26), \
394  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(27, 27), \
395  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(28, 28), \
396  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(29, 29), \
397  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(30, 30), \
398  RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(31, 31)
399
400#define CONFIGURE_SMP_SCHEDULER_ASSIGNMENTS \
401  RTEMS_SCHEDULER_ASSIGN(0, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_MANDATORY), \
402  RTEMS_SCHEDULER_ASSIGN(1, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
403  RTEMS_SCHEDULER_ASSIGN(2, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
404  RTEMS_SCHEDULER_ASSIGN(3, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
405  RTEMS_SCHEDULER_ASSIGN(4, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
406  RTEMS_SCHEDULER_ASSIGN(5, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
407  RTEMS_SCHEDULER_ASSIGN(6, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
408  RTEMS_SCHEDULER_ASSIGN(7, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
409  RTEMS_SCHEDULER_ASSIGN(8, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
410  RTEMS_SCHEDULER_ASSIGN(9, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
411  RTEMS_SCHEDULER_ASSIGN(10, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
412  RTEMS_SCHEDULER_ASSIGN(11, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
413  RTEMS_SCHEDULER_ASSIGN(12, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
414  RTEMS_SCHEDULER_ASSIGN(13, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
415  RTEMS_SCHEDULER_ASSIGN(14, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
416  RTEMS_SCHEDULER_ASSIGN(15, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
417  RTEMS_SCHEDULER_ASSIGN(16, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
418  RTEMS_SCHEDULER_ASSIGN(17, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
419  RTEMS_SCHEDULER_ASSIGN(18, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
420  RTEMS_SCHEDULER_ASSIGN(19, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
421  RTEMS_SCHEDULER_ASSIGN(20, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
422  RTEMS_SCHEDULER_ASSIGN(21, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
423  RTEMS_SCHEDULER_ASSIGN(22, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
424  RTEMS_SCHEDULER_ASSIGN(23, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
425  RTEMS_SCHEDULER_ASSIGN(24, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
426  RTEMS_SCHEDULER_ASSIGN(25, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
427  RTEMS_SCHEDULER_ASSIGN(26, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
428  RTEMS_SCHEDULER_ASSIGN(27, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
429  RTEMS_SCHEDULER_ASSIGN(28, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
430  RTEMS_SCHEDULER_ASSIGN(29, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
431  RTEMS_SCHEDULER_ASSIGN(30, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL), \
432  RTEMS_SCHEDULER_ASSIGN(31, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL)
433
434#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
435
436#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
437
438#define CONFIGURE_INIT
439
440#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.