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

4.115
Last change on this file since c3cd7e7 was 6c0301d, checked in by Sebastian Huber <sebastian.huber@…>, on 03/25/14 at 07:06:21

tests/sptests: Use <rtems/test.h>

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