source: rtems/cpukit/score/src/semaphore.c @ 2afb22b

5
Last change on this file since 2afb22b was c3105894, checked in by Sebastian Huber <sebastian.huber@…>, on 10/19/17 at 11:47:57

score: Move thread queue timeout handling

Update #3117.
Update #3182.

  • Property mode set to 100644
File size: 2.7 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_enqueue_do_nothing_extra( &queue_context );
64    _Thread_queue_Context_set_ISR_level( &queue_context, level );
65    _Thread_queue_Enqueue(
66      &sem->Queue.Queue,
67      SEMAPHORE_TQ_OPERATIONS,
68      executing,
69      &queue_context
70    );
71  }
72}
73
74void _Semaphore_Post( struct _Semaphore_Control *_sem )
75{
76  Sem_Control          *sem;
77  ISR_Level             level;
78  Thread_queue_Context  queue_context;
79  Thread_queue_Heads   *heads;
80
81  sem = _Sem_Get( _sem );
82  _Thread_queue_Context_initialize( &queue_context );
83  _Thread_queue_Context_ISR_disable( &queue_context, level );
84  _Sem_Queue_acquire_critical( sem, &queue_context );
85
86  heads = sem->Queue.Queue.heads;
87  if ( __predict_true( heads == NULL ) ) {
88    _Assert( sem->count < UINT_MAX );
89    ++sem->count;
90    _Sem_Queue_release( sem, level, &queue_context );
91  } else {
92    const Thread_queue_Operations *operations;
93    Thread_Control *first;
94
95    _Thread_queue_Context_set_ISR_level( &queue_context, level );
96    operations = SEMAPHORE_TQ_OPERATIONS;
97    first = ( *operations->first )( heads );
98
99    _Thread_queue_Extract_critical(
100      &sem->Queue.Queue,
101      operations,
102      first,
103      &queue_context
104    );
105  }
106}
Note: See TracBrowser for help on using the repository browser.