diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2021-08-11 10:00:58 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2021-08-11 10:00:58 +0200 |
commit | 05c79706226b566a180c4e4be0388285f6c70cb6 (patch) | |
tree | 4f5f733e87c6e6da0aa165123b25e83e0b091828 | |
parent | ddc0a1bcf3d90dedd962a15cd1ff6cd64217944f (diff) |
testsuites/validation/tc-task-wake-after.c
-rw-r--r-- | testsuites/validation/tc-task-wake-after.c | 144 |
1 files changed, 120 insertions, 24 deletions
diff --git a/testsuites/validation/tc-task-wake-after.c b/testsuites/validation/tc-task-wake-after.c index 7eed2bbdab..a40e3d7464 100644 --- a/testsuites/validation/tc-task-wake-after.c +++ b/testsuites/validation/tc-task-wake-after.c @@ -54,6 +54,7 @@ #include <rtems.h> #include <rtems/test-scheduler.h> +#include <rtems/score/threaddispatch.h> #include <rtems/score/timecounter.h> #include "tx-support.h" @@ -75,6 +76,12 @@ typedef enum { } RtemsTaskReqWakeAfter_Pre_Ticks; typedef enum { + RtemsTaskReqWakeAfter_Pre_Suspended_Yes, + RtemsTaskReqWakeAfter_Pre_Suspended_No, + RtemsTaskReqWakeAfter_Pre_Suspended_NA +} RtemsTaskReqWakeAfter_Pre_Suspended; + +typedef enum { RtemsTaskReqWakeAfter_Post_Status_Ok, RtemsTaskReqWakeAfter_Post_Status_NA } RtemsTaskReqWakeAfter_Post_Status; @@ -93,6 +100,7 @@ typedef enum { typedef enum { RtemsTaskReqWakeAfter_Post_Scheduler_Block, RtemsTaskReqWakeAfter_Post_Scheduler_Yield, + RtemsTaskReqWakeAfter_Post_Scheduler_Nop, RtemsTaskReqWakeAfter_Post_Scheduler_NA } RtemsTaskReqWakeAfter_Post_Scheduler; @@ -117,6 +125,12 @@ typedef struct { rtems_id worker_id;; /** + * @brief If this member is true, then the worker shall be suspended during + * the rtems_task_wake_after() call. + */ + bool suspended;; + + /** * @brief This member contains the timer information of the worker task. */ TaskTimerInfo timer_info;; @@ -135,7 +149,7 @@ typedef struct { /** * @brief This member defines the pre-condition states for the next action. */ - size_t pcs[ 1 ]; + size_t pcs[ 2 ]; /** * @brief This member indicates if the test action loop is currently @@ -153,8 +167,15 @@ static const char * const RtemsTaskReqWakeAfter_PreDesc_Ticks[] = { "NA" }; +static const char * const RtemsTaskReqWakeAfter_PreDesc_Suspended[] = { + "Yes", + "No", + "NA" +}; + static const char * const * const RtemsTaskReqWakeAfter_PreDesc[] = { RtemsTaskReqWakeAfter_PreDesc_Ticks, + RtemsTaskReqWakeAfter_PreDesc_Suspended, NULL }; @@ -171,11 +192,29 @@ static void Worker( rtems_task_argument arg ) SuspendSelf(); + ctx->now = rtems_clock_get_ticks_since_boot(); + + if ( ctx->suspended ) { + Per_CPU_Control *cpu_self; + + /* + * The rtems_task_wake_after() disables thread dispatching to carry out + * its operations. While thread dispatching is disabled, when an + * interrupt suspends the calling task, the suspended task executes + * until it enables thread dispatching. We simulate this situation + * with the code below. Where the system was built with SMP support + * enabled, other processors may suspend an executing task in parallel. + * This case is also simulated by the code below. + */ + cpu_self = _Thread_Dispatch_disable(); + SuspendSelf(); + cpu_self->dispatch_necessary = false; + _Thread_Dispatch_enable( cpu_self ); + } + log = T_scheduler_record_4( &ctx->scheduler_log ); T_null( log ); - ctx->now = rtems_clock_get_ticks_since_boot(); - ctx->status = rtems_task_wake_after( ctx->ticks ); (void) T_scheduler_record( NULL ); @@ -209,6 +248,33 @@ static void RtemsTaskReqWakeAfter_Pre_Ticks_Prepare( } } +static void RtemsTaskReqWakeAfter_Pre_Suspended_Prepare( + RtemsTaskReqWakeAfter_Context *ctx, + RtemsTaskReqWakeAfter_Pre_Suspended state +) +{ + switch ( state ) { + case RtemsTaskReqWakeAfter_Pre_Suspended_Yes: { + /* + * While the calling task is suspended. + */ + ctx->suspended = true; + break; + } + + case RtemsTaskReqWakeAfter_Pre_Suspended_No: { + /* + * While the calling task is not suspended. + */ + ctx->suspended = false; + break; + } + + case RtemsTaskReqWakeAfter_Pre_Suspended_NA: + break; + } +} + static void RtemsTaskReqWakeAfter_Post_Status_Check( RtemsTaskReqWakeAfter_Context *ctx, RtemsTaskReqWakeAfter_Post_Status state @@ -309,6 +375,15 @@ static void RtemsTaskReqWakeAfter_Post_Scheduler_Check( break; } + case RtemsTaskReqWakeAfter_Post_Scheduler_Nop: { + /* + * The calling task shall not carry out a scheduler operation through the + * rtems_task_wake_after() call. + */ + T_eq_sz( ctx->scheduler_log.header.recorded, 0 ); + break; + } + case RtemsTaskReqWakeAfter_Post_Scheduler_NA: break; } @@ -357,25 +432,39 @@ static void RtemsTaskReqWakeAfter_Action( RtemsTaskReqWakeAfter_Context *ctx ) ResumeTask( ctx->worker_id ); (void) T_scheduler_record( NULL ); GetTaskTimerInfo( ctx->worker_id, &ctx->timer_info ); + + if ( ctx->suspended ) { + ResumeTask( ctx->worker_id ); + } + FinalClockTick(); } typedef struct { - uint8_t Skip : 1; - uint8_t Pre_Ticks_NA : 1; - uint8_t Post_Status : 1; - uint8_t Post_Timer : 2; - uint8_t Post_Expire : 1; - uint8_t Post_Scheduler : 2; + uint16_t Skip : 1; + uint16_t Pre_Ticks_NA : 1; + uint16_t Pre_Suspended_NA : 1; + uint16_t Post_Status : 1; + uint16_t Post_Timer : 2; + uint16_t Post_Expire : 1; + uint16_t Post_Scheduler : 2; } RtemsTaskReqWakeAfter_Entry; static const RtemsTaskReqWakeAfter_Entry RtemsTaskReqWakeAfter_Entries[] = { - { 0, 0, RtemsTaskReqWakeAfter_Post_Status_Ok, + { 0, 0, 0, RtemsTaskReqWakeAfter_Post_Status_Ok, + RtemsTaskReqWakeAfter_Post_Timer_Inactive, + RtemsTaskReqWakeAfter_Post_Expire_NA, + RtemsTaskReqWakeAfter_Post_Scheduler_Nop }, + { 0, 0, 0, RtemsTaskReqWakeAfter_Post_Status_Ok, RtemsTaskReqWakeAfter_Post_Timer_Inactive, RtemsTaskReqWakeAfter_Post_Expire_NA, RtemsTaskReqWakeAfter_Post_Scheduler_Yield }, - { 0, 0, RtemsTaskReqWakeAfter_Post_Status_Ok, + { 0, 0, 0, RtemsTaskReqWakeAfter_Post_Status_Ok, + RtemsTaskReqWakeAfter_Post_Timer_Ticks, + RtemsTaskReqWakeAfter_Post_Expire_Relative, + RtemsTaskReqWakeAfter_Post_Scheduler_Nop }, + { 0, 0, 0, RtemsTaskReqWakeAfter_Post_Status_Ok, RtemsTaskReqWakeAfter_Post_Timer_Ticks, RtemsTaskReqWakeAfter_Post_Expire_Relative, RtemsTaskReqWakeAfter_Post_Scheduler_Block } @@ -383,7 +472,7 @@ RtemsTaskReqWakeAfter_Entries[] = { static const uint8_t RtemsTaskReqWakeAfter_Map[] = { - 0, 1 + 0, 1, 2, 3 }; static size_t RtemsTaskReqWakeAfter_Scope( void *arg, char *buf, size_t n ) @@ -433,18 +522,25 @@ T_TEST_CASE_FIXTURE( RtemsTaskReqWakeAfter, &RtemsTaskReqWakeAfter_Fixture ) ctx->pcs[ 0 ] < RtemsTaskReqWakeAfter_Pre_Ticks_NA; ++ctx->pcs[ 0 ] ) { - RtemsTaskReqWakeAfter_Entry entry; - - entry = RtemsTaskReqWakeAfter_GetEntry( index ); - ++index; - - RtemsTaskReqWakeAfter_Prepare( ctx ); - RtemsTaskReqWakeAfter_Pre_Ticks_Prepare( ctx, ctx->pcs[ 0 ] ); - RtemsTaskReqWakeAfter_Action( ctx ); - RtemsTaskReqWakeAfter_Post_Status_Check( ctx, entry.Post_Status ); - RtemsTaskReqWakeAfter_Post_Timer_Check( ctx, entry.Post_Timer ); - RtemsTaskReqWakeAfter_Post_Expire_Check( ctx, entry.Post_Expire ); - RtemsTaskReqWakeAfter_Post_Scheduler_Check( ctx, entry.Post_Scheduler ); + for ( + ctx->pcs[ 1 ] = RtemsTaskReqWakeAfter_Pre_Suspended_Yes; + ctx->pcs[ 1 ] < RtemsTaskReqWakeAfter_Pre_Suspended_NA; + ++ctx->pcs[ 1 ] + ) { + RtemsTaskReqWakeAfter_Entry entry; + + entry = RtemsTaskReqWakeAfter_GetEntry( index ); + ++index; + + RtemsTaskReqWakeAfter_Prepare( ctx ); + RtemsTaskReqWakeAfter_Pre_Ticks_Prepare( ctx, ctx->pcs[ 0 ] ); + RtemsTaskReqWakeAfter_Pre_Suspended_Prepare( ctx, ctx->pcs[ 1 ] ); + RtemsTaskReqWakeAfter_Action( ctx ); + RtemsTaskReqWakeAfter_Post_Status_Check( ctx, entry.Post_Status ); + RtemsTaskReqWakeAfter_Post_Timer_Check( ctx, entry.Post_Timer ); + RtemsTaskReqWakeAfter_Post_Expire_Check( ctx, entry.Post_Expire ); + RtemsTaskReqWakeAfter_Post_Scheduler_Check( ctx, entry.Post_Scheduler ); + } } } |