source: rtems/testsuites/sptests/sp37/init.c @ 6cf45cb

4.115
Last change on this file since 6cf45cb was 2d5424d2, checked in by Sebastian Huber <sebastian.huber@…>, on 04/09/14 at 07:40:43

sptests/sp37: Account for internal struct align

  • Property mode set to 100644
File size: 13.8 KB
Line 
1/**
2 *  @brief Test for Bodies of Macros
3 *
4 *  Interrupt Disable/Enable Tests
5 *  Clock Tick from task level
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2012.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.org/license/LICENSE.
15 */
16
17#ifdef HAVE_CONFIG_H
18#include "config.h"
19#endif
20
21#define CONFIGURE_INIT
22#include "system.h"
23
24const char rtems_test_name[] = "SP 37";
25
26/* prototypes */
27void test_interrupt_inline(void);
28void check_isr_in_progress_inline(void);
29rtems_task blocked_task(rtems_task_argument argument);
30rtems_timer_service_routine test_unblock_task(
31  rtems_id  timer,
32  void     *arg
33);
34rtems_timer_service_routine test_unblock_task(
35  rtems_id  timer,
36  void     *arg
37);
38void check_isr_worked(
39  char *s,
40  int   result
41);
42rtems_timer_service_routine test_isr_in_progress(
43  rtems_id  timer,
44  void     *arg
45);
46
47/* test bodies */
48
49#define TEST_ISR_EVENT RTEMS_EVENT_0
50
51typedef struct {
52  ISR_Level actual_level;
53  rtems_id master_task_id;
54} test_isr_level_context;
55
56static void isr_level_check_task( rtems_task_argument arg )
57{
58  test_isr_level_context *ctx = (test_isr_level_context *) arg;
59  rtems_status_code sc;
60
61  ctx->actual_level = _ISR_Get_level();
62
63  sc = rtems_event_send( ctx->master_task_id,  TEST_ISR_EVENT );
64  rtems_test_assert( sc == RTEMS_SUCCESSFUL );
65
66  ( void ) rtems_task_suspend( RTEMS_SELF );
67  rtems_test_assert( 0 );
68}
69
70static void test_isr_level_for_new_threads( ISR_Level last_proper_level )
71{
72  ISR_Level mask = CPU_MODES_INTERRUPT_MASK;
73  ISR_Level current;
74  test_isr_level_context ctx = {
75    .master_task_id = rtems_task_self()
76  };
77
78  for ( current = 0 ; current <= mask ; ++current ) {
79    rtems_mode initial_modes = RTEMS_INTERRUPT_LEVEL(current);
80    rtems_id id;
81    rtems_status_code sc;
82    rtems_event_set events;
83
84    ctx.actual_level = 0xffffffff;
85
86    sc = rtems_task_create(
87      rtems_build_name('I', 'S', 'R', 'L'),
88      RTEMS_MINIMUM_PRIORITY,
89      RTEMS_MINIMUM_STACK_SIZE,
90      initial_modes,
91      RTEMS_DEFAULT_ATTRIBUTES,
92      &id
93    );
94    rtems_test_assert( sc == RTEMS_SUCCESSFUL );
95
96    sc = rtems_task_start(
97      id,
98      isr_level_check_task,
99      (rtems_task_argument) &ctx
100    );
101    rtems_test_assert( sc == RTEMS_SUCCESSFUL );
102
103    sc = rtems_event_receive(
104      TEST_ISR_EVENT,
105      RTEMS_EVENT_ALL | RTEMS_WAIT,
106      RTEMS_NO_TIMEOUT,
107      &events
108    );
109    rtems_test_assert( sc == RTEMS_SUCCESSFUL );
110    rtems_test_assert( events == TEST_ISR_EVENT );
111
112    if ( current <= last_proper_level ) {
113      rtems_test_assert( ctx.actual_level == current );
114    } else {
115      rtems_test_assert( ctx.actual_level == last_proper_level );
116    }
117
118    sc = rtems_task_delete( id ) ;
119    rtems_test_assert( sc == RTEMS_SUCCESSFUL );
120  }
121}
122
123static void test_isr_level( void )
124{
125  ISR_Level mask = CPU_MODES_INTERRUPT_MASK;
126  ISR_Level normal = _ISR_Get_level();
127  ISR_Level current = 0;
128  ISR_Level last_proper_level;
129
130  _ISR_Set_level( current );
131  rtems_test_assert( _ISR_Get_level() == current );
132
133  for ( current = current + 1 ; current <= mask ; ++current ) {
134    ISR_Level actual;
135
136    _ISR_Set_level( current );
137
138    actual = _ISR_Get_level();
139    rtems_test_assert( actual == current || actual == ( current - 1 ) );
140
141    if ( _ISR_Get_level() != current ) {
142      break;
143    }
144  }
145
146  last_proper_level = current - 1;
147
148  for ( current = current + 1 ; current <= mask ; ++current ) {
149    _ISR_Set_level( current );
150    rtems_test_assert( _ISR_Get_level() == current );
151  }
152
153  _ISR_Set_level( normal );
154
155  /*
156   * Now test that the ISR level specified for _Thread_Initialize() propagates
157   * properly to the thread.
158   */
159  test_isr_level_for_new_threads( last_proper_level );
160}
161
162#if defined(RTEMS_SMP) && defined(RTEMS_PROFILING)
163static const size_t lock_size =
164  offsetof( ISR_lock_Control, lock.ticket_lock.Stats.name )
165    + sizeof( ((ISR_lock_Control *) 0)->lock.ticket_lock.Stats.name );
166#else
167static const size_t lock_size = sizeof( ISR_lock_Control );
168#endif
169
170static void test_isr_locks( void )
171{
172  ISR_Level normal_interrupt_level = _ISR_Get_level();
173  ISR_lock_Control initialized = ISR_LOCK_INITIALIZER("test");
174  ISR_lock_Control lock;
175  ISR_lock_Context lock_context;
176
177  _ISR_lock_Initialize( &lock, "test" );
178  rtems_test_assert( memcmp( &lock, &initialized, lock_size ) == 0 );
179
180  _ISR_lock_ISR_disable_and_acquire( &lock, &lock_context );
181  rtems_test_assert( normal_interrupt_level != _ISR_Get_level() );
182  _ISR_lock_Release_and_ISR_enable( &lock, &lock_context );
183
184  rtems_test_assert( normal_interrupt_level == _ISR_Get_level() );
185
186  _ISR_lock_Acquire( &lock, &lock_context );
187  rtems_test_assert( normal_interrupt_level == _ISR_Get_level() );
188  _ISR_lock_Release( &lock, &lock_context );
189
190  rtems_test_assert( normal_interrupt_level == _ISR_Get_level() );
191
192  _ISR_lock_Destroy( &lock );
193  _ISR_lock_Destroy( &initialized );
194}
195
196static rtems_mode get_interrupt_level( void )
197{
198  rtems_status_code sc;
199  rtems_mode mode;
200
201  sc = rtems_task_mode( RTEMS_CURRENT_MODE, RTEMS_CURRENT_MODE, &mode );
202  rtems_test_assert( sc == RTEMS_SUCCESSFUL );
203
204  return mode & RTEMS_INTERRUPT_MASK;
205}
206
207static void test_interrupt_locks( void )
208{
209  rtems_mode normal_interrupt_level = get_interrupt_level();
210  rtems_interrupt_lock initialized = RTEMS_INTERRUPT_LOCK_INITIALIZER("test");
211  rtems_interrupt_lock lock;
212  rtems_interrupt_lock_context lock_context;
213
214  rtems_interrupt_lock_initialize( &lock, "test" );
215  rtems_test_assert( memcmp( &lock, &initialized, lock_size ) == 0 );
216
217  rtems_interrupt_lock_acquire( &lock, &lock_context );
218  rtems_test_assert( normal_interrupt_level != get_interrupt_level() );
219  rtems_interrupt_lock_release( &lock, &lock_context );
220
221  rtems_test_assert( normal_interrupt_level == get_interrupt_level() );
222
223  rtems_interrupt_lock_acquire_isr( &lock, &lock_context );
224  rtems_test_assert( normal_interrupt_level == get_interrupt_level() );
225  rtems_interrupt_lock_release_isr( &lock, &lock_context );
226
227  rtems_test_assert( normal_interrupt_level == get_interrupt_level() );
228
229  rtems_interrupt_lock_destroy( &lock );
230  rtems_interrupt_lock_destroy( &initialized );
231}
232
233void test_interrupt_inline(void)
234{
235  rtems_interrupt_level level;
236  rtems_mode            level_mode_body;
237  rtems_mode            level_mode_macro;
238  bool                  in_isr;
239
240  puts( "interrupt is in progress (use body)" );
241  in_isr = rtems_interrupt_is_in_progress();
242  if ( in_isr ) {
243    puts( "interrupt reported to be is in progress (body)" );
244    rtems_test_exit( 0 );
245  }
246
247  puts( "interrupt disable (use inline)" );
248  _Thread_Disable_dispatch();
249  rtems_interrupt_disable( level );
250  _Thread_Enable_dispatch();
251
252  puts( "interrupt flash (use inline)" );
253  _Thread_Disable_dispatch();
254  rtems_interrupt_flash( level );
255  _Thread_Enable_dispatch();
256
257  puts( "interrupt enable (use inline)" );
258  _Thread_Disable_dispatch();
259  rtems_interrupt_enable( level );
260  _Thread_Enable_dispatch();
261
262  puts( "interrupt level mode (use inline)" );
263  level_mode_body = rtems_interrupt_level_body( level );
264  level_mode_macro = RTEMS_INTERRUPT_LEVEL(level);
265  if ( level_mode_macro == level_mode_body ) {
266    puts( "test case working.." );
267  }
268}
269
270volatile int isr_in_progress_body;
271volatile int isr_in_progress_inline;
272
273void check_isr_in_progress_inline(void)
274{
275  bool in_isr;
276
277  in_isr = rtems_interrupt_is_in_progress();
278  isr_in_progress_inline = ( in_isr ) ? 1 : 2;
279}
280
281#undef rtems_interrupt_disable
282extern rtems_interrupt_level rtems_interrupt_disable(void);
283#undef rtems_interrupt_enable
284extern void rtems_interrupt_enable(rtems_interrupt_level previous_level);
285#undef rtems_interrupt_flash
286extern void rtems_interrupt_flash(rtems_interrupt_level previous_level);
287#undef rtems_interrupt_is_in_progress
288extern bool rtems_interrupt_is_in_progress(void);
289
290rtems_timer_service_routine test_isr_in_progress(
291  rtems_id  timer,
292  void     *arg
293)
294{
295  bool in_isr;
296
297  check_isr_in_progress_inline();
298
299  in_isr = rtems_interrupt_is_in_progress();
300  isr_in_progress_body = ( in_isr ) ? 1 : 2;
301}
302
303void check_isr_worked(
304  char *s,
305  int   result
306)
307{
308  switch (result) {
309    case -1:
310      printf( "isr_in_progress(%s) timer did not fire\n", s );
311      break;
312    case 1:
313      printf( "isr_in_progress(%s) from ISR -- OK\n", s );
314      break;
315    case 2:
316      printf( "isr_in_progress(%s) from ISR -- returned bad value\n", s);
317      rtems_test_exit(0);
318      break;
319  }
320}
321
322volatile int blocked_task_status;
323rtems_id     blocked_task_id;
324
325rtems_task blocked_task(
326  rtems_task_argument argument
327)
328{
329  rtems_status_code     status;
330
331  puts( "Blocking task... suspending self" );
332  blocked_task_status = 1;
333  status = rtems_task_suspend( RTEMS_SELF );
334  directive_failed( status, "rtems_task_suspend" );
335
336  blocked_task_status = 3;
337  status = rtems_task_delete( RTEMS_SELF );
338  directive_failed( status, "rtems_task_delete" );
339}
340
341/*
342 *  Timer Service Routine
343 *
344 *  If we are in an ISR, then this is a normal clock tick.
345 *  If we are not, then it is the test case.
346 */
347rtems_timer_service_routine test_unblock_task(
348  rtems_id  timer,
349  void     *arg
350)
351{
352  bool              in_isr;
353  rtems_status_code status;
354
355  in_isr = rtems_interrupt_is_in_progress();
356  status = rtems_task_is_suspended( blocked_task_id );
357  if ( in_isr ) {
358    status = rtems_timer_fire_after( timer, 1, test_unblock_task, NULL );
359    directive_failed( status, "timer_fire_after failed" );
360    return;
361  }
362
363  if ( (status != RTEMS_ALREADY_SUSPENDED) ) {
364    status = rtems_timer_fire_after( timer, 1, test_unblock_task, NULL );
365    directive_failed( status, "timer_fire_after failed" );
366    return;
367  }
368
369  blocked_task_status = 2;
370  _Thread_Disable_dispatch();
371  status = rtems_task_resume( blocked_task_id );
372  _Thread_Unnest_dispatch();
373#if defined( RTEMS_SMP )
374  directive_failed_with_level( status, "rtems_task_resume", 1 );
375#else
376  directive_failed( status, "rtems_task_resume" );
377#endif
378}
379
380rtems_task Init(
381  rtems_task_argument argument
382)
383{
384  rtems_time_of_day     time;
385  rtems_status_code     status;
386  rtems_interrupt_level level;
387  rtems_mode            level_mode_body;
388  rtems_mode            level_mode_macro;
389  bool                  in_isr;
390  rtems_id              timer;
391  int                   i;
392
393  TEST_BEGIN();
394
395  test_isr_level();
396  test_isr_locks();
397  test_interrupt_locks();
398
399  build_time( &time, 12, 31, 1988, 9, 0, 0, 0 );
400  status = rtems_clock_set( &time );
401  directive_failed( status, "rtems_clock_set" );
402
403  /*
404   *  Timer used in multiple ways
405   */
406  status = rtems_timer_create( 1, &timer );
407  directive_failed( status, "rtems_timer_create" );
408
409  /*
410   *  Test clock tick from outside ISR
411   */
412  status = rtems_clock_tick();
413  directive_failed( status, "rtems_clock_tick" );
414  puts( "clock_tick from task level" );
415
416  /*
417   *  Now do a dispatch directly out of a clock tick that is
418   *  called from a task.  We need to create a task that will
419   *  block so we have one to unblock.  Then we schedule a TSR
420   *  to run in the clock tick but it has to be careful to
421   *  make sure it is not called from an ISR and that the
422   *  dispatching critical section is managed properly to
423   *  make the dispatch happen.
424   */
425
426  blocked_task_status = -1;
427
428  status = rtems_task_create(
429    rtems_build_name( 'T', 'A', '1', ' ' ),
430    1,
431    RTEMS_MINIMUM_STACK_SIZE,
432    RTEMS_DEFAULT_MODES,
433    RTEMS_DEFAULT_ATTRIBUTES,
434    &blocked_task_id
435  );
436  directive_failed( status, "rtems_task_create" );
437
438  status = rtems_task_start( blocked_task_id, blocked_task, 0 );
439  directive_failed( status, "rtems_task_start" );
440
441  status = rtems_task_wake_after( 10 );
442  directive_failed( status, "rtems_task_wake_after" );
443
444  status = rtems_timer_fire_after( timer, 1, test_unblock_task, NULL );
445  directive_failed( status, "timer_fire_after failed" );
446
447  /* we expect to be preempted from this call */
448  for ( i=0 ; i<100 && blocked_task_status != 3 ; i++ ) {
449    status = rtems_clock_tick();
450    directive_failed( status, "rtems_clock_tick" );
451  }
452  switch ( blocked_task_status ) {
453     case -1:
454       puts(
455         "clock_tick with task preempt -- task blocked, timer did not fire"
456       );
457       rtems_test_exit(0);
458       break;
459     case 1:
460       puts( "clock_tick with task preempt -- timer fired case 1" );
461       rtems_test_exit(0);
462       break;
463     case 2:
464       puts( "clock_tick with task preempt -- timer fired case 2" );
465       rtems_test_exit(0);
466       break;
467     case 3:
468       puts( "clock_tick from task level with preempt -- OK" );
469       break;
470  }
471
472  /*
473   *  Test interrupt inline versions
474   */
475  test_interrupt_inline();
476
477  /*
478   *  Test interrupt bodies
479   */
480  puts( "interrupt is in progress (use body)" );
481  in_isr = rtems_interrupt_is_in_progress();
482  if ( in_isr ) {
483    puts( "interrupt reported to be is in progress (body)" );
484    rtems_test_exit( 0 );
485  }
486
487  puts( "interrupt disable (use body)" );
488  _Thread_Disable_dispatch();
489  level = rtems_interrupt_disable();
490  _Thread_Enable_dispatch();
491
492  puts( "interrupt disable (use body)" );
493  _Thread_Disable_dispatch();
494  level = rtems_interrupt_disable();
495  _Thread_Enable_dispatch();
496
497  puts( "interrupt flash (use body)" );
498  _Thread_Disable_dispatch();
499  rtems_interrupt_flash( level );
500  _Thread_Enable_dispatch();
501
502  puts( "interrupt enable (use body)" );
503  _Thread_Disable_dispatch();
504  rtems_interrupt_enable( level );
505  _Thread_Enable_dispatch();
506
507  puts( "interrupt level mode (use body)" );
508  level_mode_body = rtems_interrupt_level_body( level );
509  level_mode_macro = RTEMS_INTERRUPT_LEVEL(level);
510  if ( level_mode_macro == level_mode_body ) {
511    puts("test seems to work");
512  }
513
514  /*
515   * Test ISR in progress from actual ISR
516   */
517  isr_in_progress_body   = -1;
518  isr_in_progress_inline = -1;
519
520  status = rtems_timer_fire_after( timer, 10, test_isr_in_progress, NULL );
521  directive_failed( status, "timer_fire_after failed" );
522
523  status = rtems_task_wake_after( 100 );
524  directive_failed( status, "wake_after failed" );
525
526  check_isr_worked( "inline", isr_in_progress_body );
527
528  check_isr_worked( "body", isr_in_progress_body );
529
530  TEST_END();
531  rtems_test_exit( 0 );
532}
Note: See TracBrowser for help on using the repository browser.