source: rtems/cpukit/score/src/semaphore.c @ c090db7

5
Last change on this file since c090db7 was c090db7, checked in by Sebastian Huber <sebastian.huber@…>, on 09/12/17 at 06:09:16

posix: Implement self-contained POSIX semaphores

For semaphore object pointer and object validation see
POSIX_SEMAPHORE_VALIDATE_OBJECT().

Destruction or close of a busy semaphore returns an error status. The
object is not flushed.

POSIX semaphores are now available in all configurations and no longer
depend on --enable-posix.

Update #2514.
Update #3116.

  • Property mode set to 100644
File size: 2.8 KB
Line 
1/*
2 * Copyright (c) 2015 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#if HAVE_CONFIG_H
16  #include "config.h"
17#endif
18
19#include <rtems/score/semaphoreimpl.h>
20#include <rtems/score/statesimpl.h>
21
22#include <limits.h>
23
24RTEMS_STATIC_ASSERT(
25  offsetof( Sem_Control, Queue )
26    == offsetof( struct _Semaphore_Control, _Queue ),
27  SEMAPHORE_CONTROL_QUEUE
28);
29
30RTEMS_STATIC_ASSERT(
31  offsetof( Sem_Control, count )
32    == offsetof( struct _Semaphore_Control, _count ),
33  SEMAPHORE_CONTROL_COUNT
34);
35
36RTEMS_STATIC_ASSERT(
37  sizeof( Sem_Control ) == sizeof( struct _Semaphore_Control ),
38  SEMAPHORE_CONTROL_SIZE
39);
40
41void _Semaphore_Wait( struct _Semaphore_Control *_sem )
42{
43  Sem_Control          *sem;
44  ISR_Level             level;
45  Thread_queue_Context  queue_context;
46  Thread_Control       *executing;
47  unsigned int          count;
48
49  sem = _Sem_Get( _sem );
50  _Thread_queue_Context_initialize( &queue_context );
51  _Thread_queue_Context_ISR_disable( &queue_context, level );
52  executing = _Sem_Queue_acquire_critical( sem, &queue_context );
53
54  count = sem->count;
55  if ( __predict_true( count > 0 ) ) {
56    sem->count = count - 1;
57    _Sem_Queue_release( sem, level, &queue_context );
58  } else {
59    _Thread_queue_Context_set_thread_state(
60      &queue_context,
61      STATES_WAITING_FOR_SEMAPHORE
62    );
63    _Thread_queue_Context_set_do_nothing_enqueue_callout( &queue_context );
64    _Thread_queue_Context_set_no_timeout( &queue_context );
65    _Thread_queue_Context_set_ISR_level( &queue_context, level );
66    _Thread_queue_Enqueue(
67      &sem->Queue.Queue,
68      SEMAPHORE_TQ_OPERATIONS,
69      executing,
70      &queue_context
71    );
72  }
73}
74
75void _Semaphore_Post( struct _Semaphore_Control *_sem )
76{
77  Sem_Control          *sem;
78  ISR_Level             level;
79  Thread_queue_Context  queue_context;
80  Thread_queue_Heads   *heads;
81
82  sem = _Sem_Get( _sem );
83  _Thread_queue_Context_initialize( &queue_context );
84  _Thread_queue_Context_ISR_disable( &queue_context, level );
85  _Sem_Queue_acquire_critical( sem, &queue_context );
86
87  heads = sem->Queue.Queue.heads;
88  if ( __predict_true( heads == NULL ) ) {
89    _Assert( sem->count < UINT_MAX );
90    ++sem->count;
91    _Sem_Queue_release( sem, level, &queue_context );
92  } else {
93    const Thread_queue_Operations *operations;
94    Thread_Control *first;
95
96    _Thread_queue_Context_set_ISR_level( &queue_context, level );
97    operations = SEMAPHORE_TQ_OPERATIONS;
98    first = ( *operations->first )( heads );
99
100    _Thread_queue_Extract_critical(
101      &sem->Queue.Queue,
102      operations,
103      first,
104      &queue_context
105    );
106  }
107}
Note: See TracBrowser for help on using the repository browser.