source: rtems/testsuites/sptests/spintrcritical10/init.c @ dce48791

Last change on this file since dce48791 was dce48791, checked in by Sebastian Huber <sebastian.huber@…>, on May 23, 2016 at 11:37:59 AM

score: Add Status_Control for all APIs

Unify the status codes of the Classic and POSIX API to use the new enum
Status_Control. This eliminates the Thread_Control::Wait::timeout_code
field and the timeout parameter of _Thread_queue_Enqueue_critical() and
_MPCI_Send_request_packet(). It gets rid of the status code translation
tables and instead uses simple bit operations to get the status for a
particular API. This enables translation of status code constants at
compile time. Add _Thread_Wait_get_status() to avoid direct access of
thread internal data structures.

  • Property mode set to 100644
File size: 9.2 KB
Line 
1/*
2 *  COPYRIGHT (c) 1989-2012.
3 *  On-Line Applications Research Corporation (OAR).
4 *
5 *  Copyright (c) 2013 embedded brains GmbH.
6 *
7 *  The license and distribution terms for this file may be
8 *  found in the file LICENSE in this distribution or at
9 *  http://www.rtems.org/license/LICENSE.
10 */
11
12#ifdef HAVE_CONFIG_H
13  #include "config.h"
14#endif
15
16#include <tmacros.h>
17#include <intrcritical.h>
18
19#include <rtems/score/threadimpl.h>
20#include <rtems/rtems/eventimpl.h>
21
22const char rtems_test_name[] = "SPINTRCRITICAL 10";
23
24#define GREEN RTEMS_EVENT_0
25
26#define RED RTEMS_EVENT_1
27
28#define EVENTS (GREEN | RED)
29
30#define DEADBEEF 0xdeadbeef
31
32typedef struct {
33  rtems_id timer;
34  Thread_Control *thread;
35  bool hit;
36} test_context;
37
38static bool blocks_for_event(Thread_Wait_flags flags)
39{
40  return flags == (THREAD_WAIT_CLASS_EVENT | THREAD_WAIT_STATE_INTEND_TO_BLOCK)
41    || flags == (THREAD_WAIT_CLASS_EVENT | THREAD_WAIT_STATE_BLOCKED);
42}
43
44static bool interrupts_blocking_op(Thread_Wait_flags flags)
45{
46  return
47    flags == (THREAD_WAIT_CLASS_EVENT | THREAD_WAIT_STATE_INTEND_TO_BLOCK);
48}
49
50static void any_satisfy_before_timeout(rtems_id timer, void *arg)
51{
52  rtems_status_code sc;
53  test_context *ctx = arg;
54  Thread_Control *thread = ctx->thread;
55  Thread_Wait_flags flags = _Thread_Wait_flags_get(thread);
56
57  if (blocks_for_event(flags)) {
58    ctx->hit = interrupts_blocking_op(flags);
59
60    rtems_test_assert(
61      *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
62    );
63    rtems_test_assert(_Thread_Wait_get_status(thread) == STATUS_SUCCESSFUL);
64
65    sc = rtems_event_send(thread->Object.id, GREEN);
66    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
67
68    rtems_test_assert(
69      *(rtems_event_set *) thread->Wait.return_argument == GREEN
70    );
71    rtems_test_assert(_Thread_Wait_get_status(thread) == STATUS_SUCCESSFUL);
72
73    sc = rtems_event_send(thread->Object.id, RED);
74    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
75
76    rtems_test_assert(
77      *(rtems_event_set *) thread->Wait.return_argument == GREEN
78    );
79    rtems_test_assert(_Thread_Wait_get_status(thread) == STATUS_SUCCESSFUL);
80
81    _Thread_Timeout(&thread->Timer.Watchdog);
82
83    rtems_test_assert(
84      *(rtems_event_set *) thread->Wait.return_argument == GREEN
85    );
86    rtems_test_assert(_Thread_Wait_get_status(thread) == STATUS_SUCCESSFUL);
87
88    if (ctx->hit) {
89      rtems_test_assert(
90        _Thread_Wait_flags_get(thread)
91          == (THREAD_WAIT_CLASS_EVENT | THREAD_WAIT_STATE_READY_AGAIN)
92      );
93    }
94
95    rtems_test_assert(thread->Wait.count == EVENTS);
96  }
97
98  sc = rtems_timer_reset(timer);
99  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
100}
101
102static bool test_body_any_satisfy_before_timeout(void *arg)
103{
104  test_context *ctx = arg;
105  rtems_status_code sc;
106  rtems_event_set out;
107
108  out = DEADBEEF;
109  sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ANY | RTEMS_WAIT, 1, &out);
110  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
111  rtems_test_assert(out == GREEN);
112
113  out = DEADBEEF;
114  sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, 0, &out);
115  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
116  rtems_test_assert(out == RED);
117
118  return ctx->hit;
119}
120
121static void test_any_satisfy_before_timeout(test_context *ctx)
122{
123  rtems_status_code sc;
124
125  puts(
126    "Init - Trying to generate any satisfied before timeout "
127    "while blocking on event"
128  );
129
130  ctx->hit = false;
131
132  sc = rtems_timer_fire_after(ctx->timer, 1, any_satisfy_before_timeout, ctx);
133  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
134
135  interrupt_critical_section_test(
136    test_body_any_satisfy_before_timeout,
137    ctx,
138    NULL
139  );
140
141  sc = rtems_timer_cancel(ctx->timer);
142  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
143
144  rtems_test_assert(ctx->hit);
145}
146
147static void all_satisfy_before_timeout(rtems_id timer, void *arg)
148{
149  rtems_status_code sc;
150  test_context *ctx = arg;
151  Thread_Control *thread = ctx->thread;
152  Thread_Wait_flags flags = _Thread_Wait_flags_get(thread);
153
154  if (blocks_for_event(flags)) {
155    ctx->hit = interrupts_blocking_op(flags);
156
157    rtems_test_assert(
158      *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
159    );
160    rtems_test_assert(_Thread_Wait_get_status(thread) == STATUS_SUCCESSFUL);
161
162    sc = rtems_event_send(thread->Object.id, GREEN);
163    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
164
165    rtems_test_assert(
166      *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
167    );
168    rtems_test_assert(_Thread_Wait_get_status(thread) == STATUS_SUCCESSFUL);
169
170    sc = rtems_event_send(thread->Object.id, RED);
171    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
172
173    rtems_test_assert(
174      *(rtems_event_set *) thread->Wait.return_argument == EVENTS
175    );
176    rtems_test_assert(_Thread_Wait_get_status(thread) == STATUS_SUCCESSFUL);
177
178    _Thread_Timeout(&thread->Timer.Watchdog);
179
180    rtems_test_assert(
181      *(rtems_event_set *) thread->Wait.return_argument == EVENTS
182    );
183    rtems_test_assert(_Thread_Wait_get_status(thread) == STATUS_SUCCESSFUL);
184
185    if (ctx->hit) {
186      rtems_test_assert(
187        _Thread_Wait_flags_get(thread)
188          == (THREAD_WAIT_CLASS_EVENT | THREAD_WAIT_STATE_READY_AGAIN)
189      );
190    }
191
192    rtems_test_assert(thread->Wait.count == EVENTS);
193  }
194
195  sc = rtems_timer_reset(timer);
196  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
197}
198
199static bool test_body_all_satisfy_before_timeout(void *arg)
200{
201  test_context *ctx = arg;
202  rtems_status_code sc;
203  rtems_event_set out;
204
205  out = DEADBEEF;
206  sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ALL | RTEMS_WAIT, 1, &out);
207  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
208  rtems_test_assert(out == EVENTS);
209
210  return ctx->hit;
211}
212
213static void test_all_satisfy_before_timeout(test_context *ctx)
214{
215  rtems_status_code sc;
216
217  puts(
218    "Init - Trying to generate all satisfied before timeout "
219    "while blocking on event"
220  );
221
222  ctx->hit = false;
223
224  sc = rtems_timer_fire_after(ctx->timer, 1, all_satisfy_before_timeout, ctx);
225  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
226
227  interrupt_critical_section_test(
228    test_body_all_satisfy_before_timeout,
229    ctx,
230    NULL
231  );
232
233  sc = rtems_timer_cancel(ctx->timer);
234  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
235
236  rtems_test_assert(ctx->hit);
237}
238
239static void timeout_before_satisfied(rtems_id timer, void *arg)
240{
241  rtems_status_code sc;
242  test_context *ctx = arg;
243  Thread_Control *thread = ctx->thread;
244  Thread_Wait_flags flags = _Thread_Wait_flags_get(thread);
245
246  if (blocks_for_event(flags)) {
247    ctx->hit = interrupts_blocking_op(flags);
248
249    rtems_test_assert(
250      *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
251    );
252    rtems_test_assert(_Thread_Wait_get_status(thread) == STATUS_SUCCESSFUL);
253
254    _Thread_Timeout(&thread->Timer.Watchdog);
255
256    rtems_test_assert(
257      *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
258    );
259    rtems_test_assert(_Thread_Wait_get_status(thread) == STATUS_TIMEOUT);
260
261    sc = rtems_event_send(thread->Object.id, EVENTS);
262    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
263
264    rtems_test_assert(
265      *(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
266    );
267    rtems_test_assert(_Thread_Wait_get_status(thread) == STATUS_TIMEOUT);
268
269    if (ctx->hit) {
270      rtems_test_assert(
271        _Thread_Wait_flags_get(thread)
272          == (THREAD_WAIT_CLASS_EVENT | THREAD_WAIT_STATE_READY_AGAIN)
273      );
274    }
275
276    rtems_test_assert(thread->Wait.count == EVENTS);
277  }
278
279  sc = rtems_timer_reset(timer);
280  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
281}
282
283static bool test_body_timeout_before_all_satisfy(void *arg)
284{
285  test_context *ctx = arg;
286  rtems_event_set out;
287  rtems_status_code sc;
288
289  out = DEADBEEF;
290  sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ALL | RTEMS_WAIT, 1, &out);
291  rtems_test_assert(sc == RTEMS_TIMEOUT);
292  rtems_test_assert(out == DEADBEEF);
293
294  out = DEADBEEF;
295  sc = rtems_event_receive(EVENTS, RTEMS_EVENT_ALL | RTEMS_NO_WAIT, 0, &out);
296  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
297  rtems_test_assert(out == EVENTS);
298
299  return ctx->hit;
300}
301
302static void test_timeout_before_all_satisfy(test_context *ctx)
303{
304  rtems_status_code sc;
305
306  puts(
307    "Init - Trying to generate timeout before all satisfied "
308    "while blocking on event"
309  );
310
311  ctx->hit = false;
312
313  sc = rtems_timer_fire_after(ctx->timer, 1, timeout_before_satisfied, ctx);
314  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
315
316  interrupt_critical_section_test(
317    test_body_timeout_before_all_satisfy,
318    ctx,
319    NULL
320  );
321
322  sc = rtems_timer_cancel(ctx->timer);
323  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
324
325  rtems_test_assert(ctx->hit);
326}
327
328static rtems_task Init(
329  rtems_task_argument ignored
330)
331{
332  rtems_status_code sc;
333  test_context ctx = {
334    .thread = _Thread_Get_executing()
335  };
336
337  TEST_BEGIN();
338
339  sc = rtems_timer_create(rtems_build_name('T', 'I', 'M', 'R'), &ctx.timer);
340  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
341
342  test_any_satisfy_before_timeout(&ctx);
343  test_all_satisfy_before_timeout(&ctx);
344  test_timeout_before_all_satisfy(&ctx);
345
346  TEST_END();
347  rtems_test_exit(0);
348}
349
350/* configuration information */
351
352#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
353#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
354
355#define CONFIGURE_MAXIMUM_TASKS       1
356#define CONFIGURE_MAXIMUM_TIMERS      1
357#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1
358#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
359
360#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
361#define CONFIGURE_MICROSECONDS_PER_TICK  1000
362
363#define CONFIGURE_INIT
364#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.