source: rtems/cpukit/score/src/coremutexsurrender.c @ bd029d87

4.8
Last change on this file since bd029d87 was 96d0b64, checked in by Joel Sherrill <joel.sherrill@…>, on 03/05/07 at 21:01:40

2007-03-05 Joel Sherrill <joel@…>

PR 1222/cpukit

  • score/Makefile.am, score/include/rtems/score/coremutex.h, score/include/rtems/score/threadq.h, score/inline/rtems/score/coremutex.inl, score/src/coremsgsubmit.c, score/src/coremutexsurrender.c, score/src/threadchangepriority.c, score/src/threadclearstate.c, score/src/threadhandler.c, score/src/threadinitialize.c, score/src/threadqdequeuefifo.c, score/src/threadqdequeuepriority.c, score/src/threadqenqueue.c, score/src/threadqenqueuefifo.c, score/src/threadqenqueuepriority.c, score/src/threadqextractfifo.c, score/src/threadqextractpriority.c, score/src/threadsetstate.c: Enhance so that when the prioirity of a thread that is blocked on a priority based thread queue is changed, that its placement in the queue is reevaluated based upon the new priority. This enhancement includes modifications to the SuperCore? as well as new test cases.
  • score/src/threadqrequeue.c: New file.
  • Property mode set to 100644
File size: 4.7 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-2006.
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 *  $Id$
17 */
18
19#if HAVE_CONFIG_H
20#include "config.h"
21#endif
22
23#include <rtems/system.h>
24#include <rtems/score/isr.h>
25#include <rtems/score/coremutex.h>
26#include <rtems/score/states.h>
27#include <rtems/score/thread.h>
28#include <rtems/score/threadq.h>
29
30/*
31 *  _CORE_mutex_Surrender
32 *
33 *  DESCRIPTION:
34 *
35 *  This routine frees a unit to the mutex.  If a task was blocked waiting for
36 *  a unit from this mutex, then that task will be readied and the unit
37 *  given to that task.  Otherwise, the unit will be returned to the mutex.
38 *
39 *  Input parameters:
40 *    the_mutex            - the mutex to be flushed
41 *    id                   - id of parent mutex
42 *    api_mutex_mp_support - api dependent MP support actions
43 *
44 *  Output parameters:
45 *    CORE_MUTEX_STATUS_SUCCESSFUL - if successful
46 *    core error code              - if unsuccessful
47 */
48
49CORE_mutex_Status _CORE_mutex_Surrender(
50  CORE_mutex_Control                *the_mutex,
51  Objects_Id                         id,
52  CORE_mutex_API_mp_support_callout  api_mutex_mp_support
53)
54{
55  Thread_Control *the_thread;
56  Thread_Control *holder;
57
58  holder    = the_mutex->holder;
59
60  /*
61   *  The following code allows a thread (or ISR) other than the thread
62   *  which acquired the mutex to release that mutex.  This is only
63   *  allowed when the mutex in quetion is FIFO or simple Priority
64   *  discipline.  But Priority Ceiling or Priority Inheritance mutexes
65   *  must be released by the thread which acquired them.
66   */
67
68  if ( the_mutex->Attributes.only_owner_release ) {
69    if ( !_Thread_Is_executing( holder ) )
70      return CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE;
71  }
72
73  /* XXX already unlocked -- not right status */
74
75  if ( !the_mutex->nest_count )
76    return CORE_MUTEX_STATUS_SUCCESSFUL;
77
78  the_mutex->nest_count--;
79
80  if ( the_mutex->nest_count != 0 ) {
81    switch ( the_mutex->Attributes.lock_nesting_behavior ) {
82      case CORE_MUTEX_NESTING_ACQUIRES:
83        return CORE_MUTEX_STATUS_SUCCESSFUL;
84      case CORE_MUTEX_NESTING_IS_ERROR:
85        /* should never occur */
86        return CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED;
87      case CORE_MUTEX_NESTING_BLOCKS:
88        /* Currently no API exercises this behavior. */
89        break;
90    }
91  }
92
93  /*
94   *  Formally release the mutex before possibly transferring it to a
95   *  blocked thread.
96   */
97  if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ||
98       _CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) )
99    holder->resource_count--;
100  the_mutex->holder    = NULL;
101  the_mutex->holder_id = 0;
102
103  /*
104   *  Whether or not someone is waiting for the mutex, an
105   *  inherited priority must be lowered if this is the last
106   *  mutex (i.e. resource) this task has.
107   */
108  if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ||
109       _CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) ) {
110    if ( holder->resource_count == 0 &&
111         holder->real_priority != holder->current_priority ) {
112      _Thread_Change_priority( holder, holder->real_priority, TRUE );
113    }
114  }
115
116  /*
117   *  Now we check if another thread was waiting for this mutex.  If so,
118   *  transfer the mutex to that thread.
119   */
120  if ( ( the_thread = _Thread_queue_Dequeue( &the_mutex->Wait_queue ) ) ) {
121
122#if defined(RTEMS_MULTIPROCESSING)
123    if ( !_Objects_Is_local_id( the_thread->Object.id ) ) {
124
125      the_mutex->holder     = NULL;
126      the_mutex->holder_id  = the_thread->Object.id;
127      the_mutex->nest_count = 1;
128
129      ( *api_mutex_mp_support)( the_thread, id );
130
131    } else
132#endif
133    {
134
135      the_mutex->holder     = the_thread;
136      the_mutex->holder_id  = the_thread->Object.id;
137      the_mutex->nest_count = 1;
138
139      switch ( the_mutex->Attributes.discipline ) {
140        case CORE_MUTEX_DISCIPLINES_FIFO:
141        case CORE_MUTEX_DISCIPLINES_PRIORITY:
142          break;
143        case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT:
144          the_thread->resource_count++;
145          break;
146        case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING:
147          the_thread->resource_count++;
148          if (the_mutex->Attributes.priority_ceiling <
149              the_thread->current_priority){
150              _Thread_Change_priority(
151                the_thread,
152                the_mutex->Attributes.priority_ceiling,
153                FALSE
154              );
155          }
156          break;
157      }
158    }
159  } else
160    the_mutex->lock = CORE_MUTEX_UNLOCKED;
161
162  return CORE_MUTEX_STATUS_SUCCESSFUL;
163}
Note: See TracBrowser for help on using the repository browser.