source: rtems/c/src/exec/score/src/coremutex.c @ f926b34

4.104.114.84.95
Last change on this file since f926b34 was f926b34, checked in by Joel Sherrill <joel.sherrill@…>, on 03/08/97 at 03:51:55

Modified calls to _Thread_Change_priority to take a third argument. The new
argument indicates whether the task is to be placed at the head or tail of
its priority fifo when it is lowering its own priority. POSIX normally
follows the RTEMS API conventions but GNAT expects that all lowering of
a task's priority by the task itself will result in being placed at the
head of the priority FIFO. Normally, this would only occur as the result
of lose of inherited priority.

  • Property mode set to 100644
File size: 9.4 KB
Line 
1/*
2 *  Mutex Handler
3 *
4 *  DESCRIPTION:
5 *
6 *  This package is the implementation of the Mutex Handler.
7 *  This handler provides synchronization and mutual exclusion capabilities.
8 *
9 *  COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
10 *  On-Line Applications Research Corporation (OAR).
11 *  All rights assigned to U.S. Government, 1994.
12 *
13 *  This material may be reproduced by or for the U.S. Government pursuant
14 *  to the copyright license under the clause at DFARS 252.227-7013.  This
15 *  notice must appear in all copies of this file and its derivatives.
16 *
17 *  $Id$
18 */
19
20#include <rtems/system.h>
21#include <rtems/score/isr.h>
22#include <rtems/score/coremutex.h>
23#include <rtems/score/states.h>
24#include <rtems/score/thread.h>
25#include <rtems/score/threadq.h>
26
27/*PAGE
28 *
29 *  _CORE_mutex_Initialize
30 *
31 *  This routine initializes a mutex at create time and set the control
32 *  structure according to the values passed.
33 *
34 *  Input parameters:
35 *    the_mutex             - the mutex control block to initialize
36 *    the_class             - the API class of the object
37 *    the_mutex_attributes  - the mutex attributes specified at create time
38 *    initial_lock          - mutex initial lock or unlocked status
39 *    proxy_extract_callout - MP specific extract callout
40 *
41 *  Output parameters:  NONE
42 */
43
44void _CORE_mutex_Initialize(
45  CORE_mutex_Control           *the_mutex,
46  Objects_Classes               the_class,
47  CORE_mutex_Attributes        *the_mutex_attributes,
48  unsigned32                    initial_lock,
49  Thread_queue_Extract_callout  proxy_extract_callout
50)
51{
52
53/* Add this to the RTEMS environment later ?????????
54  rtems_assert( initial_lock == CORE_MUTEX_LOCKED ||
55                initial_lock == CORE_MUTEX_UNLOCKED );
56 */
57
58  the_mutex->Attributes = *the_mutex_attributes;
59  the_mutex->lock          = initial_lock;
60
61  if ( initial_lock == CORE_MUTEX_LOCKED ) {
62    the_mutex->nest_count = 1;
63    the_mutex->holder     = _Thread_Executing;
64    the_mutex->holder_id  = _Thread_Executing->Object.id;
65    _Thread_Executing->resource_count++;
66  } else {
67    the_mutex->nest_count = 0;
68    the_mutex->holder     = NULL;
69    the_mutex->holder_id  = 0;
70  }
71
72  _Thread_queue_Initialize(
73    &the_mutex->Wait_queue,
74    the_class,
75    _CORE_mutex_Is_fifo( the_mutex_attributes ) ?
76      THREAD_QUEUE_DISCIPLINE_FIFO : THREAD_QUEUE_DISCIPLINE_PRIORITY,
77    STATES_WAITING_FOR_MUTEX,
78    proxy_extract_callout,
79    CORE_MUTEX_TIMEOUT
80  );
81}
82
83/*PAGE
84 *
85 *  _CORE_mutex_Seize
86 *
87 *  This routine attempts to allocate a mutex to the calling thread.
88 *
89 *  Input parameters:
90 *    the_mutex - pointer to mutex control block
91 *    id        - id of object to wait on
92 *    wait      - TRUE if wait is allowed, FALSE otherwise
93 *    timeout   - number of ticks to wait (0 means forever)
94 *
95 *  Output parameters:  NONE
96 *
97 *  INTERRUPT LATENCY:
98 *    available
99 *    wait
100 */
101
102void _CORE_mutex_Seize(
103  CORE_mutex_Control  *the_mutex,
104  Objects_Id           id,
105  boolean              wait,
106  Watchdog_Interval    timeout
107)
108{
109  Thread_Control *executing;
110  ISR_Level       level;
111
112  executing = _Thread_Executing;
113  switch ( the_mutex->Attributes.discipline ) {
114    case CORE_MUTEX_DISCIPLINES_FIFO:
115    case CORE_MUTEX_DISCIPLINES_PRIORITY:
116    case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT:
117      break;
118    case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING:
119      if ( executing->current_priority <
120                              the_mutex->Attributes.priority_ceiling) {
121        executing->Wait.return_code = CORE_MUTEX_STATUS_CEILING_VIOLATED;
122        return;
123      }
124  }
125  executing->Wait.return_code = CORE_MUTEX_STATUS_SUCCESSFUL;
126  _ISR_Disable( level );
127  if ( ! _CORE_mutex_Is_locked( the_mutex ) ) {
128    the_mutex->lock       = CORE_MUTEX_LOCKED;
129    the_mutex->holder     = executing;
130    the_mutex->holder_id  = executing->Object.id;
131    the_mutex->nest_count = 1;
132    executing->resource_count++;
133    _ISR_Enable( level );
134    switch ( the_mutex->Attributes.discipline ) {
135      case CORE_MUTEX_DISCIPLINES_FIFO:
136      case CORE_MUTEX_DISCIPLINES_PRIORITY:
137      case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT:
138        /* already the highest priority */
139        break;
140      case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING:
141      if ( the_mutex->Attributes.priority_ceiling <
142                                           executing->current_priority ) {
143        _Thread_Change_priority(
144          the_mutex->holder,
145          the_mutex->Attributes.priority_ceiling,
146          FALSE
147        );
148      }
149    }
150    return;
151  }
152
153  if ( _Objects_Are_ids_equal(
154              _Thread_Executing->Object.id, the_mutex->holder_id ) ) {
155    if ( _CORE_mutex_Is_nesting_allowed( &the_mutex->Attributes ) )
156      the_mutex->nest_count++;
157    else
158      executing->Wait.return_code = CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED;
159
160    _ISR_Enable( level );
161    return;
162  }
163
164  if ( !wait ) {
165    _ISR_Enable( level );
166    executing->Wait.return_code = CORE_MUTEX_STATUS_UNSATISFIED_NOWAIT;
167    return;
168  }
169
170  _Thread_queue_Enter_critical_section( &the_mutex->Wait_queue );
171  executing->Wait.queue = &the_mutex->Wait_queue;
172  executing->Wait.id    = id;
173  _ISR_Enable( level );
174
175  switch ( the_mutex->Attributes.discipline ) {
176    case CORE_MUTEX_DISCIPLINES_FIFO:
177    case CORE_MUTEX_DISCIPLINES_PRIORITY:
178    case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING:
179      break;
180    case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT:
181      if ( the_mutex->holder->current_priority > executing->current_priority ) {
182        _Thread_Change_priority(
183          the_mutex->holder,
184          executing->current_priority,
185          FALSE
186        );
187      }
188      break;
189  }
190
191  _Thread_queue_Enqueue( &the_mutex->Wait_queue, timeout );
192
193  if ( _Thread_Executing->Wait.return_code == CORE_MUTEX_STATUS_SUCCESSFUL ) {
194    switch ( the_mutex->Attributes.discipline ) {
195      case CORE_MUTEX_DISCIPLINES_FIFO:
196      case CORE_MUTEX_DISCIPLINES_PRIORITY:
197      case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT:
198        break;
199      case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING:
200        if ( the_mutex->Attributes.priority_ceiling <
201                                           executing->current_priority ) {
202          _Thread_Change_priority(
203            executing,
204            the_mutex->Attributes.priority_ceiling,
205            FALSE
206          );
207        };
208        break;
209    }
210  }
211}
212
213/*
214 *  _CORE_mutex_Surrender
215 *
216 *  DESCRIPTION:
217 *
218 *  This routine frees a unit to the mutex.  If a task was blocked waiting for
219 *  a unit from this mutex, then that task will be readied and the unit
220 *  given to that task.  Otherwise, the unit will be returned to the mutex.
221 *
222 *  Input parameters:
223 *    the_mutex            - the mutex to be flushed
224 *    id                   - id of parent mutex
225 *    api_mutex_mp_support - api dependent MP support actions
226 *
227 *  Output parameters:
228 *    CORE_MUTEX_STATUS_SUCCESSFUL - if successful
229 *    core error code              - if unsuccessful
230 */
231
232CORE_mutex_Status _CORE_mutex_Surrender(
233  CORE_mutex_Control                *the_mutex,
234  Objects_Id                         id,
235  CORE_mutex_API_mp_support_callout  api_mutex_mp_support
236)
237{
238  Thread_Control *the_thread;
239  Thread_Control *executing;
240
241  executing = _Thread_Executing;
242
243  if ( !_Objects_Are_ids_equal(
244           _Thread_Executing->Object.id, the_mutex->holder_id ) )
245    return( CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE );
246
247  the_mutex->nest_count--;
248
249  if ( the_mutex->nest_count != 0 )
250    return( CORE_MUTEX_STATUS_SUCCESSFUL );
251
252  _Thread_Executing->resource_count--;
253  the_mutex->holder    = NULL;
254  the_mutex->holder_id = 0;
255
256  /*
257   *  Whether or not someone is waiting for the mutex, an
258   *  inherited priority must be lowered if this is the last
259   *  mutex (i.e. resource) this task has.
260   */
261
262  switch ( the_mutex->Attributes.discipline ) {
263    case CORE_MUTEX_DISCIPLINES_FIFO:
264    case CORE_MUTEX_DISCIPLINES_PRIORITY:
265      break;
266    case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING:
267    case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT:
268      if ( executing->resource_count == 0 &&
269           executing->real_priority != executing->current_priority ) {
270         _Thread_Change_priority( executing, executing->real_priority, TRUE );
271      }
272      break;
273  }
274
275
276  if ( ( the_thread = _Thread_queue_Dequeue( &the_mutex->Wait_queue ) ) ) {
277
278    if ( !_Objects_Is_local_id( the_thread->Object.id ) ) {
279     
280      the_mutex->holder     = NULL;
281      the_mutex->holder_id  = the_thread->Object.id;
282      the_mutex->nest_count = 1;
283
284      ( *api_mutex_mp_support)( the_thread, id );
285
286    } else {
287
288      the_mutex->holder     = the_thread;
289      the_mutex->holder_id  = the_thread->Object.id;
290      the_thread->resource_count++;
291      the_mutex->nest_count = 1;
292
293     /*
294      *  No special action for priority inheritance or priority ceiling
295      *  because the_thread is guaranteed to be the highest priority
296      *  thread waiting for the mutex.
297      */
298    }
299  } else
300    the_mutex->lock = CORE_MUTEX_UNLOCKED;
301
302  return( CORE_MUTEX_STATUS_SUCCESSFUL );
303}
304
305/*PAGE
306 *
307 *  _CORE_mutex_Flush
308 *
309 *  This function a flushes the mutex's task wait queue.
310 *
311 *  Input parameters:
312 *    the_mutex              - the mutex to be flushed
313 *    remote_extract_callout - function to invoke remotely
314 *    status                 - status to pass to thread
315 *
316 *  Output parameters:  NONE
317 */
318
319void _CORE_mutex_Flush(
320  CORE_mutex_Control         *the_mutex,
321  Thread_queue_Flush_callout  remote_extract_callout,
322  unsigned32                  status
323)
324{
325  _Thread_queue_Flush(
326    &the_mutex->Wait_queue,
327    remote_extract_callout,
328    status
329  );
330}
Note: See TracBrowser for help on using the repository browser.