source: rtems/cpukit/score/src/semaphore.c @ 99fc1d1d

5
Last change on this file since 99fc1d1d was 93306058, checked in by Sebastian Huber <sebastian.huber@…>, on 05/27/16 at 12:43:19

score: _CORE_mutex_Check_dispatch_for_seize()

Move the safety check performed by
_CORE_mutex_Check_dispatch_for_seize() out of the performance critical
path and generalize it. Blocking on a thread queue with an unexpected
thread dispatch disabled level is illegal in all system states.

Add the expected thread dispatch disable level (which may be 1 or 2
depending on the operation) to Thread_queue_Context and use it in
_Thread_queue_Enqueue_critical().

  • Property mode set to 100644
File size: 3.3 KB
Line 
1/*
2 * Copyright (c) 2015 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#if HAVE_CONFIG_H
16  #include "config.h"
17#endif
18
19#if HAVE_STRUCT__THREAD_QUEUE_QUEUE
20
21#include <sys/lock.h>
22
23#include <rtems/score/assert.h>
24#include <rtems/score/threadimpl.h>
25#include <rtems/score/threadqimpl.h>
26
27#define SEMAPHORE_TQ_OPERATIONS &_Thread_queue_Operations_priority
28
29typedef struct {
30  Thread_queue_Syslock_queue Queue;
31  unsigned int count;
32} Semaphore_Control;
33
34RTEMS_STATIC_ASSERT(
35  offsetof( Semaphore_Control, Queue )
36    == offsetof( struct _Semaphore_Control, _Queue ),
37  SEMAPHORE_CONTROL_QUEUE
38);
39
40RTEMS_STATIC_ASSERT(
41  offsetof( Semaphore_Control, count )
42    == offsetof( struct _Semaphore_Control, _count ),
43  SEMAPHORE_CONTROL_COUNT
44);
45
46RTEMS_STATIC_ASSERT(
47  sizeof( Semaphore_Control ) == sizeof( struct _Semaphore_Control ),
48  SEMAPHORE_CONTROL_SIZE
49);
50
51static Semaphore_Control *_Semaphore_Get(
52  struct _Semaphore_Control *_sem
53)
54{
55  return (Semaphore_Control *) _sem;
56}
57
58static Thread_Control *_Semaphore_Queue_acquire(
59  Semaphore_Control    *sem,
60  Thread_queue_Context *queue_context
61)
62{
63  Thread_Control *executing;
64
65  _ISR_lock_ISR_disable( &queue_context->Lock_context );
66  executing = _Thread_Executing;
67  _Thread_queue_Queue_acquire_critical(
68    &sem->Queue.Queue,
69    &executing->Potpourri_stats,
70    &queue_context->Lock_context
71  );
72
73  return executing;
74}
75
76static void _Semaphore_Queue_release(
77  Semaphore_Control    *sem,
78  Thread_queue_Context *queue_context
79)
80{
81  _Thread_queue_Queue_release(
82    &sem->Queue.Queue,
83    &queue_context->Lock_context
84  );
85}
86
87void _Semaphore_Wait( struct _Semaphore_Control *_sem )
88{
89  Semaphore_Control    *sem ;
90  Thread_queue_Context  queue_context;
91  Thread_Control       *executing;
92  unsigned int          count;
93
94  sem = _Semaphore_Get( _sem );
95  _Thread_queue_Context_initialize( &queue_context );
96  executing = _Semaphore_Queue_acquire( sem, &queue_context );
97
98  count = sem->count;
99  if ( count > 0 ) {
100    sem->count = count - 1;
101    _Semaphore_Queue_release( sem, &queue_context );
102  } else {
103    _Thread_queue_Context_set_expected_level( &queue_context, 1 );
104    _Thread_queue_Enqueue_critical(
105      &sem->Queue.Queue,
106      SEMAPHORE_TQ_OPERATIONS,
107      executing,
108      STATES_WAITING_FOR_SYS_LOCK_SEMAPHORE,
109      WATCHDOG_NO_TIMEOUT,
110      &queue_context
111    );
112  }
113}
114
115void _Semaphore_Post( struct _Semaphore_Control *_sem )
116{
117  Semaphore_Control    *sem;
118  Thread_queue_Context  queue_context;
119  Thread_queue_Heads   *heads;
120
121  sem = _Semaphore_Get( _sem );
122  _Thread_queue_Context_initialize( &queue_context );
123  _Semaphore_Queue_acquire( sem, &queue_context );
124
125  heads = sem->Queue.Queue.heads;
126  if ( heads == NULL ) {
127    _Assert( sem->count < UINT_MAX );
128    ++sem->count;
129    _Semaphore_Queue_release( sem, &queue_context );
130  } else {
131    const Thread_queue_Operations *operations;
132    Thread_Control *first;
133
134    operations = SEMAPHORE_TQ_OPERATIONS;
135    first = ( *operations->first )( heads );
136
137    _Thread_queue_Extract_critical(
138      &sem->Queue.Queue,
139      operations,
140      first,
141      &queue_context
142    );
143  }
144}
145
146#endif /* HAVE_STRUCT__THREAD_QUEUE_QUEUE */
Note: See TracBrowser for help on using the repository browser.