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 #ifdef HAVE_CONFIG_H
0041 #include "config.h"
0042 #endif
0043
0044 #include <sys/lock.h>
0045 #include <errno.h>
0046 #include <limits.h>
0047
0048 #include <rtems/score/atomic.h>
0049 #include <rtems/score/chainimpl.h>
0050 #include <rtems/score/threadimpl.h>
0051 #include <rtems/score/threadqimpl.h>
0052 #include <rtems/score/todimpl.h>
0053 #include <rtems/score/watchdogimpl.h>
0054
0055 #define CONDITION_TQ_OPERATIONS &_Thread_queue_Operations_FIFO
0056
0057 typedef struct {
0058 Thread_queue_Syslock_queue Queue;
0059 } Condition_Control;
0060
0061 RTEMS_STATIC_ASSERT(
0062 offsetof( Condition_Control, Queue )
0063 == offsetof( struct _Condition_Control, _Queue ),
0064 CONDITION_CONTROL_QUEUE
0065 );
0066
0067 RTEMS_STATIC_ASSERT(
0068 sizeof( Condition_Control ) == sizeof( struct _Condition_Control ),
0069 CONDITION_CONTROL_SIZE
0070 );
0071
0072 static Condition_Control *_Condition_Get(
0073 struct _Condition_Control *_condition
0074 )
0075 {
0076 return (Condition_Control *) _condition;
0077 }
0078
0079 static Thread_Control *_Condition_Queue_acquire_critical(
0080 Condition_Control *condition,
0081 Thread_queue_Context *queue_context
0082 )
0083 {
0084 Thread_Control *executing;
0085
0086 executing = _Thread_Executing;
0087 _Thread_queue_Queue_acquire_critical(
0088 &condition->Queue.Queue,
0089 &executing->Potpourri_stats,
0090 &queue_context->Lock_context.Lock_context
0091 );
0092
0093 return executing;
0094 }
0095
0096 static void _Condition_Queue_release(
0097 Condition_Control *condition,
0098 Thread_queue_Context *queue_context
0099 )
0100 {
0101 _Thread_queue_Queue_release(
0102 &condition->Queue.Queue,
0103 &queue_context->Lock_context.Lock_context
0104 );
0105 }
0106
0107 typedef struct {
0108 Thread_queue_Context Base;
0109 struct _Mutex_Control *mutex;
0110 } Condition_Enqueue_context;
0111
0112 static void _Condition_Mutex_release( Thread_queue_Context *queue_context )
0113 {
0114 Condition_Enqueue_context *context;
0115
0116 context = (Condition_Enqueue_context *) queue_context;
0117 _Mutex_Release( context->mutex );
0118 }
0119
0120 static void _Condition_Enqueue_no_timeout(
0121 Thread_queue_Queue *queue,
0122 Thread_Control *the_thread,
0123 Per_CPU_Control *cpu_self,
0124 Thread_queue_Context *queue_context
0125 )
0126 {
0127 _Condition_Mutex_release( queue_context );
0128 }
0129
0130 static void _Condition_Enqueue_with_timeout(
0131 Thread_queue_Queue *queue,
0132 Thread_Control *the_thread,
0133 Per_CPU_Control *cpu_self,
0134 Thread_queue_Context *queue_context
0135 )
0136 {
0137 _Thread_queue_Add_timeout_realtime_timespec(
0138 queue,
0139 the_thread,
0140 cpu_self,
0141 queue_context
0142 );
0143 _Condition_Mutex_release( queue_context );
0144 }
0145
0146 static Thread_Control *_Condition_Do_wait(
0147 struct _Condition_Control *_condition,
0148 struct _Mutex_Control *_mutex,
0149 Condition_Enqueue_context *context
0150 )
0151 {
0152 Condition_Control *condition;
0153 Thread_Control *executing;
0154
0155 context->mutex = _mutex;
0156 condition = _Condition_Get( _condition );
0157 _ISR_lock_ISR_disable( &context->Base.Lock_context.Lock_context );
0158 executing = _Condition_Queue_acquire_critical( condition, &context->Base );
0159 _Thread_queue_Context_set_thread_state(
0160 &context->Base,
0161 STATES_WAITING_FOR_CONDITION_VARIABLE
0162 );
0163 _Thread_queue_Enqueue(
0164 &condition->Queue.Queue,
0165 CONDITION_TQ_OPERATIONS,
0166 executing,
0167 &context->Base
0168 );
0169
0170 return executing;
0171 }
0172
0173 void _Condition_Wait(
0174 struct _Condition_Control *_condition,
0175 struct _Mutex_Control *_mutex
0176 )
0177 {
0178 Condition_Enqueue_context context;
0179
0180 _Thread_queue_Context_initialize( &context.Base );
0181 _Thread_queue_Context_set_enqueue_callout(
0182 &context.Base,
0183 _Condition_Enqueue_no_timeout
0184 );
0185 _Condition_Do_wait( _condition, _mutex, &context );
0186 _Mutex_Acquire( _mutex );
0187 }
0188
0189 int _Condition_Wait_timed(
0190 struct _Condition_Control *_condition,
0191 struct _Mutex_Control *_mutex,
0192 const struct timespec *abstime
0193 )
0194 {
0195 Condition_Enqueue_context context;
0196 Thread_Control *executing;
0197 int eno;
0198
0199 _Thread_queue_Context_initialize( &context.Base );
0200 _Thread_queue_Context_set_enqueue_callout(
0201 &context.Base,
0202 _Condition_Enqueue_with_timeout
0203 );
0204 _Thread_queue_Context_set_timeout_argument( &context.Base, abstime, true );
0205 executing = _Condition_Do_wait( _condition, _mutex, &context );
0206 eno = STATUS_GET_POSIX( _Thread_Wait_get_status( executing ) );
0207 _Mutex_Acquire( _mutex );
0208
0209 return eno;
0210 }
0211
0212 static unsigned int _Condition_Unnest_mutex(
0213 struct _Mutex_recursive_Control *_mutex
0214 )
0215 {
0216 unsigned int nest_level;
0217
0218 nest_level = _mutex->_nest_level;
0219 _mutex->_nest_level = 0;
0220
0221 return nest_level;
0222 }
0223
0224 void _Condition_Wait_recursive(
0225 struct _Condition_Control *_condition,
0226 struct _Mutex_recursive_Control *_mutex
0227 )
0228 {
0229 Condition_Enqueue_context context;
0230 unsigned int nest_level;
0231
0232 _Thread_queue_Context_initialize( &context.Base );
0233 _Thread_queue_Context_set_enqueue_callout(
0234 &context.Base,
0235 _Condition_Enqueue_no_timeout
0236 );
0237 nest_level = _Condition_Unnest_mutex( _mutex );
0238 _Condition_Do_wait( _condition, &_mutex->_Mutex, &context );
0239 _Mutex_recursive_Acquire( _mutex );
0240 _mutex->_nest_level = nest_level;
0241 }
0242
0243 int _Condition_Wait_recursive_timed(
0244 struct _Condition_Control *_condition,
0245 struct _Mutex_recursive_Control *_mutex,
0246 const struct timespec *abstime
0247 )
0248 {
0249 Condition_Enqueue_context context;
0250 Thread_Control *executing;
0251 int eno;
0252 unsigned int nest_level;
0253
0254 _Thread_queue_Context_initialize( &context.Base );
0255 _Thread_queue_Context_set_enqueue_callout(
0256 &context.Base,
0257 _Condition_Enqueue_with_timeout
0258 );
0259 _Thread_queue_Context_set_timeout_argument( &context.Base, abstime, true );
0260 nest_level = _Condition_Unnest_mutex( _mutex );
0261 executing = _Condition_Do_wait( _condition, &_mutex->_Mutex, &context );
0262 eno = STATUS_GET_POSIX( _Thread_Wait_get_status( executing ) );
0263 _Mutex_recursive_Acquire( _mutex );
0264 _mutex->_nest_level = nest_level;
0265
0266 return eno;
0267 }
0268
0269 typedef struct {
0270 Thread_queue_Context Base;
0271 int count;
0272 } Condition_Flush_context;
0273
0274 static Thread_Control *_Condition_Flush_filter(
0275 Thread_Control *the_thread,
0276 Thread_queue_Queue *queue,
0277 Thread_queue_Context *queue_context
0278 )
0279 {
0280 Condition_Flush_context *context;
0281
0282 context = (Condition_Flush_context *) queue_context;
0283
0284 if ( context->count <= 0 ) {
0285 return NULL;
0286 }
0287
0288 --context->count;
0289
0290 return the_thread;
0291 }
0292
0293 static void _Condition_Wake( struct _Condition_Control *_condition, int count )
0294 {
0295 Condition_Control *condition;
0296 Condition_Flush_context context;
0297
0298 condition = _Condition_Get( _condition );
0299 _Thread_queue_Context_initialize( &context.Base );
0300 _ISR_lock_ISR_disable( &context.Base.Lock_context.Lock_context );
0301 _Condition_Queue_acquire_critical( condition, &context.Base );
0302
0303
0304
0305
0306
0307 if (
0308 RTEMS_PREDICT_TRUE( _Thread_queue_Is_empty( &condition->Queue.Queue ) )
0309 ) {
0310 _Condition_Queue_release( condition, &context.Base );
0311 return;
0312 }
0313
0314 context.count = count;
0315 _Thread_queue_Flush_critical(
0316 &condition->Queue.Queue,
0317 CONDITION_TQ_OPERATIONS,
0318 _Condition_Flush_filter,
0319 &context.Base
0320 );
0321 }
0322
0323 void _Condition_Signal( struct _Condition_Control *_condition )
0324 {
0325 _Condition_Wake( _condition, 1 );
0326 }
0327
0328 void _Condition_Broadcast( struct _Condition_Control *_condition )
0329 {
0330 _Condition_Wake( _condition, INT_MAX );
0331 }