source: rtems/testsuites/sptests/spstdthreads01/init.c @ 99de42c

5
Last change on this file since 99de42c was bb3484c9, checked in by Sebastian Huber <sebastian.huber@…>, on 10/29/18 at 07:59:45

posix: Enable more sptests test cases by default

Update #2514.

  • Property mode set to 100644
File size: 9.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
21#include <threads.h>
22
23#include <rtems/malloc.h>
24
25const char rtems_test_name[] = "SPSTDTHREADS 1";
26
27#define US_PER_TICK 10000
28
29#define EVENT_MTX_LOCK RTEMS_EVENT_0
30
31#define EVENT_MTX_UNLOCK RTEMS_EVENT_1
32
33#define EVENT_CND_WAIT RTEMS_EVENT_2
34
35#define EVENT_CND_TIMEDWAIT RTEMS_EVENT_3
36
37#define EVENT_TSS RTEMS_EVENT_4
38
39typedef struct {
40  rtems_id high;
41  rtems_id low;
42  once_flag once_flag;
43  mtx_t mtx;
44  cnd_t cnd;
45  tss_t tss;
46  thrd_t thrd;
47  int generation;
48} test_context;
49
50static test_context test_instance = {
51  .once_flag = ONCE_FLAG_INIT
52};
53
54static void next_generation(test_context *ctx)
55{
56  ++ctx->generation;
57}
58
59static void send_event(test_context *ctx, rtems_event_set events)
60{
61  rtems_status_code sc;
62
63  sc = rtems_event_send(ctx->high, events);
64  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
65}
66
67static void get_abs_timeout(struct timespec *to)
68{
69  int rv;
70
71  rv = clock_gettime(CLOCK_REALTIME, to);
72  rtems_test_assert(rv == 0);
73
74  to->tv_nsec += 2 * US_PER_TICK * 1000;
75  if (to->tv_nsec >= 1000000000) {
76    ++to->tv_sec;
77    to->tv_nsec -= 1000000000;
78  }
79}
80
81static void test_init(test_context *ctx)
82{
83  int status;
84
85  status = mtx_init(&ctx->mtx, mtx_plain);
86  rtems_test_assert(status == thrd_success);
87
88  status = cnd_init(&ctx->cnd);
89  rtems_test_assert(status == thrd_success);
90}
91
92static void test_destroy(test_context *ctx)
93{
94  mtx_destroy(&ctx->mtx);
95  cnd_destroy(&ctx->cnd);
96}
97
98static void once_func(void)
99{
100  test_context *ctx = &test_instance;
101
102  next_generation(ctx);
103}
104
105static void test_once(test_context *ctx)
106{
107  int gen = ctx->generation;
108
109  call_once(&ctx->once_flag, once_func);
110  rtems_test_assert(ctx->generation == gen + 1);
111
112  call_once(&ctx->once_flag, once_func);
113  rtems_test_assert(ctx->generation == gen + 1);
114}
115
116static void test_mtx(test_context *ctx)
117{
118  mtx_t *mtx = &ctx->mtx;
119  int gen = ctx->generation;
120  struct timespec to;
121  int status;
122
123  status = mtx_trylock(mtx);
124  rtems_test_assert(status == thrd_success);
125
126  status = mtx_lock(mtx);
127  rtems_test_assert(status == thrd_success);
128
129  get_abs_timeout(&to);
130  status = mtx_timedlock(mtx, &to);
131  rtems_test_assert(status == thrd_success);
132
133  status = mtx_unlock(mtx);
134  rtems_test_assert(status == thrd_success);
135
136  status = mtx_unlock(mtx);
137  rtems_test_assert(status == thrd_success);
138
139  status = mtx_unlock(mtx);
140  rtems_test_assert(status == thrd_success);
141
142  send_event(ctx, EVENT_MTX_LOCK);
143  rtems_test_assert(ctx->generation == gen + 1);
144
145  status = mtx_trylock(mtx);
146  rtems_test_assert(status == thrd_busy);
147
148  memset(&to, 0xff, sizeof(to));
149  status = mtx_timedlock(mtx, &to);
150  rtems_test_assert(status == thrd_error);
151
152  get_abs_timeout(&to);
153  status = mtx_timedlock(mtx, &to);
154  rtems_test_assert(status == thrd_timedout);
155
156  send_event(ctx, EVENT_MTX_UNLOCK);
157  rtems_test_assert(ctx->generation == gen + 2);
158}
159
160static void test_cnd(test_context *ctx)
161{
162  cnd_t *cnd = &ctx->cnd;
163  mtx_t *mtx = &ctx->mtx;
164  int gen = ctx->generation;
165  struct timespec to;
166  int status;
167
168  send_event(ctx, EVENT_CND_WAIT);
169  rtems_test_assert(ctx->generation == gen + 1);
170
171  status = mtx_lock(mtx);
172  rtems_test_assert(status == thrd_success);
173
174  status = cnd_signal(cnd);
175  rtems_test_assert(status == thrd_success);
176
177  status = mtx_unlock(mtx);
178  rtems_test_assert(status == thrd_success);
179  rtems_test_assert(ctx->generation == gen + 2);
180
181  send_event(ctx, EVENT_CND_WAIT);
182  rtems_test_assert(ctx->generation == gen + 3);
183
184  status = mtx_lock(mtx);
185  rtems_test_assert(status == thrd_success);
186
187  status = cnd_broadcast(cnd);
188  rtems_test_assert(status == thrd_success);
189
190  status = mtx_unlock(mtx);
191  rtems_test_assert(status == thrd_success);
192  rtems_test_assert(ctx->generation == gen + 4);
193
194  status = mtx_lock(mtx);
195  rtems_test_assert(status == thrd_success);
196
197  memset(&to, 0xff, sizeof(to));
198  status = cnd_timedwait(cnd, mtx, &to);
199  rtems_test_assert(status == thrd_error);
200
201  get_abs_timeout(&to);
202  status = cnd_timedwait(cnd, mtx, &to);
203  rtems_test_assert(status == thrd_timedout);
204
205  status = mtx_unlock(mtx);
206  rtems_test_assert(status == thrd_success);
207
208  send_event(ctx, EVENT_CND_TIMEDWAIT);
209  rtems_test_assert(ctx->generation == gen + 5);
210
211  status = mtx_lock(mtx);
212  rtems_test_assert(status == thrd_success);
213
214  status = cnd_signal(cnd);
215  rtems_test_assert(status == thrd_success);
216
217  status = mtx_unlock(mtx);
218  rtems_test_assert(status == thrd_success);
219  rtems_test_assert(ctx->generation == gen + 6);
220}
221
222static int tss_val = TSS_DTOR_ITERATIONS;
223
224static void tss_dtor(void *val)
225{
226  test_context *ctx = &test_instance;
227
228  rtems_test_assert(val == &tss_val);
229  next_generation(ctx);
230}
231
232static void test_tss(test_context *ctx)
233{
234  tss_dtor_t dtor = tss_dtor;
235  int gen = ctx->generation;
236  int status;
237
238  status = tss_create(&ctx->tss, dtor);
239  rtems_test_assert(status == thrd_success);
240
241  send_event(ctx, EVENT_TSS);
242  rtems_test_assert(ctx->generation == gen + 1);
243
244  tss_delete(ctx->tss);
245}
246
247static int thrd(void *arg)
248{
249  thrd_exit(123);
250}
251
252static void test_thrd(test_context *ctx)
253{
254  thrd_start_t thrd_start = thrd;
255  int status;
256  int exit_status;
257  struct timespec duration;
258  struct timespec remaining;
259  void *greedy;
260
261  rtems_test_assert(thrd_equal(rtems_task_self(), thrd_current()));
262
263  thrd_yield();
264
265  memset(&duration, 0, sizeof(duration));
266  duration.tv_nsec = 1;
267  thrd_sleep(&duration, &remaining);
268  rtems_test_assert(remaining.tv_sec == 0);
269  rtems_test_assert(remaining.tv_nsec == 0);
270
271  greedy = rtems_heap_greedy_allocate(NULL, 0);
272  status = thrd_create(&ctx->thrd, thrd_start, ctx);
273  rtems_test_assert(status == thrd_nomem);
274  rtems_heap_greedy_free(greedy);
275
276  status = thrd_create(&ctx->thrd, thrd_start, ctx);
277  rtems_test_assert(status == thrd_success);
278
279  status = thrd_create(&ctx->thrd, thrd_start, ctx);
280  rtems_test_assert(status == thrd_error);
281
282  exit_status = 0;
283  status = thrd_join(ctx->thrd, &exit_status);
284  rtems_test_assert(status == thrd_success);
285  rtems_test_assert(exit_status == 123);
286
287  status = thrd_detach(thrd_current());
288  rtems_test_assert(status == thrd_success);
289
290  status = thrd_detach(11235);
291  rtems_test_assert(status == thrd_error);
292}
293
294static void high_task(rtems_task_argument idx)
295{
296  test_context *ctx = &test_instance;
297
298  while (true) {
299    rtems_event_set events;
300    rtems_status_code sc;
301    int status;
302
303    sc = rtems_event_receive(
304      RTEMS_ALL_EVENTS,
305      RTEMS_EVENT_ANY | RTEMS_WAIT,
306      RTEMS_NO_TIMEOUT,
307      &events
308    );
309    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
310
311    if ((events & EVENT_MTX_LOCK) != 0) {
312      status = mtx_lock(&ctx->mtx);
313      rtems_test_assert(status == thrd_success);
314      next_generation(ctx);
315    }
316
317    if ((events & EVENT_MTX_UNLOCK) != 0) {
318      status = mtx_unlock(&ctx->mtx);
319      rtems_test_assert(status == thrd_success);
320      next_generation(ctx);
321    }
322
323    if ((events & EVENT_CND_WAIT) != 0) {
324      status = mtx_lock(&ctx->mtx);
325      rtems_test_assert(status == thrd_success);
326      next_generation(ctx);
327
328      status = cnd_wait(&ctx->cnd, &ctx->mtx);
329      rtems_test_assert(status == thrd_success);
330      next_generation(ctx);
331
332      status = mtx_unlock(&ctx->mtx);
333      rtems_test_assert(status == thrd_success);
334    }
335
336    if ((events & EVENT_CND_TIMEDWAIT) != 0) {
337      struct timespec to;
338
339      status = mtx_lock(&ctx->mtx);
340      rtems_test_assert(status == thrd_success);
341      next_generation(ctx);
342
343      get_abs_timeout(&to);
344      status = cnd_timedwait(&ctx->cnd, &ctx->mtx, &to);
345      rtems_test_assert(status == thrd_success);
346      next_generation(ctx);
347
348      status = mtx_unlock(&ctx->mtx);
349      rtems_test_assert(status == thrd_success);
350    }
351
352    if ((events & EVENT_TSS) != 0) {
353      void *val;
354
355      status = tss_set(ctx->tss, &tss_val);
356      rtems_test_assert(status == thrd_success);
357
358      val = tss_get(ctx->tss);
359      rtems_test_assert(val == &tss_val);
360
361      rtems_task_exit();
362      rtems_test_assert(0);
363    }
364  }
365}
366
367static void test(void)
368{
369  test_context *ctx = &test_instance;
370  rtems_status_code sc;
371
372  test_init(ctx);
373
374  ctx->low = rtems_task_self();
375
376  sc = rtems_task_create(
377    rtems_build_name('H', 'I', 'G', 'H'),
378    1,
379    RTEMS_MINIMUM_STACK_SIZE,
380    RTEMS_DEFAULT_MODES,
381    RTEMS_DEFAULT_ATTRIBUTES,
382    &ctx->high
383  );
384  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
385
386  sc = rtems_task_start(ctx->high, high_task, 0);
387  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
388
389  test_once(ctx);
390  test_mtx(ctx);
391  test_cnd(ctx);
392  test_tss(ctx);
393  test_thrd(ctx);
394  test_destroy(ctx);
395}
396
397static void Init(rtems_task_argument arg)
398{
399  TEST_BEGIN();
400
401  test();
402
403  TEST_END();
404  rtems_test_exit(0);
405}
406
407#define CONFIGURE_MICROSECONDS_PER_TICK US_PER_TICK
408
409#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
410#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
411
412#define CONFIGURE_MAXIMUM_TASKS 4
413
414#define CONFIGURE_MAXIMUM_POSIX_KEYS 1
415#define CONFIGURE_MAXIMUM_POSIX_KEY_VALUE_PAIRS 1
416#define CONFIGURE_MAXIMUM_POSIX_THREADS 1
417
418#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
419
420#define CONFIGURE_INIT_TASK_PRIORITY 4
421#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES
422
423#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
424
425#define CONFIGURE_SCHEDULER_NAME rtems_build_name('b', 'l', 'u', 'e')
426
427#define CONFIGURE_INIT
428
429#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.