File indexing completed on 2025-05-11 08:24:26
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049 #ifdef HAVE_CONFIG_H
0050 #include "config.h"
0051 #endif
0052
0053 #include <sys/lock.h>
0054 #include <errno.h>
0055
0056 #include <rtems/score/atomic.h>
0057 #include <rtems/score/chainimpl.h>
0058 #include <rtems/score/threadimpl.h>
0059 #include <rtems/score/threadqimpl.h>
0060
0061 #define FUTEX_TQ_OPERATIONS &_Thread_queue_Operations_FIFO
0062
0063 typedef struct {
0064 Thread_queue_Syslock_queue Queue;
0065 } Futex_Control;
0066
0067 RTEMS_STATIC_ASSERT(
0068 offsetof( Futex_Control, Queue )
0069 == offsetof( struct _Futex_Control, _Queue ),
0070 FUTEX_CONTROL_QUEUE
0071 );
0072
0073 RTEMS_STATIC_ASSERT(
0074 sizeof( Futex_Control ) == sizeof( struct _Futex_Control ),
0075 FUTEX_CONTROL_SIZE
0076 );
0077
0078 static Futex_Control *_Futex_Get( struct _Futex_Control *_futex )
0079 {
0080 return (Futex_Control *) _futex;
0081 }
0082
0083 static Thread_Control *_Futex_Queue_acquire_critical(
0084 Futex_Control *futex,
0085 Thread_queue_Context *queue_context
0086 )
0087 {
0088 Thread_Control *executing;
0089
0090 executing = _Thread_Executing;
0091 _Thread_queue_Queue_acquire_critical(
0092 &futex->Queue.Queue,
0093 &executing->Potpourri_stats,
0094 &queue_context->Lock_context.Lock_context
0095 );
0096
0097 return executing;
0098 }
0099
0100 static void _Futex_Queue_release(
0101 Futex_Control *futex,
0102 ISR_Level level,
0103 Thread_queue_Context *queue_context
0104 )
0105 {
0106 _Thread_queue_Queue_release_critical(
0107 &futex->Queue.Queue,
0108 &queue_context->Lock_context.Lock_context
0109 );
0110 _ISR_Local_enable( level );
0111 }
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129 int _Futex_Wait( struct _Futex_Control *_futex, int *uaddr, int val )
0130 {
0131 Futex_Control *futex;
0132 ISR_Level level;
0133 Thread_queue_Context queue_context;
0134 Thread_Control *executing;
0135 int eno;
0136
0137 futex = _Futex_Get( _futex );
0138 _Thread_queue_Context_initialize( &queue_context );
0139 _Thread_queue_Context_ISR_disable( &queue_context, level );
0140 executing = _Futex_Queue_acquire_critical( futex, &queue_context );
0141
0142 if ( *uaddr == val ) {
0143 _Thread_queue_Context_set_thread_state(
0144 &queue_context,
0145 STATES_WAITING_FOR_FUTEX
0146 );
0147 _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
0148 _Thread_queue_Context_set_ISR_level( &queue_context, level );
0149 _Thread_queue_Enqueue(
0150 &futex->Queue.Queue,
0151 FUTEX_TQ_OPERATIONS,
0152 executing,
0153 &queue_context
0154 );
0155 eno = 0;
0156 } else {
0157 _Futex_Queue_release( futex, level, &queue_context );
0158 eno = EAGAIN;
0159 }
0160
0161 return eno;
0162 }
0163
0164 typedef struct {
0165 Thread_queue_Context Base;
0166 int count;
0167 } Futex_Context;
0168
0169 static Thread_Control *_Futex_Flush_filter(
0170 Thread_Control *the_thread,
0171 Thread_queue_Queue *queue,
0172 Thread_queue_Context *queue_context
0173 )
0174 {
0175 Futex_Context *context;
0176
0177 context = (Futex_Context *) queue_context;
0178
0179 if ( context->count <= 0 ) {
0180 return NULL;
0181 }
0182
0183 --context->count;
0184
0185 return the_thread;
0186 }
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197 int _Futex_Wake( struct _Futex_Control *_futex, int count )
0198 {
0199 Futex_Control *futex;
0200 ISR_Level level;
0201 Futex_Context context;
0202
0203 futex = _Futex_Get( _futex );
0204 _Thread_queue_Context_initialize( &context.Base );
0205 _Thread_queue_Context_ISR_disable( &context.Base, level );
0206 _Futex_Queue_acquire_critical( futex, &context.Base );
0207
0208
0209
0210
0211
0212
0213 if ( RTEMS_PREDICT_TRUE( _Thread_queue_Is_empty( &futex->Queue.Queue ) ) ) {
0214 _Futex_Queue_release( futex, level, &context.Base );
0215 return 0;
0216 }
0217
0218 context.count = count;
0219 _Thread_queue_Context_set_ISR_level( &context.Base, level );
0220 return (int) _Thread_queue_Flush_critical(
0221 &futex->Queue.Queue,
0222 FUTEX_TQ_OPERATIONS,
0223 _Futex_Flush_filter,
0224 &context.Base
0225 );
0226 }