source: rtems/testsuites/sptests/spstdthreads01/init.c @ 51b3cbca

5
Last change on this file since 51b3cbca was 51b3cbca, checked in by Sebastian Huber <sebastian.huber@…>, on 10/04/18 at 13:23:25

tests: Use rtems_task_exit()

Update #3533.

  • Property mode set to 100644
File size: 9.6 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
247#if defined(RTEMS_POSIX_API)
248static int thrd(void *arg)
249{
250  thrd_exit(123);
251}
252#endif
253
254static void test_thrd(test_context *ctx)
255{
256#if defined(RTEMS_POSIX_API)
257  thrd_start_t thrd_start = thrd;
258  int status;
259  int exit_status;
260  struct timespec duration;
261  struct timespec remaining;
262  void *greedy;
263
264  rtems_test_assert(thrd_equal(rtems_task_self(), thrd_current()));
265
266  thrd_yield();
267
268  memset(&duration, 0, sizeof(duration));
269  duration.tv_nsec = 1;
270  thrd_sleep(&duration, &remaining);
271  rtems_test_assert(remaining.tv_sec == 0);
272  rtems_test_assert(remaining.tv_nsec == 0);
273
274  greedy = rtems_heap_greedy_allocate(NULL, 0);
275  status = thrd_create(&ctx->thrd, thrd_start, ctx);
276  rtems_test_assert(status == thrd_nomem);
277  rtems_heap_greedy_free(greedy);
278
279  status = thrd_create(&ctx->thrd, thrd_start, ctx);
280  rtems_test_assert(status == thrd_success);
281
282  status = thrd_create(&ctx->thrd, thrd_start, ctx);
283  rtems_test_assert(status == thrd_error);
284
285  exit_status = 0;
286  status = thrd_join(ctx->thrd, &exit_status);
287  rtems_test_assert(status == thrd_success);
288  rtems_test_assert(exit_status == 123);
289
290  status = thrd_detach(thrd_current());
291  rtems_test_assert(status == thrd_success);
292
293  status = thrd_detach(11235);
294  rtems_test_assert(status == thrd_error);
295#endif
296}
297
298static void high_task(rtems_task_argument idx)
299{
300  test_context *ctx = &test_instance;
301
302  while (true) {
303    rtems_event_set events;
304    rtems_status_code sc;
305    int status;
306
307    sc = rtems_event_receive(
308      RTEMS_ALL_EVENTS,
309      RTEMS_EVENT_ANY | RTEMS_WAIT,
310      RTEMS_NO_TIMEOUT,
311      &events
312    );
313    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
314
315    if ((events & EVENT_MTX_LOCK) != 0) {
316      status = mtx_lock(&ctx->mtx);
317      rtems_test_assert(status == thrd_success);
318      next_generation(ctx);
319    }
320
321    if ((events & EVENT_MTX_UNLOCK) != 0) {
322      status = mtx_unlock(&ctx->mtx);
323      rtems_test_assert(status == thrd_success);
324      next_generation(ctx);
325    }
326
327    if ((events & EVENT_CND_WAIT) != 0) {
328      status = mtx_lock(&ctx->mtx);
329      rtems_test_assert(status == thrd_success);
330      next_generation(ctx);
331
332      status = cnd_wait(&ctx->cnd, &ctx->mtx);
333      rtems_test_assert(status == thrd_success);
334      next_generation(ctx);
335
336      status = mtx_unlock(&ctx->mtx);
337      rtems_test_assert(status == thrd_success);
338    }
339
340    if ((events & EVENT_CND_TIMEDWAIT) != 0) {
341      struct timespec to;
342
343      status = mtx_lock(&ctx->mtx);
344      rtems_test_assert(status == thrd_success);
345      next_generation(ctx);
346
347      get_abs_timeout(&to);
348      status = cnd_timedwait(&ctx->cnd, &ctx->mtx, &to);
349      rtems_test_assert(status == thrd_success);
350      next_generation(ctx);
351
352      status = mtx_unlock(&ctx->mtx);
353      rtems_test_assert(status == thrd_success);
354    }
355
356    if ((events & EVENT_TSS) != 0) {
357      void *val;
358
359      status = tss_set(ctx->tss, &tss_val);
360      rtems_test_assert(status == thrd_success);
361
362      val = tss_get(ctx->tss);
363      rtems_test_assert(val == &tss_val);
364
365      rtems_task_exit();
366      rtems_test_assert(0);
367    }
368  }
369}
370
371static void test(void)
372{
373  test_context *ctx = &test_instance;
374  rtems_status_code sc;
375
376  test_init(ctx);
377
378  ctx->low = rtems_task_self();
379
380  sc = rtems_task_create(
381    rtems_build_name('H', 'I', 'G', 'H'),
382    1,
383    RTEMS_MINIMUM_STACK_SIZE,
384    RTEMS_DEFAULT_MODES,
385    RTEMS_DEFAULT_ATTRIBUTES,
386    &ctx->high
387  );
388  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
389
390  sc = rtems_task_start(ctx->high, high_task, 0);
391  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
392
393  test_once(ctx);
394  test_mtx(ctx);
395  test_cnd(ctx);
396  test_tss(ctx);
397  test_thrd(ctx);
398  test_destroy(ctx);
399}
400
401static void Init(rtems_task_argument arg)
402{
403  TEST_BEGIN();
404
405  test();
406
407  TEST_END();
408  rtems_test_exit(0);
409}
410
411#define CONFIGURE_MICROSECONDS_PER_TICK US_PER_TICK
412
413#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
414#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
415
416#define CONFIGURE_MAXIMUM_TASKS 4
417
418#define CONFIGURE_MAXIMUM_POSIX_KEYS 1
419#define CONFIGURE_MAXIMUM_POSIX_KEY_VALUE_PAIRS 1
420
421#if defined(RTEMS_POSIX_API)
422#define CONFIGURE_MAXIMUM_POSIX_THREADS 1
423#endif
424
425#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
426
427#define CONFIGURE_INIT_TASK_PRIORITY 4
428#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES
429
430#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
431
432#define CONFIGURE_SCHEDULER_NAME rtems_build_name('b', 'l', 'u', 'e')
433
434#define CONFIGURE_INIT
435
436#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.