source: rtems/cpukit/rtems/src/sem.c @ 98e4ebf5

4.104.114.84.95
Last change on this file since 98e4ebf5 was 98e4ebf5, checked in by Joel Sherrill <joel.sherrill@…>, on 10/08/97 at 15:45:54

Fixed typo in the pointer to the license terms.

  • Property mode set to 100644
File size: 14.9 KB
Line 
1/*
2 *  Semaphore Manager
3 *
4 *  DESCRIPTION:
5 *
6 *  This package is the implementation of the Semaphore Manager.
7 *  This manager utilizes standard Dijkstra counting semaphores to provide
8 *  synchronization and mutual exclusion capabilities.
9 *
10 *  Directives provided are:
11 *
12 *     + create a semaphore
13 *     + get an ID of a semaphore
14 *     + delete a semaphore
15 *     + acquire a semaphore
16 *     + release a semaphore
17 *
18 *  COPYRIGHT (c) 1989-1997.
19 *  On-Line Applications Research Corporation (OAR).
20 *  Copyright assigned to U.S. Government, 1994.
21 *
22 *  The license and distribution terms for this file may be
23 *  found in the file LICENSE in this distribution or at
24 *  http://www.OARcorp.com/rtems/license.html.
25 *
26 *  $Id$
27 */
28
29#include <rtems/system.h>
30#include <rtems/rtems/status.h>
31#include <rtems/rtems/support.h>
32#include <rtems/rtems/attr.h>
33#include <rtems/score/isr.h>
34#include <rtems/score/object.h>
35#include <rtems/rtems/options.h>
36#include <rtems/rtems/sem.h>
37#include <rtems/score/coremutex.h>
38#include <rtems/score/coresem.h>
39#include <rtems/score/states.h>
40#include <rtems/score/thread.h>
41#include <rtems/score/threadq.h>
42#include <rtems/score/mpci.h>
43#include <rtems/score/sysstate.h>
44
45#include <rtems/score/interr.h>
46
47/*PAGE
48 *
49 *  _Semaphore_Manager_initialization
50 *
51 *  This routine initializes all semaphore manager related data structures.
52 *
53 *  Input parameters:
54 *    maximum_semaphores - maximum configured semaphores
55 *
56 *  Output parameters:  NONE
57 */
58
59void _Semaphore_Manager_initialization(
60  unsigned32 maximum_semaphores
61)
62{
63  _Objects_Initialize_information(
64    &_Semaphore_Information,
65    OBJECTS_RTEMS_SEMAPHORES,
66    TRUE,
67    maximum_semaphores,
68    sizeof( Semaphore_Control ),
69    FALSE,
70    RTEMS_MAXIMUM_NAME_LENGTH,
71    FALSE
72  );
73 
74  /*
75   *  Register the MP Process Packet routine.
76   */
77 
78  _MPCI_Register_packet_processor(
79    MP_PACKET_SEMAPHORE,
80    _Semaphore_MP_Process_packet
81  );
82
83}
84
85/*PAGE
86 *
87 *  rtems_semaphore_create
88 *
89 *  This directive creates a semaphore and sets the initial value based
90 *  on the given count.  A semaphore id is returned.
91 *
92 *  Input parameters:
93 *    name             - user defined semaphore name
94 *    count            - initial count of semaphore
95 *    attribute_set    - semaphore attributes
96 *    priority_ceiling - semaphore's ceiling priority
97 *    id               - pointer to semaphore id
98 *
99 *  Output parameters:
100 *    id       - semaphore id
101 *    RTEMS_SUCCESSFUL - if successful
102 *    error code - if unsuccessful
103 */
104
105rtems_status_code rtems_semaphore_create(
106  rtems_name           name,
107  unsigned32           count,
108  rtems_attribute      attribute_set,
109  rtems_task_priority  priority_ceiling,
110  Objects_Id          *id
111)
112{
113  register Semaphore_Control *the_semaphore;
114  CORE_mutex_Attributes       the_mutex_attributes;
115  CORE_semaphore_Attributes   the_semaphore_attributes;
116  unsigned32                  lock;
117
118  if ( !rtems_is_name_valid( name ) )
119    return RTEMS_INVALID_NAME;
120
121  if ( _Attributes_Is_global( attribute_set ) ) {
122
123    if ( !_System_state_Is_multiprocessing )
124      return RTEMS_MP_NOT_CONFIGURED;
125
126    if ( _Attributes_Is_inherit_priority( attribute_set ) )
127      return RTEMS_NOT_DEFINED;
128
129  } else if ( _Attributes_Is_inherit_priority( attribute_set ) ||
130              _Attributes_Is_priority_ceiling( attribute_set ) ) {
131
132    if ( ! ( _Attributes_Is_binary_semaphore( attribute_set ) &&
133             _Attributes_Is_priority( attribute_set ) ) )
134      return RTEMS_NOT_DEFINED;
135
136  }
137
138  if ( _Attributes_Is_binary_semaphore( attribute_set ) && ( count > 1 ) )
139    return RTEMS_INVALID_NUMBER;
140
141  _Thread_Disable_dispatch();             /* prevents deletion */
142
143  the_semaphore = _Semaphore_Allocate();
144
145  if ( !the_semaphore ) {
146    _Thread_Enable_dispatch();
147    return RTEMS_TOO_MANY;
148  }
149
150  if ( _Attributes_Is_global( attribute_set ) &&
151       ! ( _Objects_MP_Allocate_and_open( &_Semaphore_Information, name,
152                            the_semaphore->Object.id, FALSE ) ) ) {
153    _Semaphore_Free( the_semaphore );
154    _Thread_Enable_dispatch();
155    return RTEMS_TOO_MANY;
156  }
157
158  the_semaphore->attribute_set = attribute_set;
159
160  if ( _Attributes_Is_binary_semaphore( attribute_set ) ) {
161    if ( _Attributes_Is_inherit_priority( attribute_set ) )
162      the_mutex_attributes.discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT;
163    else if (_Attributes_Is_priority_ceiling( attribute_set ) )
164      the_mutex_attributes.discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING;
165    else if (_Attributes_Is_priority( attribute_set ) )
166      the_mutex_attributes.discipline = CORE_MUTEX_DISCIPLINES_PRIORITY;
167    else
168      the_mutex_attributes.discipline = CORE_MUTEX_DISCIPLINES_FIFO;
169
170    the_mutex_attributes.allow_nesting = TRUE;
171
172    /* Add priority ceiling code here ????? */
173
174    the_mutex_attributes.priority_ceiling = priority_ceiling;
175
176    if ( count == 1 )
177      lock = CORE_MUTEX_UNLOCKED;
178    else
179      lock = CORE_MUTEX_LOCKED;
180
181    _CORE_mutex_Initialize(
182      &the_semaphore->Core_control.mutex,
183      OBJECTS_RTEMS_SEMAPHORES,
184      &the_mutex_attributes,
185      lock,
186      _Semaphore_MP_Send_extract_proxy
187    );
188  }
189  else {
190    if ( _Attributes_Is_priority( attribute_set ) )
191      the_semaphore_attributes.discipline = CORE_SEMAPHORE_DISCIPLINES_PRIORITY;
192    else
193      the_semaphore_attributes.discipline = CORE_SEMAPHORE_DISCIPLINES_FIFO;
194
195    /*
196     *  The following are just to make Purify happy.
197     */
198
199    the_mutex_attributes.allow_nesting = TRUE;
200    the_mutex_attributes.priority_ceiling = PRIORITY_MINIMUM;
201
202    _CORE_semaphore_Initialize(
203      &the_semaphore->Core_control.semaphore,
204      OBJECTS_RTEMS_SEMAPHORES,
205      &the_semaphore_attributes,
206      count,
207      _Semaphore_MP_Send_extract_proxy
208    );
209  }
210
211  _Objects_Open( &_Semaphore_Information, &the_semaphore->Object, &name );
212
213  *id = the_semaphore->Object.id;
214
215  if ( _Attributes_Is_global( attribute_set ) )
216    _Semaphore_MP_Send_process_packet(
217      SEMAPHORE_MP_ANNOUNCE_CREATE,
218      the_semaphore->Object.id,
219      name,
220      0                          /* Not used */
221    );
222  _Thread_Enable_dispatch();
223  return RTEMS_SUCCESSFUL;
224}
225
226/*PAGE
227 *
228 *  rtems_semaphore_ident
229 *
230 *  This directive returns the system ID associated with
231 *  the semaphore name.
232 *
233 *  Input parameters:
234 *    name - user defined semaphore name
235 *    node - node(s) to be searched
236 *    id   - pointer to semaphore id
237 *
238 *  Output parameters:
239 *    *id      - semaphore id
240 *    RTEMS_SUCCESSFUL - if successful
241 *    error code - if unsuccessful
242 */
243
244rtems_status_code rtems_semaphore_ident(
245  rtems_name  name,
246  unsigned32  node,
247  Objects_Id *id
248)
249{
250  Objects_Name_to_id_errors  status;
251 
252  status = _Objects_Name_to_id( &_Semaphore_Information, &name, node, id );
253 
254  return _Status_Object_name_errors_to_status[ status ];
255}
256
257/*PAGE
258 *
259 *  rtems_semaphore_delete
260 *
261 *  This directive allows a thread to delete a semaphore specified by
262 *  the semaphore id.  The semaphore is freed back to the inactive
263 *  semaphore chain.
264 *
265 *  Input parameters:
266 *    id - semaphore id
267 *
268 *  Output parameters:
269 *    RTEMS_SUCCESSFUL - if successful
270 *    error code        - if unsuccessful
271 */
272
273rtems_status_code rtems_semaphore_delete(
274  Objects_Id id
275)
276{
277  register Semaphore_Control *the_semaphore;
278  Objects_Locations           location;
279
280  the_semaphore = _Semaphore_Get( id, &location );
281  switch ( location ) {
282    case OBJECTS_ERROR:
283      return RTEMS_INVALID_ID;
284    case OBJECTS_REMOTE:
285      _Thread_Dispatch();
286      return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
287    case OBJECTS_LOCAL:
288      if ( _Attributes_Is_binary_semaphore( the_semaphore->attribute_set) ) {
289        if ( _CORE_mutex_Is_locked( &the_semaphore->Core_control.mutex ) ) {
290          _Thread_Enable_dispatch();
291          return RTEMS_RESOURCE_IN_USE;
292        }
293        else
294          _CORE_mutex_Flush(
295            &the_semaphore->Core_control.mutex,
296            _Semaphore_MP_Send_object_was_deleted,
297            CORE_MUTEX_WAS_DELETED
298          );
299      }
300      else
301        _CORE_semaphore_Flush(
302          &the_semaphore->Core_control.semaphore,
303          _Semaphore_MP_Send_object_was_deleted,
304          CORE_SEMAPHORE_WAS_DELETED
305        );
306
307      _Objects_Close( &_Semaphore_Information, &the_semaphore->Object );
308
309      _Semaphore_Free( the_semaphore );
310
311      if ( _Attributes_Is_global( the_semaphore->attribute_set ) ) {
312
313        _Objects_MP_Close( &_Semaphore_Information, the_semaphore->Object.id );
314
315        _Semaphore_MP_Send_process_packet(
316          SEMAPHORE_MP_ANNOUNCE_DELETE,
317          the_semaphore->Object.id,
318          0,                         /* Not used */
319          0                          /* Not used */
320        );
321      }
322      _Thread_Enable_dispatch();
323      return RTEMS_SUCCESSFUL;
324  }
325
326  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
327}
328
329/*PAGE
330 *
331 *  rtems_semaphore_obtain
332 *
333 *  This directive allows a thread to acquire a semaphore.
334 *
335 *  Input parameters:
336 *    id         - semaphore id
337 *    option_set - wait option
338 *    timeout    - number of ticks to wait (0 means wait forever)
339 *
340 *  Output parameters:
341 *    RTEMS_SUCCESSFUL - if successful
342 *    error code        - if unsuccessful
343 */
344
345rtems_status_code rtems_semaphore_obtain(
346  Objects_Id      id,
347  unsigned32      option_set,
348  rtems_interval  timeout
349)
350{
351  register Semaphore_Control *the_semaphore;
352  Objects_Locations           location;
353  boolean                     wait;
354
355  the_semaphore = _Semaphore_Get( id, &location );
356  switch ( location ) {
357    case OBJECTS_ERROR:
358      return RTEMS_INVALID_ID;
359    case OBJECTS_REMOTE:
360      return _Semaphore_MP_Send_request_packet(
361          SEMAPHORE_MP_OBTAIN_REQUEST,
362          id,
363          option_set,
364          timeout
365      );
366    case OBJECTS_LOCAL:
367      if ( _Options_Is_no_wait( option_set ) )
368        wait = FALSE;
369      else
370        wait = TRUE;
371
372      if ( _Attributes_Is_binary_semaphore( the_semaphore->attribute_set ) ) {
373        _CORE_mutex_Seize(
374          &the_semaphore->Core_control.mutex,
375          id,
376          wait,
377          timeout
378        );
379        _Thread_Enable_dispatch();
380        return _Semaphore_Translate_core_mutex_return_code(
381                  _Thread_Executing->Wait.return_code );
382      } else {
383        _CORE_semaphore_Seize(
384          &the_semaphore->Core_control.semaphore,
385          id,
386          wait,
387          timeout
388        );
389        _Thread_Enable_dispatch();
390        return _Semaphore_Translate_core_semaphore_return_code(
391                  _Thread_Executing->Wait.return_code );
392      }
393  }
394
395  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
396}
397
398/*PAGE
399 *
400 *  rtems_semaphore_release
401 *
402 *  This directive allows a thread to release a semaphore.
403 *
404 *  Input parameters:
405 *    id - semaphore id
406 *
407 *  Output parameters:
408 *    RTEMS_SUCCESSFUL - if successful
409 *    error code        - if unsuccessful
410 */
411
412rtems_status_code rtems_semaphore_release(
413  Objects_Id id
414)
415{
416  register Semaphore_Control *the_semaphore;
417  Objects_Locations           location;
418  CORE_mutex_Status           mutex_status;
419  CORE_semaphore_Status       semaphore_status;
420
421  the_semaphore = _Semaphore_Get( id, &location );
422  switch ( location ) {
423    case OBJECTS_ERROR:
424      return RTEMS_INVALID_ID;
425    case OBJECTS_REMOTE:
426      return _Semaphore_MP_Send_request_packet(
427        SEMAPHORE_MP_RELEASE_REQUEST,
428        id,
429        0,                               /* Not used */
430        MPCI_DEFAULT_TIMEOUT
431      );
432    case OBJECTS_LOCAL:
433      if ( _Attributes_Is_binary_semaphore( the_semaphore->attribute_set ) ) {
434        mutex_status = _CORE_mutex_Surrender(
435                         &the_semaphore->Core_control.mutex,
436                         id,
437                         _Semaphore_Core_mutex_mp_support
438                       );
439        _Thread_Enable_dispatch();
440        return _Semaphore_Translate_core_mutex_return_code( mutex_status );
441      }
442      else
443        semaphore_status = _CORE_semaphore_Surrender(
444                             &the_semaphore->Core_control.semaphore,
445                             id,
446                             _Semaphore_Core_semaphore_mp_support
447                           );
448        _Thread_Enable_dispatch();
449        return
450          _Semaphore_Translate_core_semaphore_return_code( semaphore_status );
451  }
452
453  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
454}
455
456/*PAGE
457 *
458 *  _Semaphore_Translate_core_mutex_return_code
459 *
460 *  Input parameters:
461 *    the_mutex_status - mutex status code to translate
462 *
463 *  Output parameters:
464 *    rtems status code - translated RTEMS status code
465 *
466 */
467 
468rtems_status_code _Semaphore_Translate_core_mutex_return_code (
469  unsigned32 the_mutex_status
470)
471{
472  switch ( the_mutex_status ) {
473    case  CORE_MUTEX_STATUS_SUCCESSFUL:
474      return RTEMS_SUCCESSFUL;
475    case CORE_MUTEX_STATUS_UNSATISFIED_NOWAIT:
476      return RTEMS_UNSATISFIED;
477    case CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED:
478      return RTEMS_INTERNAL_ERROR;
479    case CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE:
480      return RTEMS_NOT_OWNER_OF_RESOURCE;
481    case CORE_MUTEX_WAS_DELETED:
482      return RTEMS_OBJECT_WAS_DELETED;
483    case CORE_MUTEX_TIMEOUT:
484      return RTEMS_TIMEOUT;
485    case THREAD_STATUS_PROXY_BLOCKING:
486      return THREAD_STATUS_PROXY_BLOCKING;
487  }
488  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
489}
490
491/*PAGE
492 *
493 *  _Semaphore_Translate_core_semaphore_return_code
494 *
495 *  Input parameters:
496 *    the_semaphore_status - semaphore status code to translate
497 *
498 *  Output parameters:
499 *    rtems status code - translated RTEMS status code
500 *
501 */
502 
503rtems_status_code _Semaphore_Translate_core_semaphore_return_code (
504  unsigned32 the_semaphore_status
505)
506{
507  switch ( the_semaphore_status ) {
508    case  CORE_SEMAPHORE_STATUS_SUCCESSFUL:
509      return RTEMS_SUCCESSFUL;
510    case CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT:
511      return RTEMS_UNSATISFIED;
512    case CORE_SEMAPHORE_WAS_DELETED:
513      return RTEMS_OBJECT_WAS_DELETED;
514    case CORE_SEMAPHORE_TIMEOUT:
515      return RTEMS_TIMEOUT;
516    case THREAD_STATUS_PROXY_BLOCKING:
517      return THREAD_STATUS_PROXY_BLOCKING;
518  }
519  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
520}
521
522/*PAGE
523 *
524 *  _Semaphore_Core_mutex_mp_support
525 *
526 *  Input parameters:
527 *    the_thread - the remote thread the semaphore was surrendered to
528 *    id         - id of the surrendered semaphore
529 *
530 *  Output parameters: NONE
531 */
532 
533void  _Semaphore_Core_mutex_mp_support (
534  Thread_Control *the_thread,
535  Objects_Id      id
536)
537{
538  the_thread->receive_packet->return_code = RTEMS_SUCCESSFUL;
539 
540  _Semaphore_MP_Send_response_packet(
541     SEMAPHORE_MP_OBTAIN_RESPONSE,
542     id,
543     the_thread
544   );
545}
546
547
548/*PAGE
549 *
550 *  _Semaphore_Core_semaphore_mp_support
551 *
552 *  Input parameters:
553 *    the_thread - the remote thread the semaphore was surrendered to
554 *    id         - id of the surrendered semaphore
555 *
556 *  Output parameters: NONE
557 */
558 
559void  _Semaphore_Core_semaphore_mp_support (
560  Thread_Control *the_thread,
561  Objects_Id      id
562)
563{
564  the_thread->receive_packet->return_code = RTEMS_SUCCESSFUL;
565 
566  _Semaphore_MP_Send_response_packet(
567     SEMAPHORE_MP_OBTAIN_RESPONSE,
568     id,
569     the_thread
570   );
571}
Note: See TracBrowser for help on using the repository browser.