source: rtems/cpukit/score/src/coremutexsurrender.c @ 500a8e9c

5
Last change on this file since 500a8e9c was 500a8e9c, checked in by Sebastian Huber <sebastian.huber@…>, on 04/28/16 at 04:26:01

score: Delete RTEMS_STRICT_ORDER_MUTEX

Remove support for strict order mutexes.

Close #2124.

  • Property mode set to 100644
File size: 5.3 KB
Line 
1/**
2 * @file
3 *
4 * @brief Surrender the Mutex
5 * @ingroup ScoreMutex
6 */
7
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.org/license/LICENSE.
15 */
16
17#if HAVE_CONFIG_H
18#include "config.h"
19#endif
20
21#include <rtems/system.h>
22#include <rtems/score/isr.h>
23#include <rtems/score/coremuteximpl.h>
24#include <rtems/score/thread.h>
25
26CORE_mutex_Status _CORE_mutex_Do_surrender(
27  CORE_mutex_Control      *the_mutex,
28#if defined(RTEMS_MULTIPROCESSING)
29  Thread_queue_MP_callout  mp_callout,
30  Objects_Id               mp_id,
31#endif
32  ISR_lock_Context        *lock_context
33)
34{
35  Thread_Control *the_thread;
36  Thread_Control *holder;
37
38  holder = the_mutex->holder;
39
40  /*
41   *  The following code allows a thread (or ISR) other than the thread
42   *  which acquired the mutex to release that mutex.  This is only
43   *  allowed when the mutex in quetion is FIFO or simple Priority
44   *  discipline.  But Priority Ceiling or Priority Inheritance mutexes
45   *  must be released by the thread which acquired them.
46   */
47
48  if ( the_mutex->Attributes.only_owner_release ) {
49    if ( !_Thread_Is_executing( holder ) ) {
50      _ISR_lock_ISR_enable( lock_context );
51      return CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE;
52    }
53  }
54
55  _Thread_queue_Acquire_critical( &the_mutex->Wait_queue, lock_context );
56
57  /* XXX already unlocked -- not right status */
58
59  if ( !the_mutex->nest_count ) {
60    _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
61    return CORE_MUTEX_STATUS_SUCCESSFUL;
62  }
63
64  the_mutex->nest_count--;
65
66  if ( the_mutex->nest_count != 0 ) {
67    /*
68     *  All error checking is on the locking side, so if the lock was
69     *  allowed to acquired multiple times, then we should just deal with
70     *  that.  The RTEMS_DEBUG is just a validation.
71     */
72    #if defined(RTEMS_DEBUG)
73      switch ( the_mutex->Attributes.lock_nesting_behavior ) {
74        case CORE_MUTEX_NESTING_ACQUIRES:
75          _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
76          return CORE_MUTEX_STATUS_SUCCESSFUL;
77        #if defined(RTEMS_POSIX_API)
78          case CORE_MUTEX_NESTING_IS_ERROR:
79            /* should never occur */
80            _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
81            return CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED;
82        #endif
83        case CORE_MUTEX_NESTING_BLOCKS:
84          /* Currently no API exercises this behavior. */
85          break;
86      }
87    #else
88      _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
89      /* must be CORE_MUTEX_NESTING_ACQUIRES or we wouldn't be here */
90      return CORE_MUTEX_STATUS_SUCCESSFUL;
91    #endif
92  }
93
94  /*
95   *  Formally release the mutex before possibly transferring it to a
96   *  blocked thread.
97   */
98  if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ||
99       _CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) ) {
100    holder->resource_count--;
101  }
102  the_mutex->holder = NULL;
103
104  /*
105   *  Now we check if another thread was waiting for this mutex.  If so,
106   *  transfer the mutex to that thread.
107   */
108  if (
109    ( the_thread = _Thread_queue_First_locked(
110        &the_mutex->Wait_queue,
111        the_mutex->operations
112      )
113    )
114  ) {
115    bool unblock;
116
117    the_mutex->holder     = the_thread;
118    the_mutex->nest_count = 1;
119
120    /*
121     * We must extract the thread now since this will restore its default
122     * thread lock.  This is necessary to avoid a deadlock in the
123     * _Thread_Change_priority() below due to a recursive thread queue lock
124     * acquire.
125     */
126    unblock = _Thread_queue_Extract_locked(
127      &the_mutex->Wait_queue.Queue,
128      the_mutex->operations,
129      the_thread,
130      mp_callout,
131      mp_id
132    );
133
134#if defined(RTEMS_MULTIPROCESSING)
135    if ( _Objects_Is_local_id( the_thread->Object.id ) )
136#endif
137    {
138      switch ( the_mutex->Attributes.discipline ) {
139        case CORE_MUTEX_DISCIPLINES_FIFO:
140        case CORE_MUTEX_DISCIPLINES_PRIORITY:
141          break;
142        case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT:
143          the_thread->resource_count++;
144          _Thread_queue_Boost_priority( &the_mutex->Wait_queue.Queue, the_thread );
145          break;
146        case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING:
147          the_thread->resource_count++;
148          _Thread_Raise_priority(
149            the_thread,
150            the_mutex->Attributes.priority_ceiling
151          );
152          break;
153      }
154    }
155
156    _Thread_queue_Unblock_critical(
157      unblock,
158      &the_mutex->Wait_queue.Queue,
159      the_thread,
160      mp_callout,
161      mp_id,
162      lock_context
163    );
164  } else {
165    _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
166  }
167
168  /*
169   *  Whether or not someone is waiting for the mutex, an
170   *  inherited priority must be lowered if this is the last
171   *  mutex (i.e. resource) this task has.
172   */
173  if ( !_Thread_Owns_resources( holder ) ) {
174    /*
175     * Ensure that the holder resource count is visible to all other processors
176     * and that we read the latest priority restore hint.
177     */
178    _Atomic_Fence( ATOMIC_ORDER_ACQ_REL );
179
180    if ( holder->priority_restore_hint ) {
181      Per_CPU_Control *cpu_self;
182
183      cpu_self = _Thread_Dispatch_disable();
184      _Thread_Restore_priority( holder );
185      _Thread_Dispatch_enable( cpu_self );
186    }
187  }
188
189  return CORE_MUTEX_STATUS_SUCCESSFUL;
190}
Note: See TracBrowser for help on using the repository browser.