source: rtems/testsuites/tmtests/tm27/task1.c @ bf30999

4.115
Last change on this file since bf30999 was bf30999, checked in by Sebastian Huber <sebastian.huber@…>, on 08/23/13 at 14:15:50

smp: Add and use _Assert_Owner_of_giant()

Add and use _ISR_Disable_without_giant() and
_ISR_Enable_without_giant() if RTEMS_SMP is defined.

On single processor systems the ISR disable/enable was the big hammer
which ensured system-wide mutual exclusion. On SMP configurations this
no longer works since other processors do not care about disabled
interrupts on this processor and continue to execute freely.

On SMP in addition to ISR disable/enable an SMP lock must be used.
Currently we have only the Giant lock so we can check easily that ISR
disable/enable is used only in the right context.

  • Property mode set to 100644
File size: 6.6 KB
Line 
1/*
2 *  COPYRIGHT (c) 1989-2011.
3 *  On-Line Applications Research Corporation (OAR).
4 *
5 *  The license and distribution terms for this file may be
6 *  found in the file LICENSE in this distribution or at
7 *  http://www.rtems.com/license/LICENSE.
8 */
9
10/*
11 *  WARNING!!!!!!!!!
12 *
13 *  THIS TEST USES INTERNAL RTEMS VARIABLES!!!
14 */
15
16#ifdef HAVE_CONFIG_H
17#include "config.h"
18#endif
19
20#define CONFIGURE_INIT
21#include "system.h"
22
23#include <bsp.h>
24
25#define _RTEMS_TMTEST27
26#include <tm27.h>
27
28rtems_task Task_1(
29  rtems_task_argument argument
30);
31
32rtems_task Task_2(
33  rtems_task_argument argument
34);
35
36volatile uint32_t   Interrupt_occurred;
37volatile uint32_t   Interrupt_enter_time, Interrupt_enter_nested_time;
38volatile uint32_t   Interrupt_return_time, Interrupt_return_nested_time;
39uint32_t   Interrupt_nest;
40uint32_t   timer_overhead;
41
42rtems_isr Isr_handler(
43  rtems_vector_number vector
44);
45
46rtems_task Init(
47  rtems_task_argument argument
48)
49{
50  rtems_status_code status;
51
52  Print_Warning();
53
54  puts( "\n\n*** TIME TEST 27 ***" );
55  if (_Scheduler.Operations.initialize != _Scheduler_priority_Initialize) {
56    puts("  Error ==> " );
57    puts("Test only supported for deterministic priority scheduler\n" );
58    puts( "*** END OF TEST 26 ***" );
59    rtems_test_exit( 0 );
60  }
61
62#define LOW_PRIORITY (RTEMS_MAXIMUM_PRIORITY - 1u)
63  status = rtems_task_create(
64    rtems_build_name( 'T', 'A', '1', ' ' ),
65    LOW_PRIORITY,
66    RTEMS_MINIMUM_STACK_SIZE,
67    RTEMS_DEFAULT_MODES,
68    RTEMS_DEFAULT_ATTRIBUTES,
69    &Task_id[ 1 ]
70  );
71  directive_failed( status, "rtems_task_create Task_1" );
72
73  status = rtems_task_start( Task_id[ 1 ], Task_1, 0 );
74  directive_failed( status, "rtems_task_start Task_1" );
75
76  status = rtems_task_create(
77    rtems_build_name( 'T', 'A', '2', ' ' ),
78    LOW_PRIORITY,
79    RTEMS_MINIMUM_STACK_SIZE,
80    RTEMS_DEFAULT_MODES,
81    RTEMS_DEFAULT_ATTRIBUTES,
82    &Task_id[ 2 ]
83  );
84  directive_failed( status, "rtems_task_create of Task_2" );
85
86  status = rtems_task_start( Task_id[ 2 ], Task_2, 0 );
87  directive_failed( status, "rtems_task_start of Task_2" );
88
89  benchmark_timer_initialize();
90  benchmark_timer_read();
91  benchmark_timer_initialize();
92  timer_overhead = benchmark_timer_read();
93
94  status = rtems_task_delete( RTEMS_SELF );
95  directive_failed( status, "rtems_task_delete of RTEMS_SELF" );
96}
97
98rtems_task Task_1(
99  rtems_task_argument argument
100)
101{
102#if defined(RTEMS_SMP)
103  rtems_interrupt_level level;
104#endif
105  Chain_Control   *ready_queues;
106
107  Install_tm27_vector( Isr_handler );
108
109  /*
110   *  No preempt .. no nesting
111   */
112
113  Interrupt_nest = 0;
114
115  _Thread_Dispatch_set_disable_level( 0 );
116
117  Interrupt_occurred = 0;
118
119  benchmark_timer_initialize();
120  Cause_tm27_intr();
121  /* goes to Isr_handler */
122
123#if (MUST_WAIT_FOR_INTERRUPT == 1)
124  while ( Interrupt_occurred == 0 );
125#endif
126  Interrupt_return_time = benchmark_timer_read();
127
128  put_time(
129    "interrupt entry overhead: returns to interrupted task",
130    Interrupt_enter_time,
131    1,
132    0,
133    timer_overhead
134  );
135
136  put_time(
137    "interrupt exit overhead: returns to interrupted task",
138    Interrupt_return_time,
139    1,
140    0,
141    timer_overhead
142  );
143
144  /*
145   *  No preempt .. nested
146   */
147
148  _Thread_Dispatch_set_disable_level( 1 );
149
150  Interrupt_nest = 1;
151
152  Interrupt_occurred = 0;
153  benchmark_timer_initialize();
154  Cause_tm27_intr();
155  /* goes to Isr_handler */
156
157#if (MUST_WAIT_FOR_INTERRUPT == 1)
158  while ( Interrupt_occurred == 0 );
159#endif
160  Interrupt_return_time = benchmark_timer_read();
161
162  _Thread_Dispatch_set_disable_level( 0 );
163
164  put_time(
165    "interrupt entry overhead: returns to nested interrupt",
166    Interrupt_enter_nested_time,
167    1,
168    0,
169    0
170  );
171
172  put_time(
173    "interrupt exit overhead: returns to nested interrupt",
174    Interrupt_return_nested_time,
175    1,
176    0,
177    0
178  );
179
180  /*
181   *  Does a preempt .. not nested
182   */
183
184  _Thread_Dispatch_set_disable_level( 0 );
185
186#if defined(RTEMS_SMP)
187  _ISR_Disable_without_giant(level);
188#endif
189
190  ready_queues      = (Chain_Control *) _Scheduler.information;
191  _Thread_Executing =
192        (Thread_Control *) _Chain_First(&ready_queues[LOW_PRIORITY]);
193
194  _Thread_Dispatch_necessary = 1;
195
196#if defined(RTEMS_SMP)
197  _ISR_Enable_without_giant(level);
198#endif
199
200  Interrupt_occurred = 0;
201  benchmark_timer_initialize();
202  Cause_tm27_intr();
203
204  /*
205   *  goes to Isr_handler and then returns
206   */
207
208  puts( "*** END OF TEST 27 ***" );
209  rtems_test_exit( 0 );
210}
211
212/*
213 *  NOTE:  When this task is executing, some of the assumptions made
214 *         regarding the placement of the currently executing task's TCB
215 *         on the ready chains have been violated.  At least the assumption
216 *         that this task is at the head of the chain for its priority
217 *         has been violated.
218 */
219
220rtems_task Task_2(
221  rtems_task_argument argument
222)
223{
224#if defined(RTEMS_SMP)
225  rtems_interrupt_level level;
226#endif
227  Chain_Control   *ready_queues;
228
229#if (MUST_WAIT_FOR_INTERRUPT == 1)
230  while ( Interrupt_occurred == 0 );
231#endif
232  end_time = benchmark_timer_read();
233
234  put_time(
235    "interrupt entry overhead: returns to preempting task",
236    Interrupt_enter_time,
237    1,
238    0,
239    timer_overhead
240  );
241
242  put_time(
243    "interrupt exit overhead: returns to preempting task",
244    end_time,
245    1,
246    0,
247    0
248  );
249
250  fflush( stdout );
251
252  /*
253   *  Switch back to the other task to exit the test.
254   */
255
256  _Thread_Dispatch_set_disable_level( 0 );
257
258#if defined(RTEMS_SMP)
259  rtems_interrupt_disable(level);
260#endif
261
262  ready_queues      = (Chain_Control *) _Scheduler.information;
263  _Thread_Executing =
264        (Thread_Control *) _Chain_First(&ready_queues[LOW_PRIORITY]);
265
266  _Thread_Dispatch_necessary = 1;
267
268#if defined(RTEMS_SMP)
269  rtems_interrupt_enable(level);
270#endif
271
272  _Thread_Dispatch();
273
274}
275
276/*  The Isr_handler() and Isr_handler_inner() routines are structured
277 *  so that there will be as little entry overhead as possible included
278 *  in the interrupt entry time.
279 */
280
281void Isr_handler_inner( void );
282
283rtems_isr Isr_handler(
284  rtems_vector_number vector
285)
286{
287  end_time = benchmark_timer_read();
288
289  Interrupt_occurred = 1;
290  Isr_handler_inner();
291}
292
293void Isr_handler_inner( void )
294{
295
296  /*enable_tracing();*/
297  Clear_tm27_intr();
298  switch ( Interrupt_nest ) {
299    case 0:
300      Interrupt_enter_time = end_time;
301      break;
302    case 1:
303      Interrupt_enter_time = end_time;
304      Interrupt_nest = 2;
305      Interrupt_occurred = 0;
306      Lower_tm27_intr();
307      benchmark_timer_initialize();
308      Cause_tm27_intr();
309      /* goes to a nested copy of Isr_handler */
310#if (MUST_WAIT_FOR_INTERRUPT == 1)
311       while ( Interrupt_occurred == 0 );
312#endif
313      Interrupt_return_nested_time = benchmark_timer_read();
314      break;
315    case 2:
316      Interrupt_enter_nested_time = end_time;
317      break;
318  }
319
320  benchmark_timer_initialize();
321}
Note: See TracBrowser for help on using the repository browser.