source: rtems/cpukit/score/src/coremutexsurrender.c @ 631b3c8

5
Last change on this file since 631b3c8 was 631b3c8, checked in by Sebastian Huber <sebastian.huber@…>, on 05/23/16 at 09:40:18

score: Move thread queue MP callout to context

Drop the multiprocessing (MP) dependent callout parameter from the
thread queue extract, dequeue, flush and unblock methods. Merge this
parameter with the lock context into new structure Thread_queue_Context.
This helps to gets rid of the conditionally compiled method call
helpers.

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