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

5
Last change on this file since c3d8d9e was c3d8d9e, checked in by Sebastian Huber <sebastian.huber@…>, on 05/23/16 at 04:55:49

score: Get rid of mp_id parameter

Get rid of the mp_id parameter used for some thread queue methods. Use
THREAD_QUEUE_QUEUE_TO_OBJECT() instead.

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