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

4.115
Last change on this file since c7bc6d4 was c7bc6d4, checked in by Sebastian Huber <sebastian.huber@…>, on 06/10/13 at 09:14:35

rtems: Add interrupt locks

Interrupt locks are low-level lock to protect critical sections accessed
by threads and interrupt service routines.

  • Property mode set to 100644
File size: 8.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
47static void test_interrupt_locks( void )
48{
49  rtems_interrupt_lock lock = RTEMS_INTERRUPT_LOCK_INITIALIZER;
50  rtems_interrupt_level level;
51
52  rtems_interrupt_lock_initialize( &lock );
53
54  rtems_interrupt_lock_acquire( &lock, level );
55  rtems_interrupt_lock_release( &lock, level );
56
57  rtems_interrupt_lock_acquire_isr( &lock );
58  rtems_interrupt_lock_release_isr( &lock );
59}
60
61void test_interrupt_inline(void)
62{
63  rtems_interrupt_level level;
64  rtems_mode            level_mode_body;
65  rtems_mode            level_mode_macro;
66  bool                  in_isr;
67
68  puts( "interrupt is in progress (use body)" );
69  in_isr = rtems_interrupt_is_in_progress();
70  if ( in_isr ) {
71    puts( "interrupt reported to be is in progress (body)" );
72    rtems_test_exit( 0 );
73  }
74
75  puts( "interrupt disable (use inline)" );
76  rtems_interrupt_disable( level );
77
78  puts( "interrupt flash (use inline)" );
79  rtems_interrupt_flash( level );
80
81  puts( "interrupt enable (use inline)" );
82  rtems_interrupt_enable( level );
83
84  puts( "interrupt level mode (use inline)" );
85  level_mode_body = rtems_interrupt_level_body( level );
86  level_mode_macro = RTEMS_INTERRUPT_LEVEL(level);
87  if ( level_mode_macro == level_mode_body ) {
88    puts( "test case working.." );
89  }
90}
91
92volatile int isr_in_progress_body;
93volatile int isr_in_progress_inline;
94
95void check_isr_in_progress_inline(void)
96{
97  bool in_isr;
98
99  in_isr = rtems_interrupt_is_in_progress();
100  isr_in_progress_inline = ( in_isr ) ? 1 : 2;
101}
102
103#undef rtems_interrupt_disable
104extern rtems_interrupt_level rtems_interrupt_disable(void);
105#undef rtems_interrupt_enable
106extern void rtems_interrupt_enable(rtems_interrupt_level previous_level);
107#undef rtems_interrupt_flash
108extern void rtems_interrupt_flash(rtems_interrupt_level previous_level);
109#undef rtems_interrupt_is_in_progress
110extern bool rtems_interrupt_is_in_progress(void);
111
112rtems_timer_service_routine test_isr_in_progress(
113  rtems_id  timer,
114  void     *arg
115)
116{
117  bool in_isr;
118
119  check_isr_in_progress_inline();
120
121  in_isr = rtems_interrupt_is_in_progress();
122  isr_in_progress_body = ( in_isr ) ? 1 : 2;
123}
124
125void check_isr_worked(
126  char *s,
127  int   result
128)
129{
130  switch (result) {
131    case -1:
132      printf( "isr_in_progress(%s) timer did not fire\n", s );
133      break;
134    case 1:
135      printf( "isr_in_progress(%s) from ISR -- OK\n", s );
136      break;
137    case 2:
138      printf( "isr_in_progress(%s) from ISR -- returned bad value\n", s);
139      rtems_test_exit(0);
140      break;
141  }
142}
143
144volatile int blocked_task_status;
145rtems_id     blocked_task_id;
146
147rtems_task blocked_task(
148  rtems_task_argument argument
149)
150{
151  rtems_status_code     status;
152
153  puts( "Blocking task... suspending self" );
154  blocked_task_status = 1;
155  status = rtems_task_suspend( RTEMS_SELF );
156  directive_failed( status, "rtems_task_suspend" );
157
158  blocked_task_status = 3;
159  status = rtems_task_delete( RTEMS_SELF );
160  directive_failed( status, "rtems_task_delete" );
161}
162
163/*
164 *  Timer Service Routine
165 *
166 *  If we are in an ISR, then this is a normal clock tick.
167 *  If we are not, then it is the test case.
168 */
169rtems_timer_service_routine test_unblock_task(
170  rtems_id  timer,
171  void     *arg
172)
173{
174  bool              in_isr;
175  rtems_status_code status;
176
177  in_isr = rtems_interrupt_is_in_progress();
178  status = rtems_task_is_suspended( blocked_task_id );
179  if ( in_isr ) {
180    status = rtems_timer_fire_after( timer, 1, test_unblock_task, NULL );
181    directive_failed( status, "timer_fire_after failed" );
182    return;
183  }
184
185  if ( (status != RTEMS_ALREADY_SUSPENDED) ) {
186    status = rtems_timer_fire_after( timer, 1, test_unblock_task, NULL );
187    directive_failed( status, "timer_fire_after failed" );
188    return;
189  }
190
191  blocked_task_status = 2;
192  _Thread_Disable_dispatch();
193  status = rtems_task_resume( blocked_task_id );
194  _Thread_Unnest_dispatch();
195  directive_failed( status, "rtems_task_resume" );
196}
197
198rtems_task Init(
199  rtems_task_argument argument
200)
201{
202  rtems_time_of_day     time;
203  rtems_status_code     status;
204  rtems_interrupt_level level;
205  rtems_mode            level_mode_body;
206  rtems_mode            level_mode_macro;
207  bool                  in_isr;
208  rtems_id              timer;
209  int                   i;
210
211  puts( "\n\n*** TEST 37 ***" );
212
213  build_time( &time, 12, 31, 1988, 9, 0, 0, 0 );
214  status = rtems_clock_set( &time );
215  directive_failed( status, "rtems_clock_set" );
216
217  /*
218   *  Timer used in multiple ways
219   */
220  status = rtems_timer_create( 1, &timer );
221  directive_failed( status, "rtems_timer_create" );
222
223  /*
224   *  Test clock tick from outside ISR
225   */
226  status = rtems_clock_tick();
227  directive_failed( status, "rtems_clock_tick" );
228  puts( "clock_tick from task level" );
229
230  /*
231   *  Now do a dispatch directly out of a clock tick that is
232   *  called from a task.  We need to create a task that will
233   *  block so we have one to unblock.  Then we schedule a TSR
234   *  to run in the clock tick but it has to be careful to
235   *  make sure it is not called from an ISR and that the
236   *  dispatching critical section is managed properly to
237   *  make the dispatch happen.
238   */
239
240  blocked_task_status = -1;
241
242  status = rtems_task_create(
243    rtems_build_name( 'T', 'A', '1', ' ' ),
244    1,
245    RTEMS_MINIMUM_STACK_SIZE,
246    RTEMS_DEFAULT_MODES,
247    RTEMS_DEFAULT_ATTRIBUTES,
248    &blocked_task_id
249  );
250  directive_failed( status, "rtems_task_create" );
251
252  status = rtems_task_start( blocked_task_id, blocked_task, 0 );
253  directive_failed( status, "rtems_task_start" );
254
255  status = rtems_task_wake_after( 10 );
256  directive_failed( status, "rtems_task_wake_after" );
257
258  status = rtems_timer_fire_after( timer, 1, test_unblock_task, NULL );
259  directive_failed( status, "timer_fire_after failed" );
260
261  /* we expect to be preempted from this call */
262  for ( i=0 ; i<100 && blocked_task_status != 3 ; i++ ) {
263    status = rtems_clock_tick();
264    directive_failed( status, "rtems_clock_tick" );
265  }
266  switch ( blocked_task_status ) {
267     case -1:
268       puts(
269         "clock_tick with task preempt -- task blocked, timer did not fire"
270       );
271       rtems_test_exit(0);
272       break;
273     case 1:
274       puts( "clock_tick with task preempt -- timer fired case 1" );
275       rtems_test_exit(0);
276       break;
277     case 2:
278       puts( "clock_tick with task preempt -- timer fired case 2" );
279       rtems_test_exit(0);
280       break;
281     case 3:
282       puts( "clock_tick from task level with preempt -- OK" );
283       break;
284  }
285
286  /*
287   *  Test interrupt inline versions
288   */
289  test_interrupt_inline();
290
291  /*
292   *  Test interrupt bodies
293   */
294  puts( "interrupt is in progress (use body)" );
295  in_isr = rtems_interrupt_is_in_progress();
296  if ( in_isr ) {
297    puts( "interrupt reported to be is in progress (body)" );
298    rtems_test_exit( 0 );
299  }
300
301  puts( "interrupt disable (use body)" );
302  level = rtems_interrupt_disable();
303
304  puts( "interrupt disable (use body)" );
305  level = rtems_interrupt_disable();
306
307  puts( "interrupt flash (use body)" );
308  rtems_interrupt_flash( level );
309
310  puts( "interrupt enable (use body)" );
311  rtems_interrupt_enable( level );
312
313  puts( "interrupt level mode (use body)" );
314  level_mode_body = rtems_interrupt_level_body( level );
315  level_mode_macro = RTEMS_INTERRUPT_LEVEL(level);
316  if ( level_mode_macro == level_mode_body ) {
317    puts("test seems to work");
318  }
319
320  /*
321   * Test ISR in progress from actual ISR
322   */
323  isr_in_progress_body   = -1;
324  isr_in_progress_inline = -1;
325
326  status = rtems_timer_fire_after( timer, 10, test_isr_in_progress, NULL );
327  directive_failed( status, "timer_fire_after failed" );
328
329  status = rtems_task_wake_after( 100 );
330  directive_failed( status, "wake_after failed" );
331
332  check_isr_worked( "inline", isr_in_progress_body );
333
334  check_isr_worked( "body", isr_in_progress_body );
335
336  test_interrupt_locks();
337
338  puts( "*** END OF TEST 37 ***" );
339  rtems_test_exit( 0 );
340}
Note: See TracBrowser for help on using the repository browser.