source: rtems/testsuites/sptests/sp42/init.c @ 93f158f

5
Last change on this file since 93f158f was 3ad5f86, checked in by Sebastian Huber <sebastian.huber@…>, on 06/03/16 at 06:15:21

rtems: Fix no protocol mutex release

The Classic binary semaphores without a locking protocol
(RTEMS_BINARY_SEMAPHORE) could be released by everyone, e.g. in contrast
to the POSIX mutexes (all variants) or the Classic binary semphores with
priority inheritance or ceiling, there was no owner check in the release
path.

This behaviour was a bit unexpected and not documented. Add an owner
check to the release path. Update sptests/sp42 accordingly.

This change has nothing to do with the simple binary semaphores
(RTEMS_SIMPLE_BINARY_SEMAPHORE) which have no owner at all.

Update #2725

  • Property mode set to 100644
File size: 6.8 KB
Line 
1/*
2 *  Exercise thread queue enqueue and dequeue priority
3 *
4 *  COPYRIGHT (c) 1989-2009.
5 *  On-Line Applications Research Corporation (OAR).
6 *
7 *  The license and distribution terms for this file may be
8 *  found in the file LICENSE in this distribution or at
9 *  http://www.rtems.org/license/LICENSE.
10 */
11
12#ifdef HAVE_CONFIG_H
13#include "config.h"
14#endif
15
16#include <stdio.h>
17#include <stdlib.h>
18
19#include <bsp.h>
20
21#include "tmacros.h"
22
23const char rtems_test_name[] = "SP 42";
24
25#define MAX_TASKS 20
26
27/*
28 * Carefully chosen to exercise threadq enqueue/dequeue priority logic.
29 * Somewhat randomly sorted to ensure than if discipline is FIFO, run-time
30 * behavior won't be the same when released.
31 */
32static const rtems_task_priority Priorities_High[MAX_TASKS] = {
33  37, 37, 37, 37,       /* backward - more 2-n */
34  2, 2, 2, 2,           /* forward - multiple are on 2-n chain */
35  4, 3,                 /* forward - search forward arbitrary */
36  3, 3, 3, 3,           /* forward - more 2-n */
37  38, 37,               /* backward - search backward arbitrary */
38  34, 34, 34, 34,       /* backward - multple on 2-n chain */
39};
40
41static const rtems_task_priority Priorities_Low[MAX_TASKS] = {
42  13, 13, 13, 13,       /* backward - more 2-n */
43  2, 2, 2, 2,           /* forward - multiple are on 2-n chain */
44  4, 3,                 /* forward - search forward arbitrary */
45  3, 3, 3, 3,           /* forward - more 2-n */
46  14, 13,               /* backward - search backward arbitrary */
47  12, 12, 12, 12,       /* backward - multple on 2-n chain */
48};
49
50static const int Obtain_order[2][MAX_TASKS] = {
51  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 },
52  { 4, 5, 6, 7, 9, 10, 11, 12, 13, 8, 16, 17, 18, 19, 0, 1, 2, 3, 15, 14 }
53};
54
55static const rtems_task_priority *Priorities;
56
57static rtems_id   Semaphore;
58static rtems_id   Master;
59static rtems_id   Task_id[ MAX_TASKS ];
60static rtems_name Task_name[ MAX_TASKS ];
61
62static rtems_task_argument Obtain_counter;
63
64static enum {
65 FIFO,
66 PRIORITY
67} Variant;
68
69static rtems_task Locker_task(
70  rtems_task_argument task_index
71)
72{
73  rtems_id            tid;
74  rtems_status_code   status;
75  rtems_task_argument my_obtain_counter;
76
77  status = rtems_task_ident( RTEMS_SELF, RTEMS_SEARCH_ALL_NODES, &tid );
78  directive_failed( status, "rtems_task_ident" );
79
80  rtems_test_assert( task_index == task_number( tid ) - 1 );
81
82  status = rtems_semaphore_obtain( Semaphore, RTEMS_DEFAULT_OPTIONS, 0 );
83  directive_failed( status, "rtems_semaphore_obtain" );
84
85  put_name( Task_name[ task_index ], FALSE );
86  puts( " - unblocked - OK" );
87
88  status = rtems_task_wake_after( 10 );
89  directive_failed( status, "rtems_task_wake_after" );
90
91  my_obtain_counter = Obtain_counter;
92  rtems_test_assert( task_index == Obtain_order[ Variant ][ Obtain_counter ] );
93  ++Obtain_counter;
94
95  status = rtems_semaphore_release( Semaphore );
96  directive_failed( status, "rtems_semaphore_release" );
97
98  if ( my_obtain_counter == MAX_TASKS - 1 ) {
99    status = rtems_event_transient_send( Master );
100    directive_failed( status, "rtems_event_transient_send" );
101  }
102
103  (void) rtems_task_delete( RTEMS_SELF );
104}
105
106static void do_test(
107  rtems_attribute attr,
108  bool            extract  /* TRUE if extract, not release */
109)
110{
111  rtems_status_code   status;
112  rtems_task_argument i;
113
114  Variant = ( ( attr & RTEMS_PRIORITY ) != 0 ? PRIORITY : FIFO );
115  Obtain_counter = 0;
116
117  status = rtems_semaphore_create(
118    rtems_build_name( 'S', 'E', 'M', '0' ),  /* name = SEM0 */
119    0,                                       /* locked */
120    RTEMS_BINARY_SEMAPHORE | attr,           /* mutex w/desired discipline */
121    0,                                       /* IGNORED */
122    &Semaphore
123  );
124  directive_failed( status, "rtems_semaphore_create" );
125
126  for (i = 0 ; i < MAX_TASKS ; i++ ) {
127    Task_name[ i ] = rtems_build_name(
128       'T',
129       'A',
130       '0' + (char)(i/10),
131       '0' + (char)(i%10)
132    );
133
134    status = rtems_task_create(
135      Task_name[ i ],
136      Priorities[ i ],
137      RTEMS_MINIMUM_STACK_SIZE,
138      RTEMS_DEFAULT_MODES,
139      RTEMS_DEFAULT_ATTRIBUTES,
140      &Task_id[ i ]
141    );
142    directive_failed( status, "rtems_task_create" );
143
144    status = rtems_task_start( Task_id[ i ], Locker_task, i );
145    directive_failed( status, "rtems_task_start" );
146  }
147
148  if ( extract ) {
149    for (i = 0 ; i< MAX_TASKS ; i++ ) {
150      status = rtems_task_delete( Task_id[ i ]  );
151      directive_failed( status, "rtems_task_delete" );
152    }
153  }
154
155  /* do the initial release */
156  status = rtems_semaphore_release( Semaphore );
157  directive_failed( status, "rtems_semaphore_release" );
158
159  if ( !extract ) {
160    status = rtems_event_transient_receive( RTEMS_WAIT, RTEMS_NO_TIMEOUT );
161    directive_failed( status, "rtems_event_transient_receive" );
162  }
163
164  /* now delete the semaphore since no one is waiting and it is unlocked */
165  status = rtems_semaphore_delete( Semaphore );
166  directive_failed( status, "rtems_semaphore_delete" );
167}
168
169static rtems_task Init(
170  rtems_task_argument argument
171)
172{
173  rtems_task_priority prio;
174  rtems_status_code status;
175
176  TEST_BEGIN();
177
178  Master = rtems_task_self();
179
180  if (RTEMS_MAXIMUM_PRIORITY == 255)
181    Priorities = Priorities_High;
182  else if (RTEMS_MAXIMUM_PRIORITY == 15)
183    Priorities = Priorities_Low;
184  else {
185    puts( "Test only supports 256 or 16 configured priority levels" );
186    rtems_test_exit( 0 );
187  }
188
189  prio = RTEMS_MAXIMUM_PRIORITY - 1;
190  status = rtems_task_set_priority(RTEMS_SELF, prio, &prio);
191  directive_failed( status, "rtems_task_set_priority" );
192
193  if ( sizeof(Priorities_Low) / sizeof(rtems_task_priority) != MAX_TASKS ) {
194    puts( "Priorities_Low table does not have right number of entries" );
195    rtems_test_exit( 0 );
196  }
197
198  if ( sizeof(Priorities_High) / sizeof(rtems_task_priority) != MAX_TASKS ) {
199    puts( "Priorities_High table does not have right number of entries" );
200    rtems_test_exit( 0 );
201  }
202
203  puts( "Exercising blocking discipline w/extract in FIFO order " );
204  do_test( RTEMS_FIFO, TRUE );
205
206  puts( "Exercising blocking discipline w/unblock in FIFO order" );
207  do_test( RTEMS_FIFO, FALSE );
208
209  rtems_test_pause_and_screen_number( 2 );
210
211  puts( "Exercising blocking discipline w/extract in priority order " );
212  do_test( RTEMS_PRIORITY, TRUE );
213
214  puts( "Exercising blocking discipline w/unblock in priority order" );
215  do_test( RTEMS_PRIORITY, FALSE );
216
217  TEST_END();
218  rtems_test_exit(0);
219}
220
221/**************** START OF CONFIGURATION INFORMATION ****************/
222
223#define CONFIGURE_INIT
224
225#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
226#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
227
228#define CONFIGURE_MAXIMUM_TASKS             MAX_TASKS+1
229#define CONFIGURE_MAXIMUM_SEMAPHORES        1
230
231#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES
232
233#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
234
235#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
236
237#include <rtems/confdefs.h>
238
239/****************  END OF CONFIGURATION INFORMATION  ****************/
240
Note: See TracBrowser for help on using the repository browser.