source: rtems/testsuites/sptests/sp37/init.c @ 28779c7

4.115
Last change on this file since 28779c7 was 28779c7, checked in by Sebastian Huber <sebastian.huber@…>, on 03/07/14 at 11:53:41

score: Add function to destroy SMP locks

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