source: rtems/cpukit/include/rtems/score/coremuteximpl.h @ 4c20da4

Last change on this file since 4c20da4 was 4c20da4, checked in by Sebastian Huber <sebastian.huber@…>, on Apr 4, 2019 at 7:18:11 AM

doxygen: Rename Score* groups in RTEMSScore*

Update #3706

  • Property mode set to 100644
File size: 11.3 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup RTEMSScoreMutex
5 *
6 * @brief CORE Mutex Implementation
7 */
8
9/*
10 *  COPYRIGHT (c) 1989-2009.
11 *  On-Line Applications Research Corporation (OAR).
12 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
15 *  http://www.rtems.org/license/LICENSE.
16 */
17
18#ifndef _RTEMS_SCORE_COREMUTEXIMPL_H
19#define _RTEMS_SCORE_COREMUTEXIMPL_H
20
21#include <rtems/score/coremutex.h>
22#include <rtems/score/chainimpl.h>
23#include <rtems/score/schedulerimpl.h>
24#include <rtems/score/status.h>
25#include <rtems/score/threadimpl.h>
26#include <rtems/score/threadqimpl.h>
27
28#ifdef __cplusplus
29extern "C" {
30#endif
31
32/**
33 * @addtogroup RTEMSScoreMutex
34 */
35/**@{**/
36
37#define CORE_MUTEX_TQ_OPERATIONS &_Thread_queue_Operations_priority
38
39#define CORE_MUTEX_TQ_PRIORITY_INHERIT_OPERATIONS \
40  &_Thread_queue_Operations_priority_inherit
41
42RTEMS_INLINE_ROUTINE void _CORE_mutex_Initialize(
43  CORE_mutex_Control *the_mutex
44)
45{
46  _Thread_queue_Object_initialize( &the_mutex->Wait_queue );
47}
48
49RTEMS_INLINE_ROUTINE void _CORE_mutex_Destroy( CORE_mutex_Control *the_mutex )
50{
51  _Thread_queue_Destroy( &the_mutex->Wait_queue );
52}
53
54RTEMS_INLINE_ROUTINE void _CORE_mutex_Acquire_critical(
55  CORE_mutex_Control   *the_mutex,
56  Thread_queue_Context *queue_context
57)
58{
59  _Thread_queue_Acquire_critical( &the_mutex->Wait_queue, queue_context );
60}
61
62RTEMS_INLINE_ROUTINE void _CORE_mutex_Release(
63  CORE_mutex_Control   *the_mutex,
64  Thread_queue_Context *queue_context
65)
66{
67  _Thread_queue_Release( &the_mutex->Wait_queue, queue_context );
68}
69
70RTEMS_INLINE_ROUTINE Thread_Control *_CORE_mutex_Get_owner(
71  const CORE_mutex_Control *the_mutex
72)
73{
74  return the_mutex->Wait_queue.Queue.owner;
75}
76
77/**
78 * @brief Is mutex locked.
79 *
80 * This routine returns true if the mutex specified is locked and false
81 * otherwise.
82 *
83 * @param[in] the_mutex is the mutex to check.
84 *
85 * @retval true The mutex is locked.
86 * @retval false The mutex is not locked.
87 */
88RTEMS_INLINE_ROUTINE bool _CORE_mutex_Is_locked(
89  const CORE_mutex_Control *the_mutex
90)
91{
92  return _CORE_mutex_Get_owner( the_mutex ) != NULL;
93}
94
95Status_Control _CORE_mutex_Seize_slow(
96  CORE_mutex_Control            *the_mutex,
97  const Thread_queue_Operations *operations,
98  Thread_Control                *executing,
99  bool                           wait,
100  Thread_queue_Context          *queue_context
101);
102
103RTEMS_INLINE_ROUTINE void _CORE_mutex_Set_owner(
104  CORE_mutex_Control *the_mutex,
105  Thread_Control     *owner
106)
107{
108  the_mutex->Wait_queue.Queue.owner = owner;
109}
110
111RTEMS_INLINE_ROUTINE bool _CORE_mutex_Is_owner(
112  const CORE_mutex_Control *the_mutex,
113  const Thread_Control     *the_thread
114)
115{
116  return _CORE_mutex_Get_owner( the_mutex ) == the_thread;
117}
118
119RTEMS_INLINE_ROUTINE void _CORE_recursive_mutex_Initialize(
120  CORE_recursive_mutex_Control *the_mutex
121)
122{
123  _CORE_mutex_Initialize( &the_mutex->Mutex );
124  the_mutex->nest_level = 0;
125}
126
127RTEMS_INLINE_ROUTINE Status_Control _CORE_recursive_mutex_Seize_nested(
128  CORE_recursive_mutex_Control *the_mutex
129)
130{
131  ++the_mutex->nest_level;
132  return STATUS_SUCCESSFUL;
133}
134
135RTEMS_INLINE_ROUTINE Status_Control _CORE_recursive_mutex_Seize(
136  CORE_recursive_mutex_Control  *the_mutex,
137  const Thread_queue_Operations *operations,
138  Thread_Control                *executing,
139  bool                           wait,
140  Status_Control              ( *nested )( CORE_recursive_mutex_Control * ),
141  Thread_queue_Context          *queue_context
142)
143{
144  Thread_Control *owner;
145
146  _CORE_mutex_Acquire_critical( &the_mutex->Mutex, queue_context );
147
148  owner = _CORE_mutex_Get_owner( &the_mutex->Mutex );
149
150  if ( owner == NULL ) {
151    _CORE_mutex_Set_owner( &the_mutex->Mutex, executing );
152    _Thread_Resource_count_increment( executing );
153    _CORE_mutex_Release( &the_mutex->Mutex, queue_context );
154    return STATUS_SUCCESSFUL;
155  }
156
157  if ( owner == executing ) {
158    Status_Control status;
159
160    status = ( *nested )( the_mutex );
161    _CORE_mutex_Release( &the_mutex->Mutex, queue_context );
162    return status;
163  }
164
165  return _CORE_mutex_Seize_slow(
166    &the_mutex->Mutex,
167    operations,
168    executing,
169    wait,
170    queue_context
171  );
172}
173
174RTEMS_INLINE_ROUTINE Status_Control _CORE_recursive_mutex_Surrender(
175  CORE_recursive_mutex_Control  *the_mutex,
176  const Thread_queue_Operations *operations,
177  Thread_Control                *executing,
178  Thread_queue_Context          *queue_context
179)
180{
181  unsigned int        nest_level;
182  Thread_queue_Heads *heads;
183
184  _CORE_mutex_Acquire_critical( &the_mutex->Mutex, queue_context );
185
186  if ( !_CORE_mutex_Is_owner( &the_mutex->Mutex, executing ) ) {
187    _CORE_mutex_Release( &the_mutex->Mutex, queue_context );
188    return STATUS_NOT_OWNER;
189  }
190
191  nest_level = the_mutex->nest_level;
192
193  if ( nest_level > 0 ) {
194    the_mutex->nest_level = nest_level - 1;
195    _CORE_mutex_Release( &the_mutex->Mutex, queue_context );
196    return STATUS_SUCCESSFUL;
197  }
198
199  _Thread_Resource_count_decrement( executing );
200  _CORE_mutex_Set_owner( &the_mutex->Mutex, NULL );
201
202  heads = the_mutex->Mutex.Wait_queue.Queue.heads;
203
204  if ( heads == NULL ) {
205    _CORE_mutex_Release( &the_mutex->Mutex, queue_context );
206    return STATUS_SUCCESSFUL;
207  }
208
209  _Thread_queue_Surrender(
210    &the_mutex->Mutex.Wait_queue.Queue,
211    heads,
212    executing,
213    queue_context,
214    operations
215  );
216  return STATUS_SUCCESSFUL;
217}
218
219RTEMS_INLINE_ROUTINE void _CORE_ceiling_mutex_Initialize(
220  CORE_ceiling_mutex_Control *the_mutex,
221  const Scheduler_Control    *scheduler,
222  Priority_Control            priority_ceiling
223)
224{
225  _CORE_recursive_mutex_Initialize( &the_mutex->Recursive );
226  _Priority_Node_initialize( &the_mutex->Priority_ceiling, priority_ceiling );
227#if defined(RTEMS_SMP)
228  the_mutex->scheduler = scheduler;
229#endif
230}
231
232RTEMS_INLINE_ROUTINE const Scheduler_Control *
233_CORE_ceiling_mutex_Get_scheduler(
234  const CORE_ceiling_mutex_Control *the_mutex
235)
236{
237#if defined(RTEMS_SMP)
238  return the_mutex->scheduler;
239#else
240  return &_Scheduler_Table[ 0 ];
241#endif
242}
243
244RTEMS_INLINE_ROUTINE void _CORE_ceiling_mutex_Set_priority(
245  CORE_ceiling_mutex_Control *the_mutex,
246  Priority_Control            priority_ceiling,
247  Thread_queue_Context       *queue_context
248)
249{
250  Thread_Control *owner;
251
252  owner = _CORE_mutex_Get_owner( &the_mutex->Recursive.Mutex );
253
254  if ( owner != NULL ) {
255    _Thread_Wait_acquire( owner, queue_context );
256    _Thread_Priority_change(
257      owner,
258      &the_mutex->Priority_ceiling,
259      priority_ceiling,
260      false,
261      queue_context
262    );
263    _Thread_Wait_release( owner, queue_context );
264  } else {
265    the_mutex->Priority_ceiling.priority = priority_ceiling;
266  }
267}
268
269RTEMS_INLINE_ROUTINE Priority_Control _CORE_ceiling_mutex_Get_priority(
270  const CORE_ceiling_mutex_Control *the_mutex
271)
272{
273  return the_mutex->Priority_ceiling.priority;
274}
275
276RTEMS_INLINE_ROUTINE Status_Control _CORE_ceiling_mutex_Set_owner(
277  CORE_ceiling_mutex_Control *the_mutex,
278  Thread_Control             *owner,
279  Thread_queue_Context       *queue_context
280)
281{
282  ISR_lock_Context  lock_context;
283  Scheduler_Node   *scheduler_node;
284  Per_CPU_Control  *cpu_self;
285
286  _Thread_Wait_acquire_default_critical( owner, &lock_context );
287
288  scheduler_node = _Thread_Scheduler_get_home_node( owner );
289
290  if (
291    _Priority_Get_priority( &scheduler_node->Wait.Priority )
292      < the_mutex->Priority_ceiling.priority
293  ) {
294    _Thread_Wait_release_default_critical( owner, &lock_context );
295    _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
296    return STATUS_MUTEX_CEILING_VIOLATED;
297  }
298
299  _CORE_mutex_Set_owner( &the_mutex->Recursive.Mutex, owner );
300  _Thread_Resource_count_increment( owner );
301  _Thread_Priority_add(
302    owner,
303    &the_mutex->Priority_ceiling,
304    queue_context
305  );
306  _Thread_Wait_release_default_critical( owner, &lock_context );
307
308  cpu_self = _Thread_queue_Dispatch_disable( queue_context );
309  _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
310  _Thread_Priority_update( queue_context );
311  _Thread_Dispatch_enable( cpu_self );
312  return STATUS_SUCCESSFUL;
313}
314
315RTEMS_INLINE_ROUTINE Status_Control _CORE_ceiling_mutex_Seize(
316  CORE_ceiling_mutex_Control    *the_mutex,
317  Thread_Control                *executing,
318  bool                           wait,
319  Status_Control              ( *nested )( CORE_recursive_mutex_Control * ),
320  Thread_queue_Context          *queue_context
321)
322{
323  Thread_Control *owner;
324
325  _CORE_mutex_Acquire_critical( &the_mutex->Recursive.Mutex, queue_context );
326
327  owner = _CORE_mutex_Get_owner( &the_mutex->Recursive.Mutex );
328
329  if ( owner == NULL ) {
330#if defined(RTEMS_SMP)
331    if (
332      _Thread_Scheduler_get_home( executing )
333        != _CORE_ceiling_mutex_Get_scheduler( the_mutex )
334    ) {
335      _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
336      return STATUS_NOT_DEFINED;
337    }
338#endif
339
340    _Thread_queue_Context_clear_priority_updates( queue_context );
341    return _CORE_ceiling_mutex_Set_owner(
342      the_mutex,
343      executing,
344      queue_context
345    );
346  }
347
348  if ( owner == executing ) {
349    Status_Control status;
350
351    status = ( *nested )( &the_mutex->Recursive );
352    _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
353    return status;
354  }
355
356  return _CORE_mutex_Seize_slow(
357    &the_mutex->Recursive.Mutex,
358    CORE_MUTEX_TQ_OPERATIONS,
359    executing,
360    wait,
361    queue_context
362  );
363}
364
365RTEMS_INLINE_ROUTINE Status_Control _CORE_ceiling_mutex_Surrender(
366  CORE_ceiling_mutex_Control *the_mutex,
367  Thread_Control             *executing,
368  Thread_queue_Context       *queue_context
369)
370{
371  unsigned int      nest_level;
372  ISR_lock_Context  lock_context;
373  Per_CPU_Control  *cpu_self;
374  Thread_Control   *new_owner;
375
376  _CORE_mutex_Acquire_critical( &the_mutex->Recursive.Mutex, queue_context );
377
378  if ( !_CORE_mutex_Is_owner( &the_mutex->Recursive.Mutex, executing ) ) {
379    _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
380    return STATUS_NOT_OWNER;
381  }
382
383  nest_level = the_mutex->Recursive.nest_level;
384
385  if ( nest_level > 0 ) {
386    the_mutex->Recursive.nest_level = nest_level - 1;
387    _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
388    return STATUS_SUCCESSFUL;
389  }
390
391  _Thread_Resource_count_decrement( executing );
392
393  _Thread_queue_Context_clear_priority_updates( queue_context );
394  _Thread_Wait_acquire_default_critical( executing, &lock_context );
395  _Thread_Priority_remove(
396    executing,
397    &the_mutex->Priority_ceiling,
398    queue_context
399  );
400  _Thread_Wait_release_default_critical( executing, &lock_context );
401
402  new_owner = _Thread_queue_First_locked(
403    &the_mutex->Recursive.Mutex.Wait_queue,
404    CORE_MUTEX_TQ_OPERATIONS
405  );
406  _CORE_mutex_Set_owner( &the_mutex->Recursive.Mutex, new_owner );
407
408  cpu_self = _Thread_Dispatch_disable_critical(
409    &queue_context->Lock_context.Lock_context
410  );
411
412  if ( new_owner != NULL ) {
413#if defined(RTEMS_MULTIPROCESSING)
414    if ( _Objects_Is_local_id( new_owner->Object.id ) )
415#endif
416    {
417      _Thread_Resource_count_increment( new_owner );
418      _Thread_Priority_add(
419        new_owner,
420        &the_mutex->Priority_ceiling,
421        queue_context
422      );
423    }
424
425    _Thread_queue_Extract_critical(
426      &the_mutex->Recursive.Mutex.Wait_queue.Queue,
427      CORE_MUTEX_TQ_OPERATIONS,
428      new_owner,
429      queue_context
430    );
431  } else {
432    _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
433  }
434
435  _Thread_Priority_update( queue_context );
436  _Thread_Dispatch_enable( cpu_self );
437  return STATUS_SUCCESSFUL;
438}
439
440/** @} */
441
442#ifdef __cplusplus
443}
444#endif
445
446#endif
447/* end of include file */
Note: See TracBrowser for help on using the repository browser.