source: rtems/testsuites/sptests/sp37/init.c @ 2d5424d2

4.115
Last change on this file since 2d5424d2 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
RevLine 
[5d443559]1/**
2 *  @brief Test for Bodies of Macros
3 *
[6bc19a1]4 *  Interrupt Disable/Enable Tests
5 *  Clock Tick from task level
[5d443559]6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2012.
[6bc19a1]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
[c499856]14 *  http://www.rtems.org/license/LICENSE.
[6bc19a1]15 */
16
[7d3f9c6]17#ifdef HAVE_CONFIG_H
18#include "config.h"
19#endif
20
[2186ba80]21#define CONFIGURE_INIT
[6bc19a1]22#include "system.h"
23
[6c0301d]24const char rtems_test_name[] = "SP 37";
25
[b84f1fdc]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 */
[c7bc6d4]48
[25d921e]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
[da831d0]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;
[25d921e]128  ISR_Level last_proper_level;
[da831d0]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
[25d921e]146  last_proper_level = current - 1;
147
[da831d0]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 );
[25d921e]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 );
[da831d0]160}
161
[2d5424d2]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
[2d915cf]170static void test_isr_locks( void )
171{
172  ISR_Level normal_interrupt_level = _ISR_Get_level();
[53ad908]173  ISR_lock_Control initialized = ISR_LOCK_INITIALIZER("test");
[2d915cf]174  ISR_lock_Control lock;
[d50acdbb]175  ISR_lock_Context lock_context;
[2d915cf]176
[53ad908]177  _ISR_lock_Initialize( &lock, "test" );
[2d5424d2]178  rtems_test_assert( memcmp( &lock, &initialized, lock_size ) == 0 );
[2d915cf]179
[d50acdbb]180  _ISR_lock_ISR_disable_and_acquire( &lock, &lock_context );
[2d915cf]181  rtems_test_assert( normal_interrupt_level != _ISR_Get_level() );
[d50acdbb]182  _ISR_lock_Release_and_ISR_enable( &lock, &lock_context );
[8d640134]183
184  rtems_test_assert( normal_interrupt_level == _ISR_Get_level() );
185
[d50acdbb]186  _ISR_lock_Acquire( &lock, &lock_context );
[8d640134]187  rtems_test_assert( normal_interrupt_level == _ISR_Get_level() );
[d50acdbb]188  _ISR_lock_Release( &lock, &lock_context );
[2d915cf]189
190  rtems_test_assert( normal_interrupt_level == _ISR_Get_level() );
[28779c7]191
192  _ISR_lock_Destroy( &lock );
193  _ISR_lock_Destroy( &initialized );
[2d915cf]194}
195
[f20275d]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
[c7bc6d4]207static void test_interrupt_locks( void )
208{
[f20275d]209  rtems_mode normal_interrupt_level = get_interrupt_level();
[53ad908]210  rtems_interrupt_lock initialized = RTEMS_INTERRUPT_LOCK_INITIALIZER("test");
[f20275d]211  rtems_interrupt_lock lock;
[d50acdbb]212  rtems_interrupt_lock_context lock_context;
[c7bc6d4]213
[53ad908]214  rtems_interrupt_lock_initialize( &lock, "test" );
[2d5424d2]215  rtems_test_assert( memcmp( &lock, &initialized, lock_size ) == 0 );
[c7bc6d4]216
[d50acdbb]217  rtems_interrupt_lock_acquire( &lock, &lock_context );
[f20275d]218  rtems_test_assert( normal_interrupt_level != get_interrupt_level() );
[d50acdbb]219  rtems_interrupt_lock_release( &lock, &lock_context );
[c7bc6d4]220
[f20275d]221  rtems_test_assert( normal_interrupt_level == get_interrupt_level() );
222
[d50acdbb]223  rtems_interrupt_lock_acquire_isr( &lock, &lock_context );
[f20275d]224  rtems_test_assert( normal_interrupt_level == get_interrupt_level() );
[d50acdbb]225  rtems_interrupt_lock_release_isr( &lock, &lock_context );
[8d640134]226
227  rtems_test_assert( normal_interrupt_level == get_interrupt_level() );
[28779c7]228
229  rtems_interrupt_lock_destroy( &lock );
230  rtems_interrupt_lock_destroy( &initialized );
[c7bc6d4]231}
232
[6bc19a1]233void test_interrupt_inline(void)
234{
235  rtems_interrupt_level level;
[5d443559]236  rtems_mode            level_mode_body;
237  rtems_mode            level_mode_macro;
238  bool                  in_isr;
[6bc19a1]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)" );
[bf30999]248  _Thread_Disable_dispatch();
[6bc19a1]249  rtems_interrupt_disable( level );
[bf30999]250  _Thread_Enable_dispatch();
[6bc19a1]251
252  puts( "interrupt flash (use inline)" );
[bf30999]253  _Thread_Disable_dispatch();
[6bc19a1]254  rtems_interrupt_flash( level );
[bf30999]255  _Thread_Enable_dispatch();
[6bc19a1]256
257  puts( "interrupt enable (use inline)" );
[bf30999]258  _Thread_Disable_dispatch();
[6bc19a1]259  rtems_interrupt_enable( level );
[bf30999]260  _Thread_Enable_dispatch();
[b1274bd9]261
[5d443559]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 ) {
[c8633f1]266    puts( "test case working.." );
267  }
[6bc19a1]268}
269
270volatile int isr_in_progress_body;
271volatile int isr_in_progress_inline;
272
273void check_isr_in_progress_inline(void)
274{
[f0157b8]275  bool in_isr;
[6bc19a1]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
[82a8add]282extern rtems_interrupt_level rtems_interrupt_disable(void);
[6bc19a1]283#undef rtems_interrupt_enable
[82a8add]284extern void rtems_interrupt_enable(rtems_interrupt_level previous_level);
[6bc19a1]285#undef rtems_interrupt_flash
[82a8add]286extern void rtems_interrupt_flash(rtems_interrupt_level previous_level);
[6bc19a1]287#undef rtems_interrupt_is_in_progress
[82a8add]288extern bool rtems_interrupt_is_in_progress(void);
[6bc19a1]289
290rtems_timer_service_routine test_isr_in_progress(
291  rtems_id  timer,
292  void     *arg
293)
294{
[f0157b8]295  bool in_isr;
[6bc19a1]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:
[79c49e1]316      printf( "isr_in_progress(%s) from ISR -- returned bad value\n", s);
[6bc19a1]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{
[f0157b8]352  bool              in_isr;
[6bc19a1]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;
[b1274bd9]367  }
[6bc19a1]368
369  blocked_task_status = 2;
370  _Thread_Disable_dispatch();
371  status = rtems_task_resume( blocked_task_id );
372  _Thread_Unnest_dispatch();
[d19cce29]373#if defined( RTEMS_SMP )
[918d5565]374  directive_failed_with_level( status, "rtems_task_resume", 1 );
[d19cce29]375#else
376  directive_failed( status, "rtems_task_resume" );
377#endif
[6bc19a1]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;
[5d443559]387  rtems_mode            level_mode_body;
388  rtems_mode            level_mode_macro;
[f0157b8]389  bool                  in_isr;
[6bc19a1]390  rtems_id              timer;
391  int                   i;
392
[6c0301d]393  TEST_BEGIN();
[6bc19a1]394
[da831d0]395  test_isr_level();
[2d915cf]396  test_isr_locks();
[f20275d]397  test_interrupt_locks();
398
[6bc19a1]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:
[9e15e9b]454       puts(
455         "clock_tick with task preempt -- task blocked, timer did not fire"
456       );
[6bc19a1]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)" );
[bf30999]488  _Thread_Disable_dispatch();
[86db88d2]489  level = rtems_interrupt_disable();
[bf30999]490  _Thread_Enable_dispatch();
[6bc19a1]491
492  puts( "interrupt disable (use body)" );
[bf30999]493  _Thread_Disable_dispatch();
[86db88d2]494  level = rtems_interrupt_disable();
[bf30999]495  _Thread_Enable_dispatch();
[6bc19a1]496
497  puts( "interrupt flash (use body)" );
[bf30999]498  _Thread_Disable_dispatch();
[6bc19a1]499  rtems_interrupt_flash( level );
[bf30999]500  _Thread_Enable_dispatch();
[6bc19a1]501
502  puts( "interrupt enable (use body)" );
[bf30999]503  _Thread_Disable_dispatch();
[6bc19a1]504  rtems_interrupt_enable( level );
[bf30999]505  _Thread_Enable_dispatch();
[b1274bd9]506
[5d443559]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 ) {
[c8633f1]511    puts("test seems to work");
512  }
[6bc19a1]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" );
[b1274bd9]525
[6bc19a1]526  check_isr_worked( "inline", isr_in_progress_body );
527
528  check_isr_worked( "body", isr_in_progress_body );
529
[6c0301d]530  TEST_END();
[6bc19a1]531  rtems_test_exit( 0 );
532}
Note: See TracBrowser for help on using the repository browser.