source: rtems/cpukit/rtems/src/semcreate.c @ 6fc34e4

5
Last change on this file since 6fc34e4 was 6fc34e4, checked in by Sebastian Huber <sebastian.huber@…>, on 06/06/16 at 08:58:04

rtems: Simplify rtems_semaphore_create()

Remove superfluous includes. Use one attribute compare for each
semaphore variant. Text size drops by 10% on PowerPC due to this.

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