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

4.11
Last change on this file since 28779c7 was 28779c7, checked in by Sebastian Huber <sebastian.huber@…>, on Mar 7, 2014 at 11:53:41 AM

score: Add function to destroy SMP locks

  • Property mode set to 100644
File size: 13.5 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.com/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
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 */
46
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
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;
126  ISR_Level last_proper_level;
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
144  last_proper_level = current - 1;
145
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 );
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 );
158}
159
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;
165  ISR_lock_Context lock_context;
166
167  _ISR_lock_Initialize( &lock );
168  rtems_test_assert( memcmp( &lock, &initialized, sizeof( lock ) ) == 0 );
169
170  _ISR_lock_ISR_disable_and_acquire( &lock, &lock_context );
171  rtems_test_assert( normal_interrupt_level != _ISR_Get_level() );
172  _ISR_lock_Release_and_ISR_enable( &lock, &lock_context );
173
174  rtems_test_assert( normal_interrupt_level == _ISR_Get_level() );
175
176  _ISR_lock_Acquire( &lock, &lock_context );
177  rtems_test_assert( normal_interrupt_level == _ISR_Get_level() );
178  _ISR_lock_Release( &lock, &lock_context );
179
180  rtems_test_assert( normal_interrupt_level == _ISR_Get_level() );
181
182  _ISR_lock_Destroy( &lock );
183  _ISR_lock_Destroy( &initialized );
184}
185
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
197static void test_interrupt_locks( void )
198{
199  rtems_mode normal_interrupt_level = get_interrupt_level();
200  rtems_interrupt_lock initialized = RTEMS_INTERRUPT_LOCK_INITIALIZER;
201  rtems_interrupt_lock lock;
202  rtems_interrupt_lock_context lock_context;
203
204  rtems_interrupt_lock_initialize( &lock );
205  rtems_test_assert( memcmp( &lock, &initialized, sizeof( lock ) ) == 0 );
206
207  rtems_interrupt_lock_acquire( &lock, &lock_context );
208  rtems_test_assert( normal_interrupt_level != get_interrupt_level() );
209  rtems_interrupt_lock_release( &lock, &lock_context );
210
211  rtems_test_assert( normal_interrupt_level == get_interrupt_level() );
212
213  rtems_interrupt_lock_acquire_isr( &lock, &lock_context );
214  rtems_test_assert( normal_interrupt_level == get_interrupt_level() );
215  rtems_interrupt_lock_release_isr( &lock, &lock_context );
216
217  rtems_test_assert( normal_interrupt_level == get_interrupt_level() );
218
219  rtems_interrupt_lock_destroy( &lock );
220  rtems_interrupt_lock_destroy( &initialized );
221}
222
223void test_interrupt_inline(void)
224{
225  rtems_interrupt_level level;
226  rtems_mode            level_mode_body;
227  rtems_mode            level_mode_macro;
228  bool                  in_isr;
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)" );
238  _Thread_Disable_dispatch();
239  rtems_interrupt_disable( level );
240  _Thread_Enable_dispatch();
241
242  puts( "interrupt flash (use inline)" );
243  _Thread_Disable_dispatch();
244  rtems_interrupt_flash( level );
245  _Thread_Enable_dispatch();
246
247  puts( "interrupt enable (use inline)" );
248  _Thread_Disable_dispatch();
249  rtems_interrupt_enable( level );
250  _Thread_Enable_dispatch();
251
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 ) {
256    puts( "test case working.." );
257  }
258}
259
260volatile int isr_in_progress_body;
261volatile int isr_in_progress_inline;
262
263void check_isr_in_progress_inline(void)
264{
265  bool in_isr;
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
272extern rtems_interrupt_level rtems_interrupt_disable(void);
273#undef rtems_interrupt_enable
274extern void rtems_interrupt_enable(rtems_interrupt_level previous_level);
275#undef rtems_interrupt_flash
276extern void rtems_interrupt_flash(rtems_interrupt_level previous_level);
277#undef rtems_interrupt_is_in_progress
278extern bool rtems_interrupt_is_in_progress(void);
279
280rtems_timer_service_routine test_isr_in_progress(
281  rtems_id  timer,
282  void     *arg
283)
284{
285  bool in_isr;
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:
306      printf( "isr_in_progress(%s) from ISR -- returned bad value\n", s);
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{
342  bool              in_isr;
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;
357  }
358
359  blocked_task_status = 2;
360  _Thread_Disable_dispatch();
361  status = rtems_task_resume( blocked_task_id );
362  _Thread_Unnest_dispatch();
363#if defined( RTEMS_SMP )
364  directive_failed_with_level( status, "rtems_task_resume", 1 );
365#else
366  directive_failed( status, "rtems_task_resume" );
367#endif
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;
377  rtems_mode            level_mode_body;
378  rtems_mode            level_mode_macro;
379  bool                  in_isr;
380  rtems_id              timer;
381  int                   i;
382
383  puts( "\n\n*** TEST 37 ***" );
384
385  test_isr_level();
386  test_isr_locks();
387  test_interrupt_locks();
388
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:
444       puts(
445         "clock_tick with task preempt -- task blocked, timer did not fire"
446       );
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)" );
478  _Thread_Disable_dispatch();
479  level = rtems_interrupt_disable();
480  _Thread_Enable_dispatch();
481
482  puts( "interrupt disable (use body)" );
483  _Thread_Disable_dispatch();
484  level = rtems_interrupt_disable();
485  _Thread_Enable_dispatch();
486
487  puts( "interrupt flash (use body)" );
488  _Thread_Disable_dispatch();
489  rtems_interrupt_flash( level );
490  _Thread_Enable_dispatch();
491
492  puts( "interrupt enable (use body)" );
493  _Thread_Disable_dispatch();
494  rtems_interrupt_enable( level );
495  _Thread_Enable_dispatch();
496
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 ) {
501    puts("test seems to work");
502  }
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" );
515
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.