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

Last change on this file since 0b713f89 was 0b713f89, checked in by Sebastian Huber <sebastian.huber@…>, on May 30, 2016 at 4:59:55 AM

score: Rework CORE inherit priority mutex

Provide dedicated seize and surrender methods for inherit priority
mutexes. This eliminates CORE_mutex_Attributes.

  • 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/system.h>
22#include <rtems/rtems/status.h>
23#include <rtems/rtems/support.h>
24#include <rtems/rtems/attrimpl.h>
25#include <rtems/score/isr.h>
26#include <rtems/rtems/options.h>
27#include <rtems/rtems/semimpl.h>
28#include <rtems/rtems/statusimpl.h>
29#include <rtems/rtems/tasksimpl.h>
30#include <rtems/score/coremuteximpl.h>
31#include <rtems/score/coresemimpl.h>
32#include <rtems/score/threaddispatch.h>
33#include <rtems/score/sysstate.h>
34
35#include <rtems/score/interr.h>
36
37/*
38 *  rtems_semaphore_create
39 *
40 *  This directive creates a semaphore and sets the initial value based
41 *  on the given count.  A semaphore id is returned.
42 *
43 *  Input parameters:
44 *    name             - user defined semaphore name
45 *    count            - initial count of semaphore
46 *    attribute_set    - semaphore attributes
47 *    priority_ceiling - semaphore's ceiling priority
48 *    id               - pointer to semaphore id
49 *
50 *  Output parameters:
51 *    id       - semaphore id
52 *    RTEMS_SUCCESSFUL - if successful
53 *    error code - if unsuccessful
54 */
55
56rtems_status_code rtems_semaphore_create(
57  rtems_name           name,
58  uint32_t             count,
59  rtems_attribute      attribute_set,
60  rtems_task_priority  priority_ceiling,
61  rtems_id            *id
62)
63{
64  Semaphore_Control *the_semaphore;
65  Thread_Control    *executing;
66  Status_Control     status;
67
68  if ( !rtems_is_name_valid( name ) )
69    return RTEMS_INVALID_NAME;
70
71  if ( !id )
72    return RTEMS_INVALID_ADDRESS;
73
74#if defined(RTEMS_MULTIPROCESSING)
75  if ( _Attributes_Is_global( attribute_set ) ) {
76
77    if ( !_System_state_Is_multiprocessing )
78      return RTEMS_MP_NOT_CONFIGURED;
79
80    if ( _Attributes_Is_inherit_priority( attribute_set ) ||
81         _Attributes_Is_priority_ceiling( attribute_set ) ||
82         _Attributes_Is_multiprocessor_resource_sharing( attribute_set ) )
83      return RTEMS_NOT_DEFINED;
84
85  } else
86#endif
87
88  if ( _Attributes_Is_multiprocessor_resource_sharing( attribute_set ) &&
89       !( _Attributes_Is_binary_semaphore( attribute_set ) &&
90         !_Attributes_Is_priority( attribute_set ) ) ) {
91    return RTEMS_NOT_DEFINED;
92  }
93
94  if ( _Attributes_Is_inherit_priority( attribute_set ) ||
95              _Attributes_Is_priority_ceiling( attribute_set ) ) {
96
97    if ( ! (_Attributes_Is_binary_semaphore( attribute_set ) &&
98            _Attributes_Is_priority( attribute_set ) ) )
99      return RTEMS_NOT_DEFINED;
100
101  }
102
103  if ( !_Attributes_Has_at_most_one_protocol( attribute_set ) )
104    return RTEMS_NOT_DEFINED;
105
106  if ( !_Attributes_Is_counting_semaphore( attribute_set ) && ( count > 1 ) )
107    return RTEMS_INVALID_NUMBER;
108
109#if !defined(RTEMS_SMP)
110  /*
111   * On uni-processor configurations the Multiprocessor Resource Sharing
112   * Protocol is equivalent to the Priority Ceiling Protocol.
113   */
114  if ( _Attributes_Is_multiprocessor_resource_sharing( attribute_set ) ) {
115    attribute_set |= RTEMS_PRIORITY_CEILING | RTEMS_PRIORITY;
116  }
117#endif
118
119  the_semaphore = _Semaphore_Allocate();
120
121  if ( !the_semaphore ) {
122    _Objects_Allocator_unlock();
123    return RTEMS_TOO_MANY;
124  }
125
126#if defined(RTEMS_MULTIPROCESSING)
127  the_semaphore->is_global = _Attributes_Is_global( attribute_set );
128
129  if ( _Attributes_Is_global( attribute_set ) &&
130       ! ( _Objects_MP_Allocate_and_open( &_Semaphore_Information, name,
131                            the_semaphore->Object.id, false ) ) ) {
132    _Semaphore_Free( the_semaphore );
133    _Objects_Allocator_unlock();
134    return RTEMS_TOO_MANY;
135  }
136#endif
137
138  priority_ceiling = _RTEMS_tasks_Priority_to_Core( priority_ceiling );
139  executing = _Thread_Get_executing();
140
141  if ( _Attributes_Is_priority( attribute_set ) ) {
142    the_semaphore->discipline = SEMAPHORE_DISCIPLINE_PRIORITY;
143  } else {
144    the_semaphore->discipline = SEMAPHORE_DISCIPLINE_FIFO;
145  }
146
147  if ( _Attributes_Is_counting_semaphore( attribute_set ) ) {
148    the_semaphore->variant = SEMAPHORE_VARIANT_COUNTING;
149    _CORE_semaphore_Initialize(
150      &the_semaphore->Core_control.semaphore,
151      count
152    );
153    status = STATUS_SUCCESSFUL;
154  } else if ( _Attributes_Is_simple_binary_semaphore( attribute_set ) ) {
155    the_semaphore->variant = SEMAPHORE_VARIANT_SIMPLE_BINARY;
156    _CORE_semaphore_Initialize(
157      &the_semaphore->Core_control.semaphore,
158      count != 0
159    );
160    status = STATUS_SUCCESSFUL;
161#if defined(RTEMS_SMP)
162  } else if ( _Attributes_Is_multiprocessor_resource_sharing( attribute_set ) ) {
163    the_semaphore->variant = SEMAPHORE_VARIANT_MRSP;
164    status = _MRSP_Initialize(
165      &the_semaphore->Core_control.mrsp,
166      priority_ceiling,
167      executing,
168      count != 1
169    );
170#endif
171  } else if ( _Attributes_Is_priority_ceiling( attribute_set ) ) {
172    _Assert( _Attributes_Is_binary_semaphore( attribute_set ) );
173    the_semaphore->variant = SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING;
174    _CORE_ceiling_mutex_Initialize(
175      &the_semaphore->Core_control.Mutex,
176      priority_ceiling
177    );
178
179    if ( count == 0 ) {
180      Thread_queue_Context queue_context;
181
182      _Thread_queue_Context_initialize( &queue_context );
183      _ISR_lock_ISR_disable( &queue_context.Lock_context );
184      _CORE_mutex_Acquire_critical(
185        &the_semaphore->Core_control.Mutex.Recursive.Mutex,
186        &queue_context
187      );
188      status = _CORE_ceiling_mutex_Set_owner(
189        &the_semaphore->Core_control.Mutex,
190        executing,
191        &queue_context
192      );
193    } else {
194      status = STATUS_SUCCESSFUL;
195    }
196  } else {
197    _Assert( _Attributes_Is_binary_semaphore( attribute_set ) );
198
199    if ( _Attributes_Is_inherit_priority( attribute_set ) ) {
200      the_semaphore->variant = SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY;
201    } else {
202      the_semaphore->variant = SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL;
203    }
204
205    _CORE_recursive_mutex_Initialize(
206      &the_semaphore->Core_control.Mutex.Recursive
207    );
208
209    if ( count == 0 ) {
210      _CORE_mutex_Set_owner(
211        &the_semaphore->Core_control.Mutex.Recursive.Mutex,
212        executing
213      );
214
215      if ( _Attributes_Is_inherit_priority( attribute_set ) ) {
216        ++executing->resource_count;
217      }
218    }
219
220    status = STATUS_SUCCESSFUL;
221  }
222
223  if ( status != STATUS_SUCCESSFUL ) {
224    _Semaphore_Free( the_semaphore );
225    _Objects_Allocator_unlock();
226    return _Status_Get( status );
227  }
228
229  /*
230   *  Whether we initialized it as a mutex or counting semaphore, it is
231   *  now ready to be "offered" for use as a Classic API Semaphore.
232   */
233  _Objects_Open(
234    &_Semaphore_Information,
235    &the_semaphore->Object,
236    (Objects_Name) name
237  );
238
239  *id = the_semaphore->Object.id;
240
241#if defined(RTEMS_MULTIPROCESSING)
242  if ( _Attributes_Is_global( attribute_set ) )
243    _Semaphore_MP_Send_process_packet(
244      SEMAPHORE_MP_ANNOUNCE_CREATE,
245      the_semaphore->Object.id,
246      name,
247      0                          /* Not used */
248    );
249#endif
250  _Objects_Allocator_unlock();
251  return RTEMS_SUCCESSFUL;
252}
Note: See TracBrowser for help on using the repository browser.