source: rtems/testsuites/sptests/sp35/priinv.c @ b1274bd9

4.104.115
Last change on this file since b1274bd9 was b1274bd9, checked in by Ralf Corsepius <ralf.corsepius@…>, on 11/30/09 at 03:33:25

Whitespace removal.

  • Property mode set to 100644
File size: 16.0 KB
Line 
1/*
2 *  Simple test program to demonstrate priority inversion when blocking
3 *
4   -Ulf Ivraeus ------------- --- -- -  -   -
5 *  Saab Ericsson Space AB
6 *  phone:  +46 (0)31 735 4542
7 *  e-mail: ulf.ivraeus@space.se
8 *  ----------------------------- --- -- -  -   -
9 *
10 *  The license and distribution terms for this file may be
11 *  found in the file LICENSE in this distribution or at
12 *  http://www.rtems.com/license/LICENSE.
13 *
14 *  $Id$
15 */
16
17/********************************************************************
18
19  Semaphore Ids:
20    Sync Mutex Id   = 0x18010009
21    Local Mutex Id  = 0x1801000a
22    Remote Mutex Id = 0x1801000b
23
24  Task Ids:
25    TaMedium[0] Id  = 0x08010002
26    TaMedium[1] Id  = 0x08010003
27    TaMedium[2] Id  = 0x08010004
28    TaHigh Id       = 0x08010005
29    TaLow Id        = 0x08010006
30    TaHwSim Id      = 0x08010007
31
32********************************************************************/
33
34/********************************************************************/
35/* define this to use the RTEMS 4.5 scheme for object names */
36/* #define TEST_ON_RTEMS_45 */
37
38/* define this to print the Id of the calling task */
39/* #define TEST_ON_TASK_ID */
40
41/* define this to print statistics when acquiring the mutex */
42/* #define TEST_PRINT_STATISTICS */
43
44/* define this if you are (1) on a ERC32 and (2) want a SW ISR trigger */
45#if defined(__sparc__)
46/* #define TEST_USE_ISR */
47#endif
48
49/* define this if you want the test to exit */
50#define TEST_EXIT_AFTER_ITERATIONS 10
51/********************************************************************/
52
53#define CONFIGURE_INIT
54
55#include <bsp.h>
56#include <stdio.h>
57#include "tmacros.h"
58
59#if defined(TEST_EXIT_AFTER_ITERATIONS)
60volatile uint32_t Iterations = 0;
61#endif
62
63const char *CallerName(void);
64
65/* Task entry point prototypes */
66rtems_task Init(rtems_task_argument ignored);
67rtems_task Medium_Exec(rtems_task_argument TaskArg);
68rtems_task Low_Exec(rtems_task_argument TaskArg);
69rtems_task High_Exec(rtems_task_argument TaskArg);
70rtems_task LocalHwSim_Exec(rtems_task_argument TaskArg);
71
72/* ISR that signals that HW has completed */
73rtems_isr  LocalHwIsr(/*in*/ rtems_vector_number   Vector);
74
75/* Test driver functions */
76void AccessLocalHw(void);
77void AccessRemoteHw(void);
78
79const char *CallerName(void)
80{
81  static char buffer[32];
82#if defined(TEST_PRINT_TASK_ID)
83  sprintf( buffer, "0x%08x -- %d",
84      rtems_task_self(), _Thread_Executing->current_priority );
85#else
86  volatile union {
87    uint32_t u;
88    unsigned char c[4];
89  } TempName;
90
91  #if defined(TEST_ON_RTEMS_45)
92    TempName.u = *(uint32_t *)_Thread_Executing->Object.name;
93  #else
94    TempName.u = (uint32_t) _Thread_Executing->Object.name.name_u32;
95  #endif
96  sprintf( buffer, "%c%c%c%c -- %" PRIdPriority_Control,
97      TempName.c[0], TempName.c[1], TempName.c[2], TempName.c[3],
98      _Thread_Executing->current_priority
99  );
100#endif
101  return buffer;
102}
103
104#define NofMediumTask_C 3
105
106/* RTEMS identifiers */
107rtems_id  TaMedium[NofMediumTask_C]; /* Medium-prio tasks accessing */
108                                     /*    the common local HW */
109rtems_id  TaHwSim;                   /* HW simulator */
110rtems_id  TaLow;                     /* Low-prio task accessing common */
111                                     /*    remote HW */
112rtems_id  TaHigh;                    /* High-prio task accessing common */
113                                     /*    remote HW */
114
115
116rtems_id  LocalHwSync_S;             /* Syncrhonize task to local HW */
117rtems_id  LocalHwAccess_R;           /* Execlusive access to the local HW */
118rtems_id  RemoteHwAccess_R;          /* Execlusive access to the remote HW */
119
120
121/* The following variable triggers simulated HW activity */
122volatile bool StartHw = false;
123
124rtems_task Medium_Exec(rtems_task_argument TaskArg)
125{
126  printf("Medium_Exec (%" PRIdrtems_task_argument ") begins...\n", TaskArg);
127
128  rtems_task_wake_after(50);
129
130  while(1) {
131    AccessLocalHw();
132  }
133
134  /* JRS - task does not get here */
135
136  printf("Medium_Exec (%" PRIdrtems_task_argument ") ends...\n", TaskArg);
137  while(1) {
138    rtems_task_wake_after(10000);
139  }
140}
141
142rtems_task High_Exec(rtems_task_argument TaskArg)
143{
144  printf("High_Exec (%" PRIdrtems_task_argument ") begins...\n", TaskArg);
145
146  /* Delay more than the Low-prio task so that Remote HW access resource is
147   * taken before call to AccesRemoteHw.
148   */
149  rtems_task_wake_after(250);
150
151  while(1) {
152    AccessRemoteHw();
153  }
154
155  /* JRS - task does not get here */
156
157  printf("High_Exec (%" PRIdrtems_task_argument ") ends...\n", TaskArg);
158  while(1) {
159    rtems_task_wake_after(10000);
160  }
161  /* task does not get here */
162}
163
164rtems_task Low_Exec(rtems_task_argument TaskArg)
165{
166  printf("Low_Exec (%" PRIdrtems_task_argument ") begins...\n", TaskArg);
167
168  /* Delay less than High-prio task so that we take the remote HW access
169   * resource before it does it. However, delay longer than the mid-prio
170   * tasks so that we know for certain that they have taken control over
171   * the local HW access.
172   */
173  rtems_task_wake_after(100);
174
175  while(1) {
176    AccessRemoteHw();
177  }
178
179  /* JRS - task does not get here */
180
181  printf("Low_Exec (%" PRIdrtems_task_argument ") ends...\n", TaskArg);
182  while(1) {
183    rtems_task_wake_after(10000);
184  }
185}
186
187
188rtems_task LocalHwSim_Exec(rtems_task_argument TaskArg)
189{
190#if 0
191  int ISRCount = 0;
192#endif
193  printf("LocalHwSim_Exec begins...\n");
194
195  while(1) {
196    if (StartHw) {
197      /* A test task has activated the HW, wait for a while and then
198       * generate an interrupt
199       */
200      rtems_task_wake_after(100);
201
202      StartHw = FALSE;
203#if 0
204      fprintf( stderr, "StartHw -- fire ISR (%d)\n", ++ISRCount );
205#endif
206#if defined(TEST_USE_ISR)
207      __asm__ volatile ("ta 5");
208      __asm__ volatile ("nop");
209      __asm__ volatile ("nop");
210#else
211      LocalHwIsr( 0x85 );
212#endif
213    }
214
215  }
216
217  printf("LocalHwSim_Exec ends...\n");
218  while(1) {
219    rtems_task_wake_after(10000);
220  }
221}
222
223
224rtems_isr  LocalHwIsr(/*in*/ rtems_vector_number   Vector)
225{
226  rtems_status_code status;
227
228  /* Signal synchroniztion semaphore to invoke waiting task */
229  status = rtems_semaphore_release(LocalHwSync_S);
230  if (status != RTEMS_SUCCESSFUL) {
231    fprintf( stderr, "LocalHwISR release %d\n", status );
232    while(1); /* Error */
233  }
234
235  return;
236}
237
238void AccessLocalHw(void)
239{
240  rtems_status_code     Sts;
241
242  rtems_task_priority   EnterPrio;   /* Statistics log */
243  rtems_task_priority   AccessPrio;  /*      :         */
244  rtems_task_priority   LeavePrio;   /*      :         */
245  uint32_t              EnterCnt;    /*      :         */
246  uint32_t              AccessCnt;   /*      :         */
247  uint32_t              LeaveCnt;    /*      :         */
248
249  /* Store information about the current situation */
250  EnterPrio = _Thread_Executing->current_priority;
251  EnterCnt  = _Thread_Executing->resource_count;
252
253
254  printf("  AccessLocalHw called by %s\n", CallerName());
255
256  /* Obtain exclusive access to local HW, Start HW, Wait for completion,
257   * Release access
258   */
259
260  Sts = rtems_semaphore_obtain(LocalHwAccess_R, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
261  directive_failed( Sts, "rtems_semaphore_obtain(LocalHwAccess_R...)" );
262
263  StartHw = TRUE;
264
265  Sts = rtems_semaphore_obtain(LocalHwSync_S, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
266  directive_failed( Sts, "rtems_semaphore_obtain(LocalHwAccess_R...)" );
267
268  /* Store information about the current situation */
269  AccessPrio = _Thread_Executing->current_priority;
270  AccessCnt  = _Thread_Executing->resource_count;
271
272  Sts = rtems_semaphore_release(LocalHwAccess_R);
273  directive_failed( Sts, "rtems_semaphore_release(LocalHwAccess_R)" );
274
275  /* Store information about the current situation */
276  LeavePrio = _Thread_Executing->current_priority;
277  LeaveCnt  = _Thread_Executing->resource_count;
278
279#if defined(TEST_PRINT_STATISTICS)
280  printf(
281    "  AccessLocalHw from %s statistics:\n"
282    " - Prio: %d -> %d -> %d\n - Cnt: %d -> %d -> %d\n",
283    CallerName(),
284    EnterPrio, AccessPrio, LeavePrio,
285    EnterCnt, AccessCnt, LeaveCnt
286  );
287#endif
288
289  printf("  AccessLocalHw returns to %s\n", CallerName());
290  #if defined(TEST_EXIT_AFTER_ITERATIONS)
291    if ( ++Iterations == 10 ) {
292      puts( "*** END OF TEST 35 ***" );
293      exit(0);
294    }
295  #endif
296  return;
297}
298
299void AccessRemoteHw(void)
300{
301  rtems_status_code     Sts;
302
303  rtems_task_priority   EnterPrio;   /* Statistics log */
304  rtems_task_priority   AccessPrio;  /*      :         */
305  rtems_task_priority   LeavePrio;   /*      :         */
306  uint32_t              EnterCnt;    /*      :         */
307  uint32_t              AccessCnt;   /*      :         */
308  uint32_t              LeaveCnt;    /*      :         */
309
310  /* Store information about the current situation */
311  EnterPrio = _Thread_Executing->current_priority;
312  EnterCnt  = _Thread_Executing->resource_count;
313
314
315  printf("AccessRemoteHw called by %s\n", CallerName());
316
317  /* Obtain exclusive access to remote HW, Start HW, Wait for completion,
318   * Release access
319   */
320
321  Sts = rtems_semaphore_obtain(RemoteHwAccess_R, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
322  directive_failed( Sts, "rtems_semaphore_obtain(RemoteHwAccess_R...)" );
323
324  /* Carry out the remote access via the Local HW interface */
325  printf("AccessRemoteHw access local %s\n", CallerName());
326  AccessLocalHw();
327
328  /* Store information about the current situation */
329  AccessPrio = _Thread_Executing->current_priority;
330  AccessCnt  = _Thread_Executing->resource_count;
331
332  Sts = rtems_semaphore_release(RemoteHwAccess_R);
333  directive_failed( Sts, "rtems_semaphore_release(RemoreHwAccess_R" );
334
335  /* Store information about the current situation */
336  LeavePrio = _Thread_Executing->current_priority;
337  LeaveCnt  = _Thread_Executing->resource_count;
338
339#if defined(TEST_PRINT_STATISTICS)
340  printf(
341    "\nAccessRemoteHw from %s statistics:\n"
342    " - Prio: %d -> %d -> %d\n - Cnt: %d -> %d -> %d\n",
343    CallerName(),
344    EnterPrio, AccessPrio, LeavePrio,
345    EnterCnt, AccessCnt, LeaveCnt);
346#endif
347
348  printf("AccessRemoteHw returns to %s\n", CallerName());
349  return;
350}
351
352/*************************************************************************/
353/**********************        INITIALIZATION        *********************/
354/*************************************************************************/
355
356/* The Init operation (the Init-task) */
357rtems_task Init(rtems_task_argument ignored)
358{
359  rtems_status_code status;
360#if defined(TEST_USE_ISR)
361  rtems_isr_entry   DummyIsr;
362#endif
363  int i;
364
365  puts( "\n\n*** TEST 35 ***" );
366
367  /* Create synchronisation semaphore for LocalHwIsr -> Test Tasks */
368  status = rtems_semaphore_create(
369    rtems_build_name ('S', 'Y', 'N', 'C'),           /* name */
370    0,                                               /* initial count = 0 */
371    RTEMS_LOCAL                   |
372    RTEMS_SIMPLE_BINARY_SEMAPHORE |
373    RTEMS_NO_INHERIT_PRIORITY     |
374    RTEMS_NO_PRIORITY_CEILING     |
375    RTEMS_FIFO,
376    0,
377    &LocalHwSync_S);                                 /* *id */
378  directive_failed( status, "rtems_semaphore_create (SYNC)" );
379
380  printf( "Sync Mutex Id = 0x%08" PRIxrtems_id "\n", LocalHwSync_S );
381
382  /* Create resource semaphore for exclusive access to the local HW */
383  status = rtems_semaphore_create(
384    rtems_build_name ('R', 'E', 'S', '1'), /* name             */
385    1,                                     /* count            */
386    RTEMS_PRIORITY         |
387    RTEMS_BINARY_SEMAPHORE |
388    RTEMS_INHERIT_PRIORITY |
389    RTEMS_LOCAL,                           /* attribute_set    */
390    1, /* insignificant */                 /* priority_ceiling */
391    &LocalHwAccess_R);                     /* *id              */
392  directive_failed( status, "rtems_semaphore_create (RES1)" );
393
394  printf( "Local Mutex Id = 0x%08" PRIxrtems_id "\n", LocalHwAccess_R );
395
396  /* Create resource semaphore for exclusive access to the remote HW */
397  status = rtems_semaphore_create(
398    rtems_build_name ('R', 'E', 'S', '2'), /* name             */
399    1,                                     /* count            */
400    RTEMS_PRIORITY         |
401    RTEMS_BINARY_SEMAPHORE |
402    RTEMS_INHERIT_PRIORITY |
403    RTEMS_LOCAL,                           /* attribute_set    */
404    1, /* insignificant */                 /* priority_ceiling */
405    &RemoteHwAccess_R);                    /* *id              */
406  directive_failed( status, "rtems_semaphore_create (RES2)" );
407
408  printf( "Remote Mutex Id = 0x%08" PRIxrtems_id "\n", RemoteHwAccess_R );
409
410#if defined(TEST_USE_ISR)
411  /* Install ISR for HW/SW synchronization, use ta 0x85 which is synchronous */
412  status = rtems_interrupt_catch(LocalHwIsr, 0x85 + 0x100, &DummyIsr);
413  directive_failed( status, "rtems_interrupt_catch" );
414#endif
415
416
417  printf("Ending Init-task\n");
418  /* Create and start all tasks in the test */
419
420  /* -- Medium-prio Test Tasks --- */
421  for (i = 0; i < NofMediumTask_C; i++) {
422#define MEDIUM_PRIORITY ((RTEMS_MAXIMUM_PRIORITY / 2u) + 1u)
423    status = rtems_task_create(
424      rtems_build_name('M','E','D','0'+i),               /* Name */
425      MEDIUM_PRIORITY,                                   /* Priority */
426      RTEMS_MINIMUM_STACK_SIZE*2,                        /* Stack size (8KB) */
427      RTEMS_DEFAULT_MODES | RTEMS_NO_ASR,                /* Mode */
428      RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,   /* Attributes */
429      &TaMedium[i]);                                     /* Assigned ID */
430    directive_failed( status, "rtems_task_create (MEDn)" );
431
432    printf( "TaMedium[%d] Id = 0x%08" PRIxrtems_id "\n", i, TaMedium[i] );
433    status = rtems_task_start(
434      TaMedium[i],
435      Medium_Exec,
436      (rtems_task_argument) i
437    );
438    directive_failed( status, "rtems_task_start (MEDn)" );
439  }
440
441  /* -- High-prio Test Task --- */
442#define HIGH_PRIORITY ((RTEMS_MAXIMUM_PRIORITY / 2u))
443  status = rtems_task_create(
444    rtems_build_name('H','I','G','H'),                 /* Name */
445    HIGH_PRIORITY,                                     /* Priority */
446    RTEMS_MINIMUM_STACK_SIZE*2,                        /* Stack size (8KB) */
447    RTEMS_DEFAULT_MODES | RTEMS_NO_ASR,                /* Mode */
448    RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,   /* Attributes */
449    &TaHigh);                                          /* Assigned ID */
450  directive_failed( status, "rtems_task_create (HIGH)" );
451
452  printf( "TaHigh Id = 0x%08" PRIxrtems_id "\n", TaHigh );
453  status = rtems_task_start(TaHigh, High_Exec, 0);
454  directive_failed( status, "rtems_task_start (HIGH)" );
455
456  /* -- Low-prio Test Task --- */
457#define LOW_PRIORITY (RTEMS_MAXIMUM_PRIORITY - 1u)
458  status = rtems_task_create(
459    rtems_build_name('L','O','W',' '),                 /* Name */
460    LOW_PRIORITY,                                      /* Priority */
461    RTEMS_MINIMUM_STACK_SIZE*2,                        /* Stack size (8KB) */
462    RTEMS_DEFAULT_MODES | RTEMS_NO_ASR,                /* Mode */
463    RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,   /* Attributes */
464    &TaLow);                                           /* Assigned ID */
465  directive_failed( status, "rtems_task_create (LOW)" );
466
467  printf( "TaLow Id = 0x%08" PRIxrtems_id "\n", TaLow );
468  status = rtems_task_start(TaLow, Low_Exec, 0);
469  directive_failed( status, "rtems_task_start (LOW)" );
470
471  /* -- HW Simulator Task --- */
472#define HWTASK_PRIORITY (RTEMS_MAXIMUM_PRIORITY - 2u)
473  status = rtems_task_create(
474    rtems_build_name('H','W','S','M'),                 /* Name */
475    HWTASK_PRIORITY,                                   /* Priority */
476    RTEMS_MINIMUM_STACK_SIZE*2,                        /* Stack size (8KB) */
477    RTEMS_DEFAULT_MODES | RTEMS_NO_ASR,                /* Mode */
478    RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,   /* Attributes */
479    &TaHwSim);                                         /* Assigned ID */
480  directive_failed( status, "rtems_task_create (HWSM)" );
481
482  printf( "TaHwSim Id = 0x%08" PRIxrtems_id "\n", TaHwSim );
483
484  status = rtems_task_start(TaHwSim, LocalHwSim_Exec, 0);
485  directive_failed( status, "rtems_task_start (HWSM)" );
486
487  /* Destroy the Init task (and let the ready tasks start running) */
488  rtems_task_delete(RTEMS_SELF);
489}
490
491/* configuration information */
492
493#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
494#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
495
496#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
497
498#define CONFIGURE_EXTRA_TASK_STACKS (RTEMS_MINIMUM_STACK_SIZE * 3)
499
500#define CONFIGURE_MAXIMUM_TASKS 10
501#define CONFIGURE_MAXIMUM_SEMAPHORES 10
502
503#include <rtems/confdefs.h>
504
505/* end of file */
Note: See TracBrowser for help on using the repository browser.