source: rtems/testsuites/sptests/sp37/init.c @ 99de42c

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