source: rtems/testsuites/sptests/spsyslock01/init.c @ a1b4af4b

5
Last change on this file since a1b4af4b was a1b4af4b, checked in by Sebastian Huber <sebastian.huber@…>, on 07/20/15 at 07:05:30

score: Add scheduler <sys/lock.h> support

  • Property mode set to 100644
File size: 14.2 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
21#include <sys/lock.h>
22#include <errno.h>
23#include <limits.h>
24#include <string.h>
25#include <time.h>
26
27const char rtems_test_name[] = "SPSYSLOCK 1";
28
29#define US_PER_TICK 10000
30
31#define EVENT_MTX_ACQUIRE RTEMS_EVENT_0
32
33#define EVENT_MTX_RELEASE RTEMS_EVENT_1
34
35#define EVENT_MTX_PRIO_INV RTEMS_EVENT_2
36
37#define EVENT_MTX_DEADLOCK RTEMS_EVENT_3
38
39#define EVENT_REC_MTX_ACQUIRE RTEMS_EVENT_4
40
41#define EVENT_REC_MTX_RELEASE RTEMS_EVENT_5
42
43#define EVENT_REC_MTX_PRIO_INV RTEMS_EVENT_6
44
45#define EVENT_SEM_WAIT RTEMS_EVENT_7
46
47#define EVENT_FUTEX_WAIT RTEMS_EVENT_8
48
49typedef struct {
50  rtems_id high[2];
51  rtems_id mid;
52  rtems_id low;
53  struct _Mutex_Control mtx;
54  struct _Mutex_recursive_Control rec_mtx;
55  struct _Semaphore_Control sem;
56  struct _Futex_Control futex;
57  int val;
58  int eno[2];
59  int generation[2];
60  int current_generation[2];
61} test_context;
62
63static test_context test_instance;
64
65static int generation(test_context *ctx, size_t idx)
66{
67  return ++ctx->current_generation[idx];
68}
69
70static void send_event(test_context *ctx, size_t idx, rtems_event_set events)
71{
72  rtems_status_code sc;
73
74  sc = rtems_event_send(ctx->high[idx], events);
75  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
76}
77
78static void get_abs_timeout(struct timespec *to)
79{
80  int rv;
81
82  rv = clock_gettime(CLOCK_REALTIME, to);
83  rtems_test_assert(rv == 0);
84
85  to->tv_nsec += 2 * US_PER_TICK * 1000;
86  if (to->tv_nsec >= 1000000000) {
87    ++to->tv_sec;
88    to->tv_nsec -= 1000000000;
89  }
90}
91
92static void test_initialization(test_context *ctx)
93{
94  struct _Mutex_Control mtx = _MUTEX_INITIALIZER;
95  struct _Mutex_recursive_Control rec_mtx = _MUTEX_RECURSIVE_INITIALIZER;
96  struct _Semaphore_Control sem = _SEMAPHORE_INITIALIZER(1);
97  struct _Futex_Control futex = _FUTEX_INITIALIZER;
98
99  _Mutex_Initialize(&ctx->mtx);
100  _Mutex_recursive_Initialize(&ctx->rec_mtx);
101  _Semaphore_Initialize(&ctx->sem, 1);
102  _Futex_Initialize(&ctx->futex);
103
104  rtems_test_assert(memcmp(&mtx, &ctx->mtx, sizeof(mtx)) == 0);
105  rtems_test_assert(memcmp(&rec_mtx, &ctx->rec_mtx, sizeof(rec_mtx)) == 0);
106  rtems_test_assert(memcmp(&sem, &ctx->sem, sizeof(sem)) == 0);
107  rtems_test_assert(memcmp(&futex, &ctx->futex, sizeof(futex)) == 0);
108
109  _Mutex_Destroy(&mtx);
110  _Mutex_recursive_Destroy(&rec_mtx);
111  _Semaphore_Destroy(&sem);
112  _Futex_Destroy(&futex);
113}
114
115static void test_recursive_acquire_normal(test_context *ctx)
116{
117  struct _Mutex_Control *mtx = &ctx->mtx;
118  size_t idx = 0;
119  int success;
120
121  success = _Mutex_Try_acquire(mtx);
122  rtems_test_assert(success == 1);
123
124  success = _Mutex_Try_acquire(mtx);
125  rtems_test_assert(success == 0);
126
127  _Mutex_Release(mtx);
128
129  success = _Mutex_Try_acquire(mtx);
130  rtems_test_assert(success == 1);
131
132  _Mutex_Release(mtx);
133
134  _Mutex_Acquire(mtx);
135
136  success = _Mutex_Try_acquire(mtx);
137  rtems_test_assert(success == 0);
138
139  _Mutex_Release(mtx);
140
141  send_event(ctx, idx, EVENT_MTX_ACQUIRE);
142
143  success = _Mutex_Try_acquire(mtx);
144  rtems_test_assert(success == 0);
145
146  send_event(ctx, idx, EVENT_MTX_RELEASE);
147}
148
149static void test_recursive_acquire_recursive(test_context *ctx)
150{
151  struct _Mutex_recursive_Control *mtx = &ctx->rec_mtx;
152  size_t idx = 0;
153  int success;
154
155  success = _Mutex_recursive_Try_acquire(mtx);
156  rtems_test_assert(success == 1);
157
158  _Mutex_recursive_Acquire(mtx);
159
160  success = _Mutex_recursive_Try_acquire(mtx);
161  rtems_test_assert(success == 1);
162
163  _Mutex_recursive_Release(mtx);
164  _Mutex_recursive_Release(mtx);
165  _Mutex_recursive_Release(mtx);
166
167  send_event(ctx, idx, EVENT_REC_MTX_ACQUIRE);
168
169  success = _Mutex_recursive_Try_acquire(mtx);
170  rtems_test_assert(success == 0);
171
172  send_event(ctx, idx, EVENT_REC_MTX_RELEASE);
173}
174
175static void test_prio_acquire_order(test_context *ctx)
176{
177  struct _Mutex_Control *mtx = &ctx->mtx;
178  size_t a = 0;
179  size_t b = 1;
180  int gen_a;
181  int gen_b;
182
183  _Mutex_Acquire(mtx);
184
185  gen_a = ctx->generation[a];
186  gen_b = ctx->generation[b];
187
188  send_event(ctx, b, EVENT_MTX_ACQUIRE);
189  send_event(ctx, a, EVENT_MTX_ACQUIRE);
190
191  rtems_test_assert(ctx->generation[a] == gen_a);
192  rtems_test_assert(ctx->generation[b] == gen_b);
193
194  _Mutex_Release(mtx);
195
196  rtems_test_assert(ctx->generation[a] == gen_a + 1);
197  rtems_test_assert(ctx->generation[b] == gen_b);
198
199  send_event(ctx, a, EVENT_MTX_RELEASE);
200
201  rtems_test_assert(ctx->generation[a] == gen_a + 1);
202  rtems_test_assert(ctx->generation[b] == gen_b + 1);
203
204  send_event(ctx, b, EVENT_MTX_RELEASE);
205}
206
207static void test_prio_inv_normal(test_context *ctx)
208{
209  struct _Mutex_Control *mtx = &ctx->mtx;
210  size_t idx = 0;
211  int gen;
212
213  _Mutex_Acquire(mtx);
214  gen = ctx->generation[idx];
215  send_event(ctx, idx, EVENT_MTX_PRIO_INV);
216  rtems_test_assert(ctx->generation[idx] == gen);
217  _Mutex_Release(mtx);
218  rtems_test_assert(ctx->generation[idx] == gen + 1);
219}
220
221static void test_prio_inv_recursive(test_context *ctx)
222{
223  struct _Mutex_recursive_Control *mtx = &ctx->rec_mtx;
224  size_t idx = 0;
225  int gen;
226
227  _Mutex_recursive_Acquire(mtx);
228  gen = ctx->generation[idx];
229  send_event(ctx, idx, EVENT_REC_MTX_PRIO_INV);
230  rtems_test_assert(ctx->generation[idx] == gen);
231  _Mutex_recursive_Release(mtx);
232  rtems_test_assert(ctx->generation[idx] == gen + 1);
233}
234
235static void test_mtx_timeout_normal(test_context *ctx)
236{
237  struct _Mutex_Control *mtx = &ctx->mtx;
238  size_t idx = 0;
239  struct timespec to;
240  int eno;
241
242  eno = _Mutex_Acquire_timed(mtx, NULL);
243  rtems_test_assert(eno == 0);
244  _Mutex_Release(mtx);
245
246  send_event(ctx, idx, EVENT_MTX_ACQUIRE);
247
248  memset(&to, 0x00, sizeof(to));
249  eno = _Mutex_Acquire_timed(mtx, &to);
250  rtems_test_assert(eno == ETIMEDOUT);
251  memset(&to, 0xff, sizeof(to));
252  eno = _Mutex_Acquire_timed(mtx, &to);
253  rtems_test_assert(eno == EINVAL);
254  get_abs_timeout(&to);
255  eno = _Mutex_Acquire_timed(mtx, &to);
256  rtems_test_assert(eno == ETIMEDOUT);
257
258  send_event(ctx, idx, EVENT_MTX_RELEASE);
259}
260
261static void test_mtx_timeout_recursive(test_context *ctx)
262{
263  struct _Mutex_recursive_Control *mtx = &ctx->rec_mtx;
264  size_t idx = 0;
265  struct timespec to;
266  int eno;
267
268  eno = _Mutex_recursive_Acquire_timed(mtx, NULL);
269  rtems_test_assert(eno == 0);
270  eno = _Mutex_recursive_Acquire_timed(mtx, NULL);
271  rtems_test_assert(eno == 0);
272  _Mutex_recursive_Release(mtx);
273  _Mutex_recursive_Release(mtx);
274
275  send_event(ctx, idx, EVENT_REC_MTX_ACQUIRE);
276
277  memset(&to, 0x00, sizeof(to));
278  eno = _Mutex_recursive_Acquire_timed(mtx, &to);
279  rtems_test_assert(eno == ETIMEDOUT);
280  memset(&to, 0xff, sizeof(to));
281  eno = _Mutex_recursive_Acquire_timed(mtx, &to);
282  rtems_test_assert(eno == EINVAL);
283  get_abs_timeout(&to);
284  eno = _Mutex_recursive_Acquire_timed(mtx, &to);
285  rtems_test_assert(eno == ETIMEDOUT);
286
287  send_event(ctx, idx, EVENT_REC_MTX_RELEASE);
288}
289
290static void test_sem(test_context *ctx)
291{
292  struct _Semaphore_Control *sem = &ctx->sem;
293  size_t idx = 0;
294  int gen;
295
296  _Semaphore_Wait(sem);
297  gen = ctx->generation[idx];
298  send_event(ctx, idx, EVENT_SEM_WAIT);
299  rtems_test_assert(ctx->generation[idx] == gen);
300  _Semaphore_Post(sem);
301  rtems_test_assert(ctx->generation[idx] == gen + 1);
302  _Semaphore_Post(sem);
303}
304
305static void test_sem_prio_wait_order(test_context *ctx)
306{
307  struct _Semaphore_Control *sem = &ctx->sem;
308  size_t a = 0;
309  size_t b = 1;
310  int gen_a;
311  int gen_b;
312
313  _Semaphore_Wait(sem);
314
315  gen_a = ctx->generation[a];
316  gen_b = ctx->generation[b];
317
318  send_event(ctx, b, EVENT_SEM_WAIT);
319  send_event(ctx, a, EVENT_SEM_WAIT);
320
321  rtems_test_assert(ctx->generation[a] == gen_a);
322  rtems_test_assert(ctx->generation[b] == gen_b);
323
324  _Semaphore_Post(sem);
325
326  rtems_test_assert(ctx->generation[a] == gen_a + 1);
327  rtems_test_assert(ctx->generation[b] == gen_b);
328
329  _Semaphore_Post(sem);
330
331  rtems_test_assert(ctx->generation[a] == gen_a + 1);
332  rtems_test_assert(ctx->generation[b] == gen_b + 1);
333}
334
335static void test_futex(test_context *ctx)
336{
337  struct _Futex_Control *futex = &ctx->futex;
338  size_t a = 0;
339  size_t b = 1;
340  int eno;
341  int woken;
342
343  eno = _Futex_Wait(futex, &ctx->val, 1);
344  rtems_test_assert(eno == EWOULDBLOCK);
345
346  woken = _Futex_Wake(futex, 0);
347  rtems_test_assert(woken == 0);
348
349  woken = _Futex_Wake(futex, 1);
350  rtems_test_assert(woken == 0);
351
352  ctx->val = 1;
353
354  ctx->eno[a] = -1;
355  send_event(ctx, a, EVENT_FUTEX_WAIT);
356  rtems_test_assert(ctx->eno[a] == -1);
357
358  woken = _Futex_Wake(futex, INT_MAX);
359  rtems_test_assert(woken == 1);
360  rtems_test_assert(ctx->eno[a] == 0);
361
362  ctx->eno[a] = -1;
363  ctx->eno[b] = -1;
364  send_event(ctx, a, EVENT_FUTEX_WAIT);
365  send_event(ctx, b, EVENT_FUTEX_WAIT);
366  rtems_test_assert(ctx->eno[a] == -1);
367  rtems_test_assert(ctx->eno[b] == -1);
368
369  woken = _Futex_Wake(futex, 1);
370  rtems_test_assert(woken == 1);
371  rtems_test_assert(ctx->eno[a] == 0);
372  rtems_test_assert(ctx->eno[b] == -1);
373
374  woken = _Futex_Wake(futex, 1);
375  rtems_test_assert(woken == 1);
376  rtems_test_assert(ctx->eno[a] == 0);
377  rtems_test_assert(ctx->eno[b] == 0);
378
379  ctx->eno[a] = -1;
380  ctx->eno[b] = -1;
381  send_event(ctx, a, EVENT_FUTEX_WAIT);
382  send_event(ctx, b, EVENT_FUTEX_WAIT);
383  rtems_test_assert(ctx->eno[a] == -1);
384  rtems_test_assert(ctx->eno[b] == -1);
385
386  woken = _Futex_Wake(futex, 2);
387  rtems_test_assert(woken == 2);
388  rtems_test_assert(ctx->eno[a] == 0);
389  rtems_test_assert(ctx->eno[b] == 0);
390}
391
392static void test_sched(void)
393{
394  rtems_test_assert(_Sched_Index() == 0);
395  rtems_test_assert(_Sched_Name_to_index("", 0) == -1);
396  rtems_test_assert(_Sched_Name_to_index("b", 1) == -1);
397  rtems_test_assert(_Sched_Name_to_index("bl", 2) == -1);
398  rtems_test_assert(_Sched_Name_to_index("blu", 3) == -1);
399  rtems_test_assert(_Sched_Name_to_index("blue", 4) == 0);
400  rtems_test_assert(_Sched_Name_to_index("blueX", 5) == 0);
401  rtems_test_assert(_Sched_Processor_count(-1) == 0);
402  rtems_test_assert(_Sched_Processor_count(0) == 1);
403  rtems_test_assert(_Sched_Processor_count(1) == 0);
404}
405
406static void mid_task(rtems_task_argument arg)
407{
408  rtems_test_assert(0);
409}
410
411static void high_task(rtems_task_argument idx)
412{
413  test_context *ctx = &test_instance;
414  rtems_status_code sc;
415
416  if (idx == 0) {
417    sc = rtems_task_start(ctx->mid, mid_task, 0);
418    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
419
420    sc = rtems_task_suspend(ctx->mid);
421    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
422  }
423
424  while (true) {
425    rtems_event_set events;
426
427    sc = rtems_event_receive(
428      RTEMS_ALL_EVENTS,
429      RTEMS_EVENT_ANY | RTEMS_WAIT,
430      RTEMS_NO_TIMEOUT,
431      &events
432    );
433    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
434
435    if ((events & EVENT_MTX_ACQUIRE) != 0) {
436      _Mutex_Acquire(&ctx->mtx);
437      ctx->generation[idx] = generation(ctx, idx);
438    }
439
440    if ((events & EVENT_MTX_RELEASE) != 0) {
441      _Mutex_Release(&ctx->mtx);
442    }
443
444    if ((events & EVENT_MTX_PRIO_INV) != 0) {
445      sc = rtems_task_resume(ctx->mid);
446      rtems_test_assert(sc == RTEMS_SUCCESSFUL);
447
448      _Mutex_Acquire(&ctx->mtx);
449      ctx->generation[idx] = generation(ctx, idx);
450      _Mutex_Release(&ctx->mtx);
451
452      sc = rtems_task_suspend(ctx->mid);
453      rtems_test_assert(sc == RTEMS_SUCCESSFUL);
454    }
455
456    if ((events & EVENT_MTX_DEADLOCK) != 0) {
457      struct _Mutex_Control dead = _MUTEX_INITIALIZER;
458
459      _Mutex_Acquire(&dead);
460      _Mutex_Acquire(&dead);
461    }
462
463    if ((events & EVENT_REC_MTX_ACQUIRE) != 0) {
464      _Mutex_recursive_Acquire(&ctx->rec_mtx);
465    }
466
467    if ((events & EVENT_REC_MTX_RELEASE) != 0) {
468      _Mutex_recursive_Release(&ctx->rec_mtx);
469    }
470
471    if ((events & EVENT_REC_MTX_PRIO_INV) != 0) {
472      sc = rtems_task_resume(ctx->mid);
473      rtems_test_assert(sc == RTEMS_SUCCESSFUL);
474
475      _Mutex_recursive_Acquire(&ctx->rec_mtx);
476      ctx->generation[idx] = generation(ctx, idx);
477      _Mutex_recursive_Release(&ctx->rec_mtx);
478
479      sc = rtems_task_suspend(ctx->mid);
480      rtems_test_assert(sc == RTEMS_SUCCESSFUL);
481    }
482
483    if ((events & EVENT_SEM_WAIT) != 0) {
484      _Semaphore_Wait(&ctx->sem);
485      ctx->generation[idx] = generation(ctx, idx);
486    }
487
488    if ((events & EVENT_FUTEX_WAIT) != 0) {
489      ctx->eno[idx] = _Futex_Wait(&ctx->futex, &ctx->val, 1);
490    }
491  }
492}
493
494static void test(void)
495{
496  test_context *ctx = &test_instance;
497  rtems_status_code sc;
498
499  test_initialization(ctx);
500
501  ctx->low = rtems_task_self();
502
503  sc = rtems_task_create(
504    rtems_build_name('M', 'I', 'D', ' '),
505    3,
506    RTEMS_MINIMUM_STACK_SIZE,
507    RTEMS_DEFAULT_MODES,
508    RTEMS_DEFAULT_ATTRIBUTES,
509    &ctx->mid
510  );
511  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
512
513  sc = rtems_task_create(
514    rtems_build_name('H', 'I', 'G', '0'),
515    1,
516    RTEMS_MINIMUM_STACK_SIZE,
517    RTEMS_DEFAULT_MODES,
518    RTEMS_DEFAULT_ATTRIBUTES,
519    &ctx->high[0]
520  );
521  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
522
523  sc = rtems_task_start(ctx->high[0], high_task, 0);
524  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
525
526  sc = rtems_task_create(
527    rtems_build_name('H', 'I', 'G', '1'),
528    2,
529    RTEMS_MINIMUM_STACK_SIZE,
530    RTEMS_DEFAULT_MODES,
531    RTEMS_DEFAULT_ATTRIBUTES,
532    &ctx->high[1]
533  );
534  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
535
536  sc = rtems_task_start(ctx->high[1], high_task, 1);
537  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
538
539  test_recursive_acquire_normal(ctx);
540  test_recursive_acquire_recursive(ctx);
541  test_prio_acquire_order(ctx);
542  test_prio_inv_normal(ctx);
543  test_prio_inv_recursive(ctx);
544  test_mtx_timeout_normal(ctx);
545  test_mtx_timeout_recursive(ctx);
546  test_sem(ctx);
547  test_sem_prio_wait_order(ctx);
548  test_futex(ctx);
549  test_sched();
550
551  send_event(ctx, 0, EVENT_MTX_DEADLOCK);
552
553  _Mutex_Destroy(&ctx->mtx);
554  _Mutex_recursive_Destroy(&ctx->rec_mtx);
555  _Semaphore_Destroy(&ctx->sem);
556  _Futex_Destroy(&ctx->futex);
557}
558
559static void Init(rtems_task_argument arg)
560{
561  TEST_BEGIN();
562
563  test();
564
565  TEST_END();
566  rtems_test_exit(0);
567}
568
569#define CONFIGURE_MICROSECONDS_PER_TICK US_PER_TICK
570
571#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
572#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
573
574#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
575
576#define CONFIGURE_MAXIMUM_TASKS 4
577
578#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
579
580#define CONFIGURE_INIT_TASK_PRIORITY 4
581#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES
582
583#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
584
585#define CONFIGURE_SCHEDULER_NAME rtems_build_name('b', 'l', 'u', 'e')
586
587#define CONFIGURE_INIT
588
589#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.