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

5
Last change on this file since 1506658c was 7237b3e, checked in by Sebastian Huber <sebastian.huber@…>, on 07/02/15 at 11:12:38

score: Add self-contained semaphore implementation

  • Property mode set to 100644
File size: 3.1 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#if HAVE_STRUCT__THREAD_QUEUE_QUEUE
20
21#include <sys/lock.h>
22
23#include <rtems/score/assert.h>
24#include <rtems/score/threadimpl.h>
25#include <rtems/score/threadqimpl.h>
26
27#define SEMAPHORE_TQ_OPERATIONS &_Thread_queue_Operations_priority
28
29typedef struct {
30  Thread_queue_Syslock_queue Queue;
31  unsigned int count;
32} Semaphore_Control;
33
34RTEMS_STATIC_ASSERT(
35  offsetof( Semaphore_Control, Queue )
36    == offsetof( struct _Semaphore_Control, _Queue ),
37  SEMAPHORE_CONTROL_QUEUE
38);
39
40RTEMS_STATIC_ASSERT(
41  offsetof( Semaphore_Control, count )
42    == offsetof( struct _Semaphore_Control, _count ),
43  SEMAPHORE_CONTROL_COUNT
44);
45
46RTEMS_STATIC_ASSERT(
47  sizeof( Semaphore_Control ) == sizeof( struct _Semaphore_Control ),
48  SEMAPHORE_CONTROL_SIZE
49);
50
51static Semaphore_Control *_Semaphore_Get(
52  struct _Semaphore_Control *_sem
53)
54{
55  return (Semaphore_Control *) _sem;
56}
57
58static Thread_Control *_Semaphore_Queue_acquire(
59  Semaphore_Control *sem,
60  ISR_lock_Context  *lock_context
61)
62{
63  Thread_Control *executing;
64
65  _ISR_lock_ISR_disable( lock_context );
66  executing = _Thread_Executing;
67  _Thread_queue_Queue_acquire_critical(
68    &sem->Queue.Queue,
69    &executing->Potpourri_stats,
70    lock_context
71  );
72
73  return executing;
74}
75
76static void _Semaphore_Queue_release(
77  Semaphore_Control *sem,
78  ISR_lock_Context  *lock_context
79)
80{
81  _Thread_queue_Queue_release( &sem->Queue.Queue, lock_context );
82}
83
84void _Semaphore_Wait( struct _Semaphore_Control *_sem )
85{
86  Semaphore_Control *sem ;
87  ISR_lock_Context   lock_context;
88  Thread_Control    *executing;
89  unsigned int       count;
90
91  sem = _Semaphore_Get( _sem );
92  executing = _Semaphore_Queue_acquire( sem, &lock_context );
93
94  count = sem->count;
95  if ( count > 0 ) {
96    sem->count = count - 1;
97    _Semaphore_Queue_release( sem, &lock_context );
98  } else {
99    _Thread_queue_Enqueue_critical(
100      &sem->Queue.Queue,
101      SEMAPHORE_TQ_OPERATIONS,
102      executing,
103      STATES_WAITING_FOR_SYS_LOCK_SEMAPHORE,
104      0,
105      0,
106      &lock_context
107    );
108  }
109}
110
111void _Semaphore_Post( struct _Semaphore_Control *_sem )
112{
113  Semaphore_Control  *sem;
114  ISR_lock_Context    lock_context;
115  Thread_queue_Heads *heads;
116
117  sem = _Semaphore_Get( _sem );
118  _Semaphore_Queue_acquire( sem, &lock_context );
119
120  heads = sem->Queue.Queue.heads;
121  if ( heads == NULL ) {
122    _Assert( sem->count < UINT_MAX );
123    ++sem->count;
124    _Semaphore_Queue_release( sem, &lock_context );
125  } else {
126    const Thread_queue_Operations *operations;
127    Thread_Control *first;
128
129    operations = SEMAPHORE_TQ_OPERATIONS;
130    first = ( *operations->first )( heads );
131
132    _Thread_queue_Extract_critical(
133      &sem->Queue.Queue,
134      operations,
135      first,
136      &lock_context
137    );
138  }
139}
140
141#endif /* HAVE_STRUCT__THREAD_QUEUE_QUEUE */
Note: See TracBrowser for help on using the repository browser.