source: rtems/cpukit/score/src/futex.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: 4.1 KB
Line 
1/*
2 * Copyright (c) 2015, 2016 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#include <errno.h>
23
24#include <rtems/score/atomic.h>
25#include <rtems/score/chainimpl.h>
26#include <rtems/score/threadimpl.h>
27#include <rtems/score/threadqimpl.h>
28
29#define FUTEX_TQ_OPERATIONS &_Thread_queue_Operations_FIFO
30
31typedef struct {
32  Thread_queue_Syslock_queue Queue;
33} Futex_Control;
34
35RTEMS_STATIC_ASSERT(
36  offsetof( Futex_Control, Queue )
37    == offsetof( struct _Futex_Control, _Queue ),
38  FUTEX_CONTROL_QUEUE
39);
40
41RTEMS_STATIC_ASSERT(
42  sizeof( Futex_Control ) <= sizeof( struct _Futex_Control ),
43  FUTEX_CONTROL_SIZE
44);
45
46static Futex_Control *_Futex_Get( struct _Futex_Control *_futex )
47{
48  return (Futex_Control *) _futex;
49}
50
51static Thread_Control *_Futex_Queue_acquire_critical(
52  Futex_Control        *futex,
53  Thread_queue_Context *queue_context
54)
55{
56  Thread_Control *executing;
57
58  executing = _Thread_Executing;
59  _Thread_queue_Queue_acquire_critical(
60    &futex->Queue.Queue,
61    &executing->Potpourri_stats,
62    &queue_context->Lock_context.Lock_context
63  );
64
65  return executing;
66}
67
68static void _Futex_Queue_release(
69  Futex_Control        *futex,
70  ISR_Level             level,
71  Thread_queue_Context *queue_context
72)
73{
74  _Thread_queue_Queue_release_critical(
75    &futex->Queue.Queue,
76    &queue_context->Lock_context.Lock_context
77  );
78  _ISR_Local_enable( level );
79}
80
81int _Futex_Wait( struct _Futex_Control *_futex, int *uaddr, int val )
82{
83  Futex_Control        *futex;
84  ISR_Level             level;
85  Thread_queue_Context  queue_context;
86  Thread_Control       *executing;
87  int                   eno;
88
89  futex = _Futex_Get( _futex );
90  _Thread_queue_Context_initialize( &queue_context );
91  _Thread_queue_Context_ISR_disable( &queue_context, level );
92  executing = _Futex_Queue_acquire_critical( futex, &queue_context );
93
94  if ( *uaddr == val ) {
95    _Thread_queue_Context_set_thread_state(
96      &queue_context,
97      STATES_WAITING_FOR_SYS_LOCK_FUTEX
98    );
99    _Thread_queue_Context_set_do_nothing_enqueue_callout( &queue_context );
100    _Thread_queue_Context_set_no_timeout( &queue_context );
101    _Thread_queue_Context_set_ISR_level( &queue_context, level );
102    _Thread_queue_Enqueue(
103      &futex->Queue.Queue,
104      FUTEX_TQ_OPERATIONS,
105      executing,
106      &queue_context
107    );
108    eno = 0;
109  } else {
110    _Futex_Queue_release( futex, level, &queue_context );
111    eno = EWOULDBLOCK;
112  }
113
114  return eno;
115}
116
117typedef struct {
118  Thread_queue_Context Base;
119  int                  count;
120} Futex_Context;
121
122static Thread_Control *_Futex_Flush_filter(
123  Thread_Control       *the_thread,
124  Thread_queue_Queue   *queue,
125  Thread_queue_Context *queue_context
126)
127{
128  Futex_Context *context;
129
130  context = (Futex_Context *) queue_context;
131
132  if ( context->count <= 0 ) {
133    return NULL;
134  }
135
136  --context->count;
137
138  return the_thread;
139}
140
141int _Futex_Wake( struct _Futex_Control *_futex, int count )
142{
143  Futex_Control *futex;
144  ISR_Level      level;
145  Futex_Context  context;
146
147  futex = _Futex_Get( _futex );
148  _Thread_queue_Context_initialize( &context.Base );
149  _Thread_queue_Context_ISR_disable( &context.Base, level );
150  _Futex_Queue_acquire_critical( futex, &context.Base );
151
152  /*
153   * For some synchronization objects like barriers the _Futex_Wake() must be
154   * called in the fast path.  Normally there are no threads on the queue, so
155   * check this condition early.
156   */
157  if ( __predict_true( _Thread_queue_Is_empty( &futex->Queue.Queue ) ) ) {
158    _Futex_Queue_release( futex, level, &context.Base );
159    return 0;
160  }
161
162  context.count = count;
163  _Thread_queue_Context_set_ISR_level( &context.Base, level );
164  return (int) _Thread_queue_Flush_critical(
165    &futex->Queue.Queue,
166    FUTEX_TQ_OPERATIONS,
167    _Futex_Flush_filter,
168    &context.Base
169  );
170}
171
172#endif /* HAVE_STRUCT__THREAD_QUEUE_QUEUE */
Note: See TracBrowser for help on using the repository browser.