File indexing completed on 2025-05-11 08:24:52
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
0050
0051 #ifdef HAVE_CONFIG_H
0052 #include "config.h"
0053 #endif
0054
0055 #include <rtems.h>
0056 #include <setjmp.h>
0057 #include <string.h>
0058 #include <rtems/score/atomic.h>
0059 #include <rtems/score/isrlevel.h>
0060 #include <rtems/score/threaddispatch.h>
0061
0062 #include "tx-support.h"
0063
0064 #include <rtems/test.h>
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105 typedef struct {
0106
0107
0108
0109 Atomic_Uint counter;
0110
0111
0112
0113
0114 rtems_fatal_source source;
0115
0116
0117
0118
0119 rtems_fatal_code code;
0120 } ScoreValFatal_Context;
0121
0122 static ScoreValFatal_Context
0123 ScoreValFatal_Instance;
0124
0125 typedef ScoreValFatal_Context Context;
0126
0127 static unsigned int GetFatalCounter( const Context *ctx )
0128 {
0129 return _Atomic_Load_uint( &ctx->counter, ATOMIC_ORDER_RELAXED );
0130 }
0131
0132 static unsigned int ResetFatalInfo( Context *ctx )
0133 {
0134 ctx->source = RTEMS_FATAL_SOURCE_APPLICATION;
0135 ctx->code = INTERNAL_ERROR_NO_MPCI;
0136
0137 return GetFatalCounter( ctx );
0138 }
0139
0140 static void Fatal(
0141 rtems_fatal_source source,
0142 rtems_fatal_code code,
0143 Context *ctx
0144 )
0145 {
0146 ctx->source = source;
0147 ctx->code = code;
0148 _Atomic_Fetch_add_uint( &ctx->counter, 1, ATOMIC_ORDER_RELAXED );
0149 _ISR_Set_level( 0 );
0150 }
0151
0152 static void FatalTaskExit(
0153 rtems_fatal_source source,
0154 rtems_fatal_code code,
0155 void *arg
0156 )
0157 {
0158 Fatal( source, code, arg );
0159 rtems_task_exit();
0160 }
0161
0162 static void ExitTask( rtems_task_argument arg )
0163 {
0164 (void) arg;
0165 }
0166
0167 static void FatalBadThreadDispatchEnvironment(
0168 rtems_fatal_source source,
0169 rtems_fatal_code code,
0170 void *arg
0171 )
0172 {
0173 Fatal( source, code, arg );
0174 _ISR_Set_level( 0 );
0175 _Thread_Dispatch_unnest( _Per_CPU_Get() );
0176 rtems_task_exit();
0177 }
0178
0179 static void ISRDisabledDirectThreadDispatchTask( rtems_task_argument arg )
0180 {
0181 rtems_interrupt_level level;
0182
0183 (void) arg;
0184 rtems_interrupt_local_disable( level );
0185 (void) level;
0186 rtems_task_exit();
0187 }
0188
0189 static void ISRDisabledOnDemandThreadDispatchTask( rtems_task_argument arg )
0190 {
0191 rtems_interrupt_level level;
0192
0193 (void) arg;
0194 rtems_interrupt_local_disable( level );
0195 (void) level;
0196 SetSelfPriority( PRIO_VERY_HIGH );
0197 rtems_task_exit();
0198 }
0199
0200 static void FatalBadThreadDispatchDisableLevel(
0201 rtems_fatal_source source,
0202 rtems_fatal_code code,
0203 void *arg
0204 )
0205 {
0206 Per_CPU_Control *cpu_self;
0207
0208 Fatal( source, code, arg );
0209 cpu_self = _Per_CPU_Get();
0210 _Thread_Dispatch_unnest( cpu_self );
0211 _Thread_Dispatch_direct_no_return( cpu_self );
0212 }
0213
0214 static void BadLevelThreadDispatchTask( rtems_task_argument arg )
0215 {
0216 (void) arg;
0217 _Thread_Dispatch_disable();
0218 rtems_task_exit();
0219 }
0220
0221 static jmp_buf before_fatal;
0222
0223 static rtems_id deadlock_mutex;
0224
0225 static bool ThreadCreateDeadlock( rtems_tcb *executing, rtems_tcb *created )
0226 {
0227 (void) executing;
0228 (void) created;
0229
0230 ObtainMutex( deadlock_mutex );
0231 ReleaseMutex( deadlock_mutex );
0232
0233 return true;
0234 }
0235
0236 static void FatalJumpBack(
0237 rtems_fatal_source source,
0238 rtems_fatal_code code,
0239 void *arg
0240 )
0241 {
0242 SetFatalHandler( NULL, NULL );
0243 Fatal( source, code, arg );
0244 longjmp( before_fatal, 1 );
0245 }
0246
0247 static void ThreadQueueDeadlockTask( rtems_task_argument arg )
0248 {
0249 rtems_id id;
0250
0251 (void) arg;
0252 id = CreateTask( "DORM", PRIO_NORMAL );
0253 DeleteTask( id );
0254
0255 rtems_task_exit();
0256 }
0257
0258 static T_fixture ScoreValFatal_Fixture = {
0259 .setup = NULL,
0260 .stop = NULL,
0261 .teardown = NULL,
0262 .scope = NULL,
0263 .initial_context = &ScoreValFatal_Instance
0264 };
0265
0266
0267
0268
0269
0270 static void ScoreValFatal_Action_0( ScoreValFatal_Context *ctx )
0271 {
0272 rtems_id id;
0273 unsigned int counter;
0274
0275 SetFatalHandler( FatalTaskExit, ctx );
0276 SetSelfPriority( PRIO_NORMAL );
0277 counter = ResetFatalInfo( ctx );
0278 id = CreateTask( "EXIT", PRIO_HIGH );
0279 StartTask( id, ExitTask, NULL );
0280 T_eq_uint( GetFatalCounter( ctx ), counter + 1 );
0281 T_eq_int( ctx->source, INTERNAL_ERROR_CORE );
0282 T_eq_ulong( ctx->code, INTERNAL_ERROR_THREAD_EXITTED );
0283 RestoreRunnerPriority();
0284 SetFatalHandler( NULL, NULL );
0285 }
0286
0287
0288
0289
0290
0291
0292
0293 static void ScoreValFatal_Action_1( ScoreValFatal_Context *ctx )
0294 {
0295 rtems_id id;
0296 unsigned int counter;
0297
0298 SetFatalHandler( FatalBadThreadDispatchEnvironment, ctx );
0299 SetSelfPriority( PRIO_NORMAL );
0300 counter = ResetFatalInfo( ctx );
0301 id = CreateTask( "BENV", PRIO_HIGH );
0302 StartTask( id, ISRDisabledDirectThreadDispatchTask, NULL );
0303
0304 #if CPU_ENABLE_ROBUST_THREAD_DISPATCH == FALSE
0305 if ( rtems_configuration_get_maximum_processors() > 1 ) {
0306 #endif
0307 T_eq_uint( GetFatalCounter( ctx ), counter + 1 );
0308 T_eq_int( ctx->source, INTERNAL_ERROR_CORE );
0309 T_eq_ulong( ctx->code, INTERNAL_ERROR_BAD_THREAD_DISPATCH_ENVIRONMENT );
0310 #if CPU_ENABLE_ROBUST_THREAD_DISPATCH == FALSE
0311 } else {
0312 T_eq_uint( GetFatalCounter( ctx ), counter );
0313 }
0314 #endif
0315
0316 RestoreRunnerPriority();
0317 SetFatalHandler( NULL, NULL );
0318 }
0319
0320
0321
0322
0323
0324
0325
0326 static void ScoreValFatal_Action_2( ScoreValFatal_Context *ctx )
0327 {
0328 rtems_id id;
0329 unsigned int counter;
0330
0331 SetFatalHandler( FatalBadThreadDispatchEnvironment, ctx );
0332 SetSelfPriority( PRIO_NORMAL );
0333 counter = ResetFatalInfo( ctx );
0334 id = CreateTask( "BENV", PRIO_HIGH );
0335 StartTask( id, ISRDisabledOnDemandThreadDispatchTask, NULL );
0336
0337 #if CPU_ENABLE_ROBUST_THREAD_DISPATCH == FALSE
0338 if ( rtems_configuration_get_maximum_processors() > 1 ) {
0339 #endif
0340 T_eq_uint( GetFatalCounter( ctx ), counter + 1 );
0341 T_eq_int( ctx->source, INTERNAL_ERROR_CORE );
0342 T_eq_ulong( ctx->code, INTERNAL_ERROR_BAD_THREAD_DISPATCH_ENVIRONMENT );
0343 #if CPU_ENABLE_ROBUST_THREAD_DISPATCH == FALSE
0344 } else {
0345 T_eq_uint( GetFatalCounter( ctx ), counter );
0346 }
0347 #endif
0348
0349 RestoreRunnerPriority();
0350 SetFatalHandler( NULL, NULL );
0351 }
0352
0353
0354
0355
0356
0357
0358 static void ScoreValFatal_Action_3( ScoreValFatal_Context *ctx )
0359 {
0360 rtems_id id;
0361 unsigned int counter;
0362
0363 SetFatalHandler( FatalBadThreadDispatchDisableLevel, ctx );
0364 SetSelfPriority( PRIO_NORMAL );
0365 counter = ResetFatalInfo( ctx );
0366 id = CreateTask( "BLVL", PRIO_HIGH );
0367 StartTask( id, BadLevelThreadDispatchTask, NULL );
0368 T_eq_uint( GetFatalCounter( ctx ), counter + 1 );
0369 T_eq_int( ctx->source, INTERNAL_ERROR_CORE );
0370 T_eq_ulong( ctx->code, INTERNAL_ERROR_BAD_THREAD_DISPATCH_DISABLE_LEVEL );
0371 RestoreRunnerPriority();
0372 SetFatalHandler( NULL, NULL );
0373 }
0374
0375
0376
0377
0378
0379 static void ScoreValFatal_Action_4( ScoreValFatal_Context *ctx )
0380 {
0381 rtems_extensions_table extensions;
0382 rtems_status_code sc;
0383 rtems_id extension_id;
0384 rtems_id task_id;
0385 unsigned int counter;
0386
0387 memset( &extensions, 0, sizeof( extensions ) );
0388 extensions.thread_create = ThreadCreateDeadlock;
0389
0390 sc = rtems_extension_create(
0391 rtems_build_name( 'T', 'E', 'X', 'T' ),
0392 &extensions,
0393 &extension_id
0394 );
0395 T_rsc_success( sc );
0396
0397 deadlock_mutex = CreateMutex();
0398
0399 SetFatalHandler( FatalJumpBack, ctx );
0400 SetSelfPriority( PRIO_NORMAL );
0401 counter = ResetFatalInfo( ctx );
0402
0403 ObtainMutex( deadlock_mutex );
0404
0405 task_id = CreateTask( "WORK", PRIO_HIGH );
0406 StartTask( task_id, ThreadQueueDeadlockTask, NULL );
0407
0408 if ( setjmp( before_fatal ) == 0 ) {
0409 (void) CreateTask( "DLCK", PRIO_NORMAL );
0410 }
0411
0412 ReleaseMutex( deadlock_mutex );
0413
0414 T_eq_uint( GetFatalCounter( ctx ), counter + 1 );
0415 T_eq_int( ctx->source, INTERNAL_ERROR_CORE );
0416 T_eq_ulong( ctx->code, INTERNAL_ERROR_THREAD_QUEUE_DEADLOCK );
0417
0418 RestoreRunnerPriority();
0419
0420 sc = rtems_extension_delete( extension_id );
0421 T_rsc_success( sc );
0422
0423 DeleteMutex( deadlock_mutex );
0424 }
0425
0426
0427
0428
0429
0430
0431 static void ScoreValFatal_Action_5( ScoreValFatal_Context *ctx )
0432 {
0433 unsigned int counter;
0434
0435 SetFatalHandler( FatalJumpBack, ctx );
0436 counter = ResetFatalInfo( ctx );
0437
0438 if ( setjmp( before_fatal ) == 0 ) {
0439 rtems_fatal( 123, 4567890 );
0440 }
0441
0442 T_eq_uint( GetFatalCounter( ctx ), counter + 1 );
0443 T_eq_int( ctx->source, 123 );
0444 T_eq_ulong( ctx->code, 4567890 );
0445 }
0446
0447
0448
0449
0450 T_TEST_CASE_FIXTURE( ScoreValFatal, &ScoreValFatal_Fixture )
0451 {
0452 ScoreValFatal_Context *ctx;
0453
0454 ctx = T_fixture_context();
0455
0456 ScoreValFatal_Action_0( ctx );
0457 ScoreValFatal_Action_1( ctx );
0458 ScoreValFatal_Action_2( ctx );
0459 ScoreValFatal_Action_3( ctx );
0460 ScoreValFatal_Action_4( ctx );
0461 ScoreValFatal_Action_5( ctx );
0462 }
0463
0464