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

5
Last change on this file since a7cfb4b was a7cfb4b, checked in by Sebastian Huber <sebastian.huber@…>, on 12/23/16 at 12:54:11

score: Relax <sys/lock.h> static assertions

Only require that the Newlib defined structure is big enough.

  • Property mode set to 100644
File size: 3.9 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_critical(
59  Semaphore_Control    *sem,
60  Thread_queue_Context *queue_context
61)
62{
63  Thread_Control *executing;
64
65  executing = _Thread_Executing;
66  _Thread_queue_Queue_acquire_critical(
67    &sem->Queue.Queue,
68    &executing->Potpourri_stats,
69    &queue_context->Lock_context.Lock_context
70  );
71
72  return executing;
73}
74
75static void _Semaphore_Queue_release(
76  Semaphore_Control    *sem,
77  ISR_Level             level,
78  Thread_queue_Context *queue_context
79)
80{
81  _Thread_queue_Queue_release_critical(
82    &sem->Queue.Queue,
83    &queue_context->Lock_context.Lock_context
84  );
85  _ISR_Local_enable( level );
86}
87
88void _Semaphore_Wait( struct _Semaphore_Control *_sem )
89{
90  Semaphore_Control    *sem ;
91  ISR_Level             level;
92  Thread_queue_Context  queue_context;
93  Thread_Control       *executing;
94  unsigned int          count;
95
96  sem = _Semaphore_Get( _sem );
97  _Thread_queue_Context_initialize( &queue_context );
98  _Thread_queue_Context_ISR_disable( &queue_context, level );
99  executing = _Semaphore_Queue_acquire_critical( sem, &queue_context );
100
101  count = sem->count;
102  if ( __predict_true( count > 0 ) ) {
103    sem->count = count - 1;
104    _Semaphore_Queue_release( sem, level, &queue_context );
105  } else {
106    _Thread_queue_Context_set_thread_state(
107      &queue_context,
108      STATES_WAITING_FOR_SYS_LOCK_SEMAPHORE
109    );
110    _Thread_queue_Context_set_do_nothing_enqueue_callout( &queue_context );
111    _Thread_queue_Context_set_no_timeout( &queue_context );
112    _Thread_queue_Context_set_ISR_level( &queue_context, level );
113    _Thread_queue_Enqueue(
114      &sem->Queue.Queue,
115      SEMAPHORE_TQ_OPERATIONS,
116      executing,
117      &queue_context
118    );
119  }
120}
121
122void _Semaphore_Post( struct _Semaphore_Control *_sem )
123{
124  Semaphore_Control    *sem;
125  ISR_Level             level;
126  Thread_queue_Context  queue_context;
127  Thread_queue_Heads   *heads;
128
129  sem = _Semaphore_Get( _sem );
130  _Thread_queue_Context_initialize( &queue_context );
131  _Thread_queue_Context_ISR_disable( &queue_context, level );
132  _Semaphore_Queue_acquire_critical( sem, &queue_context );
133
134  heads = sem->Queue.Queue.heads;
135  if ( __predict_true( heads == NULL ) ) {
136    _Assert( sem->count < UINT_MAX );
137    ++sem->count;
138    _Semaphore_Queue_release( sem, level, &queue_context );
139  } else {
140    const Thread_queue_Operations *operations;
141    Thread_Control *first;
142
143    _Thread_queue_Context_set_ISR_level( &queue_context, level );
144    operations = SEMAPHORE_TQ_OPERATIONS;
145    first = ( *operations->first )( heads );
146
147    _Thread_queue_Extract_critical(
148      &sem->Queue.Queue,
149      operations,
150      first,
151      &queue_context
152    );
153  }
154}
155
156#endif /* HAVE_STRUCT__THREAD_QUEUE_QUEUE */
Note: See TracBrowser for help on using the repository browser.