source: rtems/cpukit/rtems/src/semcreate.c @ 0dd49d0

5
Last change on this file since 0dd49d0 was 0dd49d0, checked in by Sebastian Huber <sebastian.huber@…>, on 10/31/16 at 15:10:32

score: Introduce thread resource count methods

This makes it easier to conditionally enable/disable the thread resource
count usage.

  • 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          _ISR_lock_ISR_disable( &queue_context.Lock_context.Lock_context );
172          _CORE_mutex_Acquire_critical(
173            &the_semaphore->Core_control.Mutex.Recursive.Mutex,
174            &queue_context
175          );
176          status = _CORE_ceiling_mutex_Set_owner(
177            &the_semaphore->Core_control.Mutex,
178            executing,
179            &queue_context
180          );
181
182          if ( status != STATUS_SUCCESSFUL ) {
183            _Thread_queue_Destroy( &the_semaphore->Core_control.Wait_queue );
184          }
185        } else {
186          status = STATUS_SUCCESSFUL;
187        }
188      } else {
189        status = STATUS_INVALID_PRIORITY;
190      }
191
192      break;
193#if defined(RTEMS_SMP)
194    case SEMAPHORE_VARIANT_MRSP:
195      scheduler = _Thread_Scheduler_get_home( executing );
196      priority = _RTEMS_Priority_To_core( scheduler, priority_ceiling, &valid );
197
198      if ( valid ) {
199        status = _MRSP_Initialize(
200          &the_semaphore->Core_control.MRSP,
201          scheduler,
202          priority,
203          executing,
204          count == 0
205        );
206      } else {
207        status = STATUS_INVALID_PRIORITY;
208      }
209
210      break;
211#endif
212    default:
213      _Assert(
214        the_semaphore->variant == SEMAPHORE_VARIANT_SIMPLE_BINARY
215          || the_semaphore->variant == SEMAPHORE_VARIANT_COUNTING
216      );
217      _CORE_semaphore_Initialize(
218        &the_semaphore->Core_control.Semaphore,
219        count
220      );
221      status = STATUS_SUCCESSFUL;
222      break;
223  }
224
225  if ( status != STATUS_SUCCESSFUL ) {
226    _Semaphore_Free( the_semaphore );
227    _Objects_Allocator_unlock();
228    return _Status_Get( status );
229  }
230
231  /*
232   *  Whether we initialized it as a mutex or counting semaphore, it is
233   *  now ready to be "offered" for use as a Classic API Semaphore.
234   */
235  _Objects_Open(
236    &_Semaphore_Information,
237    &the_semaphore->Object,
238    (Objects_Name) name
239  );
240
241  *id = the_semaphore->Object.id;
242
243#if defined(RTEMS_MULTIPROCESSING)
244  if ( _Attributes_Is_global( attribute_set ) )
245    _Semaphore_MP_Send_process_packet(
246      SEMAPHORE_MP_ANNOUNCE_CREATE,
247      the_semaphore->Object.id,
248      name,
249      0                          /* Not used */
250    );
251#endif
252  _Objects_Allocator_unlock();
253  return RTEMS_SUCCESSFUL;
254}
Note: See TracBrowser for help on using the repository browser.