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 <rtems/score/statesimpl.h>
0057 #include <rtems/score/threadimpl.h>
0058
0059 #include "ts-config.h"
0060 #include "tx-support.h"
0061
0062 #include <rtems/test.h>
0063
0064
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
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120 typedef struct {
0121
0122
0123
0124 rtems_id worker_id;
0125
0126
0127
0128
0129 rtems_id killer_id;
0130
0131
0132
0133
0134 volatile double fp_obj;
0135
0136
0137
0138
0139 int thread_switch_state;
0140
0141
0142
0143
0144 uintptr_t runner_stack[ 2 ];
0145
0146
0147
0148
0149 uintptr_t worker_stack[ 2 ];
0150 } ScoreThreadValThread_Context;
0151
0152 static ScoreThreadValThread_Context
0153 ScoreThreadValThread_Instance;
0154
0155 typedef ScoreThreadValThread_Context Context;
0156
0157 static bool test_case_executed;
0158
0159 static bool constructor_test_case_executed;
0160
0161 static uint32_t constructor_calls;
0162
0163 static rtems_id constructor_id;
0164
0165 static __attribute__(( __constructor__ )) void Constructor( void )
0166 {
0167 constructor_test_case_executed = test_case_executed;
0168 ++constructor_calls;
0169 constructor_id = rtems_task_self();
0170 }
0171
0172 static void TaskTerminate( rtems_tcb *executing )
0173 {
0174 Context *ctx;
0175
0176 ctx = T_fixture_context();
0177
0178 if ( ctx->worker_id == executing->Object.id ) {
0179 DeleteTask( ctx->killer_id );
0180 }
0181 }
0182
0183 static void WorkerTask( rtems_task_argument arg )
0184 {
0185 (void) arg;
0186 SuspendSelf();
0187 }
0188
0189 static void GoBackToRunner( void *arg )
0190 {
0191 Context *ctx;
0192
0193 ctx = arg;
0194 SetPriority( ctx->worker_id, PRIO_LOW );
0195 }
0196
0197 static void FloatingPointTask( rtems_task_argument arg )
0198 {
0199 Context *ctx;
0200
0201 ctx = (Context *) arg;
0202 ctx->fp_obj *= 1.23;
0203
0204
0205
0206
0207
0208
0209 CallWithinISR( GoBackToRunner, ctx );
0210 }
0211
0212 static void KillerTask( rtems_task_argument arg )
0213 {
0214 Context *ctx;
0215
0216 ctx = (Context *) arg;
0217 DeleteTask( ctx->worker_id );
0218 }
0219
0220 static void TaskSwitch( rtems_tcb *executing, rtems_tcb *heir )
0221 {
0222 Context *ctx;
0223 rtems_id worker_id;
0224 int state;
0225 uintptr_t heir_stack;
0226
0227 ctx = T_fixture_context();
0228 worker_id = ctx->worker_id;
0229 state = ctx->thread_switch_state;
0230 ctx->thread_switch_state = state + 1;
0231 heir_stack = _CPU_Context_Get_SP( &heir->Registers );
0232
0233 switch ( state ) {
0234 case 0:
0235 T_eq_u32( heir->Object.id, worker_id );
0236 SuspendTask( worker_id );
0237 ctx->worker_stack[ 0 ] = heir_stack;
0238 break;
0239 case 1:
0240 T_eq_u32( executing->Object.id, worker_id );
0241 ResumeTask( worker_id );
0242 ctx->runner_stack[ 0 ] = heir_stack;
0243 break;
0244 case 2:
0245 T_eq_u32( heir->Object.id, worker_id );
0246 SuspendTask( worker_id );
0247 ctx->worker_stack[ 1 ] = heir_stack;
0248 break;
0249 case 3:
0250 T_eq_u32( executing->Object.id, worker_id );
0251 ctx->runner_stack[ 1 ] = heir_stack;
0252 break;
0253 default:
0254 T_unreachable();
0255 }
0256 }
0257
0258 static T_fixture ScoreThreadValThread_Fixture = {
0259 .setup = NULL,
0260 .stop = NULL,
0261 .teardown = NULL,
0262 .scope = NULL,
0263 .initial_context = &ScoreThreadValThread_Instance
0264 };
0265
0266
0267
0268
0269
0270
0271
0272 static void ScoreThreadValThread_Action_0( ScoreThreadValThread_Context *ctx )
0273 {
0274 rtems_extensions_table table = {
0275 .thread_terminate = TaskTerminate
0276 };
0277 rtems_status_code sc;
0278 rtems_id id;
0279 rtems_tcb *worker_tcb;
0280
0281 sc = rtems_extension_create(
0282 rtems_build_name( 'T', 'E', 'S', 'T' ),
0283 &table,
0284 &id
0285 );
0286 T_rsc_success( sc );
0287
0288 SetSelfPriority( PRIO_NORMAL );
0289 ctx->worker_id = CreateTask( "WORK", PRIO_HIGH );
0290 worker_tcb = GetThread( ctx->worker_id );
0291 StartTask( ctx->worker_id, WorkerTask, NULL );
0292 ctx->killer_id = CreateTask( "KILL", PRIO_HIGH );
0293 StartTask( ctx->killer_id, KillerTask, ctx );
0294
0295
0296
0297
0298 sc = rtems_event_send( ctx->killer_id, RTEMS_EVENT_0 );
0299 T_rsc( sc, RTEMS_INVALID_ID );
0300
0301
0302
0303
0304 sc = rtems_event_send( ctx->worker_id, RTEMS_EVENT_0 );
0305 T_rsc_success( sc );
0306
0307
0308
0309
0310 T_eq_int(
0311 worker_tcb->Life.state,
0312 THREAD_LIFE_PROTECTED | THREAD_LIFE_TERMINATING
0313 );
0314
0315
0316
0317
0318 T_eq_u32(
0319 worker_tcb->current_state,
0320 STATES_WAITING_FOR_JOIN_AT_EXIT
0321 );
0322
0323
0324
0325
0326 worker_tcb->Life.state = THREAD_LIFE_DETACHED |
0327 THREAD_LIFE_PROTECTED | THREAD_LIFE_TERMINATING;
0328 _Thread_Clear_state( worker_tcb, STATES_WAITING_FOR_JOIN_AT_EXIT );
0329
0330
0331
0332
0333 KillZombies();
0334 RestoreRunnerPriority();
0335
0336 sc = rtems_extension_delete( id );
0337 T_rsc_success( sc );
0338 }
0339
0340
0341
0342
0343
0344 static void ScoreThreadValThread_Action_1( ScoreThreadValThread_Context *ctx )
0345 {
0346 rtems_status_code sc;
0347
0348 SetSelfPriority( PRIO_NORMAL );
0349 sc = rtems_task_create(
0350 rtems_build_name( 'W', 'O', 'R', 'K'),
0351 PRIO_HIGH,
0352 TEST_MINIMUM_STACK_SIZE,
0353 RTEMS_DEFAULT_MODES,
0354 RTEMS_FLOATING_POINT,
0355 &ctx->worker_id
0356 );
0357 T_rsc_success( sc );
0358
0359
0360
0361
0362 StartTask( ctx->worker_id, FloatingPointTask, ctx );
0363
0364
0365
0366
0367 DeleteTask( ctx->worker_id );
0368 KillZombies();
0369
0370
0371
0372
0373 RestoreRunnerPriority();
0374 }
0375
0376
0377
0378
0379 static void ScoreThreadValThread_Action_2( ScoreThreadValThread_Context *ctx )
0380 {
0381 test_case_executed = true;
0382
0383
0384
0385
0386 T_eq_u32( constructor_calls, 1 );
0387
0388
0389
0390
0391
0392 T_eq_u32( constructor_id, rtems_task_self() );
0393
0394
0395
0396
0397 T_false( constructor_test_case_executed );
0398 }
0399
0400
0401
0402
0403
0404
0405 static void ScoreThreadValThread_Action_3( ScoreThreadValThread_Context *ctx )
0406 {
0407 SetSelfPriority( PRIO_NORMAL );
0408 ctx->worker_id = CreateTask( "WORK", PRIO_HIGH );
0409 StartTask( ctx->worker_id, WorkerTask, NULL );
0410
0411 ctx->thread_switch_state = 0;
0412 ctx->runner_stack[ 0 ] = 0;
0413 ctx->runner_stack[ 1 ] = 1;
0414 ctx->worker_stack[ 0 ] = 0;
0415 ctx->worker_stack[ 1 ] = 1;
0416 SetTaskSwitchExtension( TaskSwitch );
0417 ResumeTask( ctx->worker_id );
0418
0419 SetTaskSwitchExtension( NULL );
0420 DeleteTask( ctx->worker_id );
0421 RestoreRunnerPriority();
0422
0423
0424
0425
0426
0427 T_eq_uptr( ctx->runner_stack[ 0 ], ctx->runner_stack[ 1 ] );
0428 T_eq_uptr( ctx->worker_stack[ 0 ], ctx->worker_stack[ 1 ] );
0429 }
0430
0431
0432
0433
0434 T_TEST_CASE_FIXTURE( ScoreThreadValThread, &ScoreThreadValThread_Fixture )
0435 {
0436 ScoreThreadValThread_Context *ctx;
0437
0438 ctx = T_fixture_context();
0439
0440 ScoreThreadValThread_Action_0( ctx );
0441 ScoreThreadValThread_Action_1( ctx );
0442 ScoreThreadValThread_Action_2( ctx );
0443 ScoreThreadValThread_Action_3( ctx );
0444 }
0445
0446