mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-09-23 03:56:16 +08:00
validation: Test scheduler detail
This particular state during a reconsider help request scheduler operation was only covered by the existing test suites under some timing conditions. Update #3716.
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
|
||||
* Copyright (C) 2021, 2022 embedded brains GmbH (http://www.embedded-brains.de)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -55,6 +55,7 @@
|
||||
#include <rtems.h>
|
||||
#include <rtems/test-scheduler.h>
|
||||
#include <rtems/score/percpu.h>
|
||||
#include <rtems/score/schedulersmp.h>
|
||||
#include <rtems/score/threadimpl.h>
|
||||
|
||||
#include "tx-support.h"
|
||||
@@ -213,6 +214,24 @@
|
||||
*
|
||||
* - Clean up all used resources.
|
||||
*
|
||||
* - Create three worker threads and a mutex. Use the mutex and the worker to
|
||||
* check that a not scheduled thread does not get removed from the set of
|
||||
* ready threads of a scheduler when a help request is reconsidered.
|
||||
*
|
||||
* - Prevent that worker B can perform a post-switch cleanup.
|
||||
*
|
||||
* - Give worker C a lower priority than worker B. Worker B will try to
|
||||
* finish the thread dispatch by doing a post-switch cleanup. The
|
||||
* post-switch cleanup cannot progress since the runner owns the thread
|
||||
* state lock. Wait until the other processor waits on the thread state
|
||||
* lock of worker B.
|
||||
*
|
||||
* - Give worker C a higher priority than worker B. Let worker B do its
|
||||
* post-switch cleanup which will carry out the reconsider help requests
|
||||
* for a not scheduled thread.
|
||||
*
|
||||
* - Clean up all used resources.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
@@ -250,7 +269,17 @@ typedef struct {
|
||||
/**
|
||||
* @brief This member contains the worker busy status.
|
||||
*/
|
||||
volatile bool busy[ WORKER_COUNT ];;
|
||||
volatile bool busy[ WORKER_COUNT ];
|
||||
|
||||
/**
|
||||
* @brief This member contains an ISR lock context.
|
||||
*/
|
||||
ISR_lock_Context lock_context;
|
||||
|
||||
/**
|
||||
* @brief This member contains a counter.
|
||||
*/
|
||||
uint32_t counter;
|
||||
|
||||
/**
|
||||
* @brief If this member is true, then the worker shall be in the busy loop.
|
||||
@@ -686,6 +715,51 @@ static void CleanupOwnerBlocked( Context *ctx )
|
||||
SetScheduler( ctx->worker_id[ WORKER_C ], SCHEDULER_A_ID, PRIO_HIGH );
|
||||
}
|
||||
|
||||
static void ReconsiderHelpRequestB(
|
||||
void *arg,
|
||||
const T_scheduler_event *event,
|
||||
T_scheduler_when when
|
||||
)
|
||||
{
|
||||
Context *ctx;
|
||||
|
||||
(void) when;
|
||||
ctx = arg;
|
||||
|
||||
if ( event->operation == T_SCHEDULER_RECONSIDER_HELP_REQUEST ) {
|
||||
Scheduler_SMP_Node *node;
|
||||
|
||||
node = (Scheduler_SMP_Node *) event->node;
|
||||
T_eq_int( node->state, SCHEDULER_SMP_NODE_READY );
|
||||
++ctx->counter;
|
||||
}
|
||||
}
|
||||
|
||||
static void ReleaseThreadLockB(
|
||||
void *arg,
|
||||
const T_scheduler_event *event,
|
||||
T_scheduler_when when
|
||||
)
|
||||
{
|
||||
Context *ctx;
|
||||
|
||||
ctx = arg;
|
||||
|
||||
if (
|
||||
when == T_SCHEDULER_AFTER &&
|
||||
event->operation == T_SCHEDULER_UPDATE_PRIORITY
|
||||
) {
|
||||
Thread_Control *worker_b;
|
||||
|
||||
T_scheduler_set_event_handler( ReconsiderHelpRequestB, ctx );
|
||||
|
||||
worker_b = GetThread( ctx->worker_id[ WORKER_B ] );
|
||||
T_eq_int( worker_b->Scheduler.state, THREAD_SCHEDULER_READY );
|
||||
|
||||
_Thread_State_release_critical( worker_b, &ctx->lock_context );
|
||||
}
|
||||
}
|
||||
|
||||
static void Worker( rtems_task_argument arg, WorkerIndex worker )
|
||||
{
|
||||
Context *ctx;
|
||||
@@ -1232,6 +1306,64 @@ static void ScoreSchedSmpValSmp_Action_16( ScoreSchedSmpValSmp_Context *ctx )
|
||||
CleanupOwnerBlocked( ctx );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create three worker threads and a mutex. Use the mutex and the
|
||||
* worker to check that a not scheduled thread does not get removed from the
|
||||
* set of ready threads of a scheduler when a help request is reconsidered.
|
||||
*/
|
||||
static void ScoreSchedSmpValSmp_Action_17( ScoreSchedSmpValSmp_Context *ctx )
|
||||
{
|
||||
Thread_Control *worker_b;
|
||||
|
||||
SetScheduler( ctx->worker_id[ WORKER_B ], SCHEDULER_B_ID, PRIO_NORMAL );
|
||||
SetScheduler( ctx->worker_id[ WORKER_C ], SCHEDULER_B_ID, PRIO_HIGH );
|
||||
SendAndSync( ctx, WORKER_B, EVENT_OBTAIN );
|
||||
SendEvents( ctx->worker_id[ WORKER_A ], EVENT_OBTAIN );
|
||||
SetPriority( ctx->worker_id[ WORKER_A ], PRIO_LOW );
|
||||
MakeBusy( ctx, WORKER_B );
|
||||
WaitForBusy( ctx, WORKER_B );
|
||||
MakeBusy( ctx, WORKER_C );
|
||||
WaitForBusy( ctx, WORKER_C );
|
||||
|
||||
/*
|
||||
* Prevent that worker B can perform a post-switch cleanup.
|
||||
*/
|
||||
worker_b = GetThread( ctx->worker_id[ WORKER_B ] );
|
||||
_Thread_State_acquire( worker_b, &ctx->lock_context );
|
||||
_ISR_lock_ISR_enable( &ctx->lock_context );
|
||||
|
||||
/*
|
||||
* Give worker C a lower priority than worker B. Worker B will try to finish
|
||||
* the thread dispatch by doing a post-switch cleanup. The post-switch
|
||||
* cleanup cannot progress since the runner owns the thread state lock. Wait
|
||||
* until the other processor waits on the thread state lock of worker B.
|
||||
*/
|
||||
SetPriority( ctx->worker_id[ WORKER_C ], PRIO_LOW );
|
||||
TicketLockWaitForOthers( &worker_b->Join_queue.Queue.Lock, 1 );
|
||||
|
||||
/*
|
||||
* Give worker C a higher priority than worker B. Let worker B do its
|
||||
* post-switch cleanup which will carry out the reconsider help requests for
|
||||
* a not scheduled thread.
|
||||
*/
|
||||
ctx->counter = 0;
|
||||
T_scheduler_set_event_handler( ReleaseThreadLockB, ctx );
|
||||
SetPriority( ctx->worker_id[ WORKER_C ], PRIO_HIGH );
|
||||
T_scheduler_set_event_handler( NULL, NULL );
|
||||
T_eq_u32( ctx->counter, 4 );
|
||||
|
||||
/*
|
||||
* Clean up all used resources.
|
||||
*/
|
||||
StopBusy( ctx, WORKER_B );
|
||||
StopBusy( ctx, WORKER_C );
|
||||
SendAndSync( ctx, WORKER_B, EVENT_RELEASE );
|
||||
SetPriority( ctx->worker_id[ WORKER_A ], PRIO_HIGH );
|
||||
SendEvents( ctx->worker_id[ WORKER_A ], EVENT_RELEASE );
|
||||
SetScheduler( ctx->worker_id[ WORKER_B ], SCHEDULER_A_ID, PRIO_HIGH );
|
||||
SetScheduler( ctx->worker_id[ WORKER_C ], SCHEDULER_A_ID, PRIO_HIGH );
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn void T_case_body_ScoreSchedSmpValSmp( void )
|
||||
*/
|
||||
@@ -1258,6 +1390,7 @@ T_TEST_CASE_FIXTURE( ScoreSchedSmpValSmp, &ScoreSchedSmpValSmp_Fixture )
|
||||
ScoreSchedSmpValSmp_Action_14( ctx );
|
||||
ScoreSchedSmpValSmp_Action_15( ctx );
|
||||
ScoreSchedSmpValSmp_Action_16( ctx );
|
||||
ScoreSchedSmpValSmp_Action_17( ctx );
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
Reference in New Issue
Block a user