source: rtems/cpukit/rtems/src/semcreate.c @ 739df1f5

Last change on this file since 739df1f5 was 739df1f5, checked in by Sebastian Huber <sebastian.huber@…>, on Nov 8, 2018 at 9:45:44 AM

rtems: Move internal structures to semdata.h

Update #3598.

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