source: rtems/testsuites/sptests/sp37/init.c @ f22af606

4.115
Last change on this file since f22af606 was f22af606, checked in by Sebastian Huber <sebastian.huber@…>, on Jun 19, 2015 at 7:17:55 PM

sptests/sp37: Fix type and simplify

  • Property mode set to 100644
File size: 15.9 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_Flash( &lock, &lock_context );
183  rtems_test_assert( normal_interrupt_level != _ISR_Get_level() );
184  _ISR_lock_Release_and_ISR_enable( &lock, &lock_context );
185
186  rtems_test_assert( normal_interrupt_level == _ISR_Get_level() );
187
188  _ISR_lock_ISR_disable( &lock_context );
189  rtems_test_assert( normal_interrupt_level != _ISR_Get_level() );
190  _ISR_lock_ISR_enable( &lock_context );
191
192  rtems_test_assert( normal_interrupt_level == _ISR_Get_level() );
193
194  _ISR_lock_Acquire( &lock, &lock_context );
195  rtems_test_assert( normal_interrupt_level == _ISR_Get_level() );
196  _ISR_lock_Release( &lock, &lock_context );
197
198  rtems_test_assert( normal_interrupt_level == _ISR_Get_level() );
199
200  _ISR_lock_Destroy( &lock );
201  _ISR_lock_Destroy( &initialized );
202}
203
204static rtems_mode get_interrupt_level( void )
205{
206  rtems_status_code sc;
207  rtems_mode mode;
208
209  sc = rtems_task_mode( RTEMS_CURRENT_MODE, RTEMS_CURRENT_MODE, &mode );
210  rtems_test_assert( sc == RTEMS_SUCCESSFUL );
211
212  return mode & RTEMS_INTERRUPT_MASK;
213}
214
215static void test_interrupt_locks( void )
216{
217  rtems_mode normal_interrupt_level = get_interrupt_level();
218  rtems_interrupt_lock initialized = RTEMS_INTERRUPT_LOCK_INITIALIZER("test");
219  rtems_interrupt_lock lock;
220  rtems_interrupt_lock_context lock_context;
221
222  rtems_interrupt_lock_initialize( &lock, "test" );
223  rtems_test_assert( memcmp( &lock, &initialized, lock_size ) == 0 );
224
225  rtems_interrupt_lock_acquire( &lock, &lock_context );
226  rtems_test_assert( normal_interrupt_level != get_interrupt_level() );
227  rtems_interrupt_lock_release( &lock, &lock_context );
228
229  rtems_test_assert( normal_interrupt_level == get_interrupt_level() );
230
231  rtems_interrupt_lock_acquire_isr( &lock, &lock_context );
232  rtems_test_assert( normal_interrupt_level == get_interrupt_level() );
233  rtems_interrupt_lock_release_isr( &lock, &lock_context );
234
235  rtems_test_assert( normal_interrupt_level == get_interrupt_level() );
236
237  rtems_interrupt_lock_destroy( &lock );
238  rtems_interrupt_lock_destroy( &initialized );
239}
240
241static void test_clock_tick_functions( void )
242{
243  rtems_interrupt_level level;
244  Watchdog_Interval saved_ticks;
245
246  _Thread_Disable_dispatch();
247  rtems_interrupt_disable( level );
248
249  saved_ticks = _Watchdog_Ticks_since_boot;
250
251  _Watchdog_Ticks_since_boot = 0xdeadbeef;
252  rtems_test_assert( rtems_clock_get_ticks_since_boot() == 0xdeadbeef );
253
254  rtems_test_assert( rtems_clock_tick_later( 0 ) == 0xdeadbeef );
255  rtems_test_assert( rtems_clock_tick_later( 0x8160311e ) == 0x600df00d );
256
257  _Watchdog_Ticks_since_boot = 0;
258  rtems_test_assert( rtems_clock_tick_later_usec( 0 ) == 1 );
259  rtems_test_assert( rtems_clock_tick_later_usec( 1 ) == 2 );
260  rtems_test_assert( rtems_clock_tick_later_usec( US_PER_TICK ) == 2 );
261  rtems_test_assert( rtems_clock_tick_later_usec( US_PER_TICK + 1 ) == 3 );
262
263  _Watchdog_Ticks_since_boot = 0;
264  rtems_test_assert( !rtems_clock_tick_before( 0xffffffff ) );
265  rtems_test_assert( !rtems_clock_tick_before( 0 ) );
266  rtems_test_assert( rtems_clock_tick_before( 1 ) );
267
268  _Watchdog_Ticks_since_boot = 1;
269  rtems_test_assert( !rtems_clock_tick_before( 0 ) );
270  rtems_test_assert( !rtems_clock_tick_before( 1 ) );
271  rtems_test_assert( rtems_clock_tick_before( 2 ) );
272
273  _Watchdog_Ticks_since_boot = 0x7fffffff;
274  rtems_test_assert( !rtems_clock_tick_before( 0x7ffffffe ) );
275  rtems_test_assert( !rtems_clock_tick_before( 0x7fffffff ) );
276  rtems_test_assert( rtems_clock_tick_before( 0x80000000 ) );
277
278  _Watchdog_Ticks_since_boot = 0x80000000;
279  rtems_test_assert( !rtems_clock_tick_before( 0x7fffffff ) );
280  rtems_test_assert( !rtems_clock_tick_before( 0x80000000 ) );
281  rtems_test_assert( rtems_clock_tick_before( 0x80000001 ) );
282
283  _Watchdog_Ticks_since_boot = 0xffffffff;
284  rtems_test_assert( !rtems_clock_tick_before( 0xfffffffe ) );
285  rtems_test_assert( !rtems_clock_tick_before( 0xffffffff ) );
286  rtems_test_assert( rtems_clock_tick_before( 0 ) );
287
288  _Watchdog_Ticks_since_boot = saved_ticks;
289
290  rtems_interrupt_enable( level );
291  _Thread_Enable_dispatch();
292}
293
294void test_interrupt_inline(void)
295{
296  rtems_interrupt_level level;
297  rtems_mode            level_mode_body;
298  rtems_mode            level_mode_macro;
299  bool                  in_isr;
300
301  puts( "interrupt is in progress (use body)" );
302  in_isr = rtems_interrupt_is_in_progress();
303  if ( in_isr ) {
304    puts( "interrupt reported to be is in progress (body)" );
305    rtems_test_exit( 0 );
306  }
307
308  puts( "interrupt disable (use inline)" );
309  _Thread_Disable_dispatch();
310  rtems_interrupt_disable( level );
311  _Thread_Enable_dispatch();
312
313  puts( "interrupt flash (use inline)" );
314  _Thread_Disable_dispatch();
315  rtems_interrupt_flash( level );
316  _Thread_Enable_dispatch();
317
318  puts( "interrupt enable (use inline)" );
319  _Thread_Disable_dispatch();
320  rtems_interrupt_enable( level );
321  _Thread_Enable_dispatch();
322
323  puts( "interrupt level mode (use inline)" );
324  level_mode_body = rtems_interrupt_level_body( level );
325  level_mode_macro = RTEMS_INTERRUPT_LEVEL(level);
326  if ( level_mode_macro == level_mode_body ) {
327    puts( "test case working.." );
328  }
329}
330
331volatile int isr_in_progress_body;
332volatile int isr_in_progress_inline;
333
334void check_isr_in_progress_inline(void)
335{
336  isr_in_progress_inline = rtems_interrupt_is_in_progress() ? 1 : 2;
337}
338
339#undef rtems_interrupt_disable
340extern rtems_interrupt_level rtems_interrupt_disable(void);
341#undef rtems_interrupt_enable
342extern void rtems_interrupt_enable(rtems_interrupt_level previous_level);
343#undef rtems_interrupt_flash
344extern void rtems_interrupt_flash(rtems_interrupt_level previous_level);
345#undef rtems_interrupt_is_in_progress
346extern bool rtems_interrupt_is_in_progress(void);
347
348rtems_timer_service_routine test_isr_in_progress(
349  rtems_id  timer,
350  void     *arg
351)
352{
353  check_isr_in_progress_inline();
354
355  isr_in_progress_body = rtems_interrupt_is_in_progress() ? 1 : 2;
356}
357
358void check_isr_worked(
359  char *s,
360  int   result
361)
362{
363  switch (result) {
364    case 0:
365      printf( "isr_in_progress(%s) timer did not fire\n", s );
366      rtems_test_exit(0);
367      break;
368    case 1:
369      printf( "isr_in_progress(%s) from ISR -- OK\n", s );
370      break;
371    default:
372      printf( "isr_in_progress(%s) from ISR -- returned bad value\n", s);
373      rtems_test_exit(0);
374      break;
375  }
376}
377
378volatile int blocked_task_status;
379rtems_id     blocked_task_id;
380
381rtems_task blocked_task(
382  rtems_task_argument argument
383)
384{
385  rtems_status_code     status;
386
387  puts( "Blocking task... suspending self" );
388  blocked_task_status = 1;
389  status = rtems_task_suspend( RTEMS_SELF );
390  directive_failed( status, "rtems_task_suspend" );
391
392  blocked_task_status = 3;
393  status = rtems_task_delete( RTEMS_SELF );
394  directive_failed( status, "rtems_task_delete" );
395}
396
397/*
398 *  Timer Service Routine
399 *
400 *  If we are in an ISR, then this is a normal clock tick.
401 *  If we are not, then it is the test case.
402 */
403rtems_timer_service_routine test_unblock_task(
404  rtems_id  timer,
405  void     *arg
406)
407{
408  bool              in_isr;
409  rtems_status_code status;
410
411  in_isr = rtems_interrupt_is_in_progress();
412  status = rtems_task_is_suspended( blocked_task_id );
413  if ( in_isr ) {
414    status = rtems_timer_fire_after( timer, 1, test_unblock_task, NULL );
415    directive_failed( status, "timer_fire_after failed" );
416    return;
417  }
418
419  if ( (status != RTEMS_ALREADY_SUSPENDED) ) {
420    status = rtems_timer_fire_after( timer, 1, test_unblock_task, NULL );
421    directive_failed( status, "timer_fire_after failed" );
422    return;
423  }
424
425  blocked_task_status = 2;
426  _Thread_Disable_dispatch();
427  status = rtems_task_resume( blocked_task_id );
428  _Thread_Unnest_dispatch();
429  directive_failed( status, "rtems_task_resume" );
430}
431
432rtems_task Init(
433  rtems_task_argument argument
434)
435{
436  rtems_time_of_day     time;
437  rtems_status_code     status;
438  rtems_interrupt_level level;
439  rtems_mode            level_mode_body;
440  rtems_mode            level_mode_macro;
441  bool                  in_isr;
442  rtems_id              timer;
443  int                   i;
444
445  TEST_BEGIN();
446
447  test_isr_level();
448  test_isr_locks();
449  test_interrupt_locks();
450
451  build_time( &time, 12, 31, 1988, 9, 0, 0, 0 );
452  status = rtems_clock_set( &time );
453  directive_failed( status, "rtems_clock_set" );
454
455  /*
456   *  Timer used in multiple ways
457   */
458  status = rtems_timer_create( 1, &timer );
459  directive_failed( status, "rtems_timer_create" );
460
461  /*
462   *  Test clock tick from outside ISR
463   */
464  status = rtems_clock_tick();
465  directive_failed( status, "rtems_clock_tick" );
466  puts( "clock_tick from task level" );
467
468  test_clock_tick_functions();
469
470  /*
471   *  Now do a dispatch directly out of a clock tick that is
472   *  called from a task.  We need to create a task that will
473   *  block so we have one to unblock.  Then we schedule a TSR
474   *  to run in the clock tick but it has to be careful to
475   *  make sure it is not called from an ISR and that the
476   *  dispatching critical section is managed properly to
477   *  make the dispatch happen.
478   */
479
480  blocked_task_status = -1;
481
482  status = rtems_task_create(
483    rtems_build_name( 'T', 'A', '1', ' ' ),
484    1,
485    RTEMS_MINIMUM_STACK_SIZE,
486    RTEMS_DEFAULT_MODES,
487    RTEMS_DEFAULT_ATTRIBUTES,
488    &blocked_task_id
489  );
490  directive_failed( status, "rtems_task_create" );
491
492  status = rtems_task_start( blocked_task_id, blocked_task, 0 );
493  directive_failed( status, "rtems_task_start" );
494
495  status = rtems_task_wake_after( 10 );
496  directive_failed( status, "rtems_task_wake_after" );
497
498  status = rtems_timer_fire_after( timer, 1, test_unblock_task, NULL );
499  directive_failed( status, "timer_fire_after failed" );
500
501  /* we expect to be preempted from this call */
502  for ( i=0 ; i<100 && blocked_task_status != 3 ; i++ ) {
503    status = rtems_clock_tick();
504    directive_failed( status, "rtems_clock_tick" );
505  }
506  switch ( blocked_task_status ) {
507     case -1:
508       puts(
509         "clock_tick with task preempt -- task blocked, timer did not fire"
510       );
511       rtems_test_exit(0);
512       break;
513     case 1:
514       puts( "clock_tick with task preempt -- timer fired case 1" );
515       rtems_test_exit(0);
516       break;
517     case 2:
518       puts( "clock_tick with task preempt -- timer fired case 2" );
519       rtems_test_exit(0);
520       break;
521     case 3:
522       puts( "clock_tick from task level with preempt -- OK" );
523       break;
524  }
525
526  /*
527   *  Test interrupt inline versions
528   */
529  test_interrupt_inline();
530
531  /*
532   *  Test interrupt bodies
533   */
534  puts( "interrupt is in progress (use body)" );
535  in_isr = rtems_interrupt_is_in_progress();
536  if ( in_isr ) {
537    puts( "interrupt reported to be is in progress (body)" );
538    rtems_test_exit( 0 );
539  }
540
541  puts( "interrupt disable (use body)" );
542  _Thread_Disable_dispatch();
543  level = rtems_interrupt_disable();
544  _Thread_Enable_dispatch();
545
546  puts( "interrupt disable (use body)" );
547  _Thread_Disable_dispatch();
548  level = rtems_interrupt_disable();
549  _Thread_Enable_dispatch();
550
551  puts( "interrupt flash (use body)" );
552  _Thread_Disable_dispatch();
553  rtems_interrupt_flash( level );
554  _Thread_Enable_dispatch();
555
556  puts( "interrupt enable (use body)" );
557  _Thread_Disable_dispatch();
558  rtems_interrupt_enable( level );
559  _Thread_Enable_dispatch();
560
561  puts( "interrupt level mode (use body)" );
562  level_mode_body = rtems_interrupt_level_body( level );
563  level_mode_macro = RTEMS_INTERRUPT_LEVEL(level);
564  if ( level_mode_macro == level_mode_body ) {
565    puts("test seems to work");
566  }
567
568  /*
569   * Test ISR in progress from actual ISR
570   */
571  status = rtems_timer_fire_after( timer, 10, test_isr_in_progress, NULL );
572  directive_failed( status, "timer_fire_after failed" );
573
574  status = rtems_task_wake_after( 11 );
575  directive_failed( status, "wake_after failed" );
576
577  check_isr_worked( "inline", isr_in_progress_inline );
578
579  check_isr_worked( "body", isr_in_progress_body );
580
581  TEST_END();
582  rtems_test_exit( 0 );
583}
Note: See TracBrowser for help on using the repository browser.