source: rtems/cpukit/rtems/src/semcreate.c @ 66cb142

Last change on this file since 66cb142 was 5b6c290, checked in by Sebastian Huber <sebastian.huber@…>, on Dec 1, 2016 at 7:42:48 PM

score: Initialize thread queue context early

Initialize thread queue context early preferably outside the critical
section.

Remove implicit _Thread_queue_Context_initialize() from
_Thread_Wait_acquire().

  • Property mode set to 100644
File size: 7.1 KB
Line 
1/**
2 * @file
3 *
4 * @brief rtems_semaphore_create
5 * @ingroup ClassicSem Semaphores
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2014.
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/rtems/semimpl.h>
22#include <rtems/rtems/attrimpl.h>
23#include <rtems/rtems/statusimpl.h>
24#include <rtems/rtems/tasksimpl.h>
25#include <rtems/score/schedulerimpl.h>
26#include <rtems/score/sysstate.h>
27
28#define SEMAPHORE_KIND_MASK ( RTEMS_SEMAPHORE_CLASS | RTEMS_INHERIT_PRIORITY \
29  | RTEMS_PRIORITY_CEILING | RTEMS_MULTIPROCESSOR_RESOURCE_SHARING )
30
31rtems_status_code rtems_semaphore_create(
32  rtems_name           name,
33  uint32_t             count,
34  rtems_attribute      attribute_set,
35  rtems_task_priority  priority_ceiling,
36  rtems_id            *id
37)
38{
39  Semaphore_Control       *the_semaphore;
40  Thread_Control          *executing;
41  Status_Control           status;
42  rtems_attribute          maybe_global;
43  rtems_attribute          mutex_with_protocol;
44  Semaphore_Variant        variant;
45  const Scheduler_Control *scheduler;
46  bool                     valid;
47  Priority_Control         priority;
48
49  if ( !rtems_is_name_valid( name ) )
50    return RTEMS_INVALID_NAME;
51
52  if ( !id )
53    return RTEMS_INVALID_ADDRESS;
54
55#if defined(RTEMS_MULTIPROCESSING)
56  if (
57    _Attributes_Is_global( attribute_set )
58      && !_System_state_Is_multiprocessing
59  ) {
60    return RTEMS_MP_NOT_CONFIGURED;
61  }
62#endif
63
64  /* Attribute subset defining a potentially global semaphore variant */
65  maybe_global = attribute_set & SEMAPHORE_KIND_MASK;
66
67  /* Attribute subset defining a mutex variant with a locking protocol */
68  mutex_with_protocol =
69    attribute_set & ( SEMAPHORE_KIND_MASK | RTEMS_GLOBAL | RTEMS_PRIORITY );
70
71  if ( maybe_global == RTEMS_COUNTING_SEMAPHORE ) {
72    variant = SEMAPHORE_VARIANT_COUNTING;
73  } else if ( count > 1 ) {
74    /*
75     * The remaining variants are all binary semphores, thus reject an invalid
76     * count value.
77     */
78    return RTEMS_INVALID_NUMBER;
79  } else if ( maybe_global == RTEMS_SIMPLE_BINARY_SEMAPHORE ) {
80    variant = SEMAPHORE_VARIANT_SIMPLE_BINARY;
81  } else if ( maybe_global == RTEMS_BINARY_SEMAPHORE ) {
82    variant = SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL;
83  } else if (
84    mutex_with_protocol
85      == ( RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY )
86  ) {
87    variant = SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY;
88  } else if (
89    mutex_with_protocol
90      == ( RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_PRIORITY_CEILING )
91  ) {
92    variant = SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING;
93  } else if (
94    mutex_with_protocol
95      == ( RTEMS_BINARY_SEMAPHORE | RTEMS_MULTIPROCESSOR_RESOURCE_SHARING )
96  ) {
97#if defined(RTEMS_SMP)
98    variant = SEMAPHORE_VARIANT_MRSP;
99#else
100    /*
101     * On uni-processor configurations the Multiprocessor Resource Sharing
102     * Protocol is equivalent to the Priority Ceiling Protocol.
103     */
104    variant = SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING;
105#endif
106  } else {
107    return RTEMS_NOT_DEFINED;
108  }
109
110  the_semaphore = _Semaphore_Allocate();
111
112  if ( !the_semaphore ) {
113    _Objects_Allocator_unlock();
114    return RTEMS_TOO_MANY;
115  }
116
117#if defined(RTEMS_MULTIPROCESSING)
118  the_semaphore->is_global = _Attributes_Is_global( attribute_set );
119
120  if ( _Attributes_Is_global( attribute_set ) &&
121       ! ( _Objects_MP_Allocate_and_open( &_Semaphore_Information, name,
122                            the_semaphore->Object.id, false ) ) ) {
123    _Semaphore_Free( the_semaphore );
124    _Objects_Allocator_unlock();
125    return RTEMS_TOO_MANY;
126  }
127#endif
128
129  executing = _Thread_Get_executing();
130
131  the_semaphore->variant = variant;
132
133  if ( _Attributes_Is_priority( attribute_set ) ) {
134    the_semaphore->discipline = SEMAPHORE_DISCIPLINE_PRIORITY;
135  } else {
136    the_semaphore->discipline = SEMAPHORE_DISCIPLINE_FIFO;
137  }
138
139  switch ( the_semaphore->variant ) {
140    case SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL:
141    case SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY:
142      _CORE_recursive_mutex_Initialize(
143        &the_semaphore->Core_control.Mutex.Recursive
144      );
145
146      if ( count == 0 ) {
147        _CORE_mutex_Set_owner(
148          &the_semaphore->Core_control.Mutex.Recursive.Mutex,
149          executing
150        );
151        _Thread_Resource_count_increment( executing );
152      }
153
154      status = STATUS_SUCCESSFUL;
155      break;
156    case SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING:
157      scheduler = _Thread_Scheduler_get_home( executing );
158      priority = _RTEMS_Priority_To_core( scheduler, priority_ceiling, &valid );
159
160      if ( valid ) {
161        _CORE_ceiling_mutex_Initialize(
162          &the_semaphore->Core_control.Mutex,
163          scheduler,
164          priority
165        );
166
167        if ( count == 0 ) {
168          Thread_queue_Context queue_context;
169
170          _Thread_queue_Context_initialize( &queue_context );
171          _Thread_queue_Context_clear_priority_updates( &queue_context );
172          _ISR_lock_ISR_disable( &queue_context.Lock_context.Lock_context );
173          _CORE_mutex_Acquire_critical(
174            &the_semaphore->Core_control.Mutex.Recursive.Mutex,
175            &queue_context
176          );
177          status = _CORE_ceiling_mutex_Set_owner(
178            &the_semaphore->Core_control.Mutex,
179            executing,
180            &queue_context
181          );
182
183          if ( status != STATUS_SUCCESSFUL ) {
184            _Thread_queue_Destroy( &the_semaphore->Core_control.Wait_queue );
185          }
186        } else {
187          status = STATUS_SUCCESSFUL;
188        }
189      } else {
190        status = STATUS_INVALID_PRIORITY;
191      }
192
193      break;
194#if defined(RTEMS_SMP)
195    case SEMAPHORE_VARIANT_MRSP:
196      scheduler = _Thread_Scheduler_get_home( executing );
197      priority = _RTEMS_Priority_To_core( scheduler, priority_ceiling, &valid );
198
199      if ( valid ) {
200        status = _MRSP_Initialize(
201          &the_semaphore->Core_control.MRSP,
202          scheduler,
203          priority,
204          executing,
205          count == 0
206        );
207      } else {
208        status = STATUS_INVALID_PRIORITY;
209      }
210
211      break;
212#endif
213    default:
214      _Assert(
215        the_semaphore->variant == SEMAPHORE_VARIANT_SIMPLE_BINARY
216          || the_semaphore->variant == SEMAPHORE_VARIANT_COUNTING
217      );
218      _CORE_semaphore_Initialize(
219        &the_semaphore->Core_control.Semaphore,
220        count
221      );
222      status = STATUS_SUCCESSFUL;
223      break;
224  }
225
226  if ( status != STATUS_SUCCESSFUL ) {
227    _Semaphore_Free( the_semaphore );
228    _Objects_Allocator_unlock();
229    return _Status_Get( status );
230  }
231
232  /*
233   *  Whether we initialized it as a mutex or counting semaphore, it is
234   *  now ready to be "offered" for use as a Classic API Semaphore.
235   */
236  _Objects_Open(
237    &_Semaphore_Information,
238    &the_semaphore->Object,
239    (Objects_Name) name
240  );
241
242  *id = the_semaphore->Object.id;
243
244#if defined(RTEMS_MULTIPROCESSING)
245  if ( _Attributes_Is_global( attribute_set ) )
246    _Semaphore_MP_Send_process_packet(
247      SEMAPHORE_MP_ANNOUNCE_CREATE,
248      the_semaphore->Object.id,
249      name,
250      0                          /* Not used */
251    );
252#endif
253  _Objects_Allocator_unlock();
254  return RTEMS_SUCCESSFUL;
255}
Note: See TracBrowser for help on using the repository browser.