posix: Fix poradic server initial CPU budget

Update #2738.
This commit is contained in:
Sebastian Huber
2016-06-15 10:39:09 +02:00
parent d6467102e2
commit 917884c408
5 changed files with 118 additions and 24 deletions

View File

@@ -54,9 +54,13 @@ extern Thread_Information _POSIX_Threads_Information;
extern pthread_attr_t _POSIX_Threads_Default_attributes;
RTEMS_INLINE_ROUTINE void _POSIX_Threads_Sporadic_timer_insert(
Thread_Control *the_thread,
POSIX_API_Control *api
)
{
the_thread->cpu_time_budget =
_Timespec_To_ticks( &api->Attributes.schedparam.sched_ss_init_budget );
_Watchdog_Per_CPU_insert_relative(
&api->Sporadic_timer,
_Per_CPU_Get(),

View File

@@ -113,11 +113,8 @@ void _POSIX_Threads_Sporadic_budget_TSR( Watchdog_Control *watchdog )
_Thread_State_acquire( the_thread, &lock_context );
the_thread->cpu_time_budget =
_Timespec_To_ticks( &api->schedparam.sched_ss_init_budget );
_Watchdog_Per_CPU_remove_relative( &api->Sporadic_timer );
_POSIX_Threads_Sporadic_timer_insert( api );
_POSIX_Threads_Sporadic_timer_insert( the_thread, api );
new_priority = _POSIX_Priority_To_core( api->schedparam.sched_priority );

View File

@@ -229,6 +229,12 @@ int pthread_create(
api->schedpolicy = schedpolicy;
api->schedparam = schedparam;
if ( schedpolicy == SCHED_SPORADIC ) {
_ISR_lock_ISR_disable( &lock_context );
_POSIX_Threads_Sporadic_timer_insert( the_thread, api );
_ISR_lock_ISR_enable( &lock_context );
}
/*
* POSIX threads are allocated and started in one operation.
*/
@@ -249,12 +255,6 @@ int pthread_create(
}
#endif
if ( schedpolicy == SCHED_SPORADIC ) {
_ISR_lock_ISR_disable( &lock_context );
_POSIX_Threads_Sporadic_timer_insert( api );
_ISR_lock_ISR_enable( &lock_context );
}
/*
* Return the id and indicate we successfully created the thread
*/

View File

@@ -11,15 +11,88 @@
#include "config.h"
#endif
#include <sched.h>
#include <sys/time.h>
#include <errno.h>
#include <inttypes.h>
#include <sched.h>
#include <stdint.h>
#include <unistd.h>
#include <pmacros.h>
const char rtems_test_name[] = "PSX 12";
#define SS_REPL_PERIOD_US 200000
#define SS_INIT_BUDGET_US 100000
#define SS_PRIO_LOW 1
#define SS_PRIO_HIGH 2
#define SS_SAMPLE_PERIODS 3
typedef struct {
uint64_t start;
struct {
uint64_t high;
uint64_t low;
} samples[ SS_SAMPLE_PERIODS ];
} test_context;
static test_context test_instance;
static void wait_for_prio( int prio )
{
int status;
int policy;
struct sched_param param;
do {
status = pthread_getschedparam( pthread_self(), &policy, &param );
rtems_test_assert( status == 0 );
} while ( prio != param.sched_priority );
}
static uint64_t timeval_to_us( const struct timeval *tv )
{
uint64_t t;
t = tv->tv_sec;
t *= 1000000;
t += tv->tv_usec;
return t;
}
static uint64_t now( void )
{
struct timeval now;
gettimeofday( &now, NULL );
return timeval_to_us( &now );
}
static uint64_t delta( test_context *ctx )
{
return now() - ctx->start;
}
static void *sporadic_server( void *argument )
{
test_context *ctx;
size_t i;
ctx = argument;
for ( i = 0 ; i < SS_SAMPLE_PERIODS ; ++i ) {
wait_for_prio( SS_PRIO_LOW );
ctx->samples[ i ].high = delta( ctx );
wait_for_prio( SS_PRIO_HIGH );
ctx->samples[ i ].low = delta( ctx );
}
puts( "Sporadic Server: exitting" );
return NULL;
@@ -27,13 +100,17 @@ static void *sporadic_server( void *argument )
static void *POSIX_Init( void *argument )
{
test_context *ctx;
int status;
pthread_attr_t attr;
pthread_t thread;
struct sched_param schedparam;
size_t i;
TEST_BEGIN();
ctx = &test_instance;
/* set the time of day, and print our buffer in multiple ways */
set_time( TM_FRIDAY, TM_MAY, 24, 96, 11, 5, 0 );
@@ -86,12 +163,12 @@ static void *POSIX_Init( void *argument )
/* invalid sched_ss_low_priority error */
schedparam.sched_ss_repl_period.tv_sec = 2;
schedparam.sched_ss_repl_period.tv_nsec = 0;
schedparam.sched_ss_init_budget.tv_sec = 1;
schedparam.sched_ss_init_budget.tv_nsec = 0;
schedparam.sched_ss_repl_period.tv_sec = 0;
schedparam.sched_ss_repl_period.tv_nsec = SS_REPL_PERIOD_US * 1000;
schedparam.sched_ss_init_budget.tv_sec = 0;
schedparam.sched_ss_init_budget.tv_nsec = SS_INIT_BUDGET_US * 1000;
schedparam.sched_priority = 200;
schedparam.sched_priority = SS_PRIO_HIGH;
schedparam.sched_ss_low_priority = -1;
status = pthread_attr_setschedparam( &attr, &schedparam );
@@ -103,25 +180,35 @@ static void *POSIX_Init( void *argument )
/* create a thread as a sporadic server */
schedparam.sched_ss_repl_period.tv_sec = 2;
schedparam.sched_ss_repl_period.tv_nsec = 0;
schedparam.sched_ss_init_budget.tv_sec = 1;
schedparam.sched_ss_init_budget.tv_nsec = 0;
schedparam.sched_ss_repl_period.tv_sec = 0;
schedparam.sched_ss_repl_period.tv_nsec = SS_REPL_PERIOD_US * 1000;
schedparam.sched_ss_init_budget.tv_sec = 0;
schedparam.sched_ss_init_budget.tv_nsec = SS_INIT_BUDGET_US * 1000;
schedparam.sched_priority = sched_get_priority_max( SCHED_FIFO );
schedparam.sched_ss_low_priority = sched_get_priority_max( SCHED_FIFO ) - 6;
schedparam.sched_priority = SS_PRIO_HIGH;
schedparam.sched_ss_low_priority = SS_PRIO_LOW;
status = pthread_attr_setschedparam( &attr, &schedparam );
rtems_test_assert( !status );
puts( "Init: pthread_create - SUCCESSFUL" );
status = pthread_create( &thread, &attr, sporadic_server, NULL );
/* Align with clock tick */
usleep( 1 );
ctx->start = now();
status = pthread_create( &thread, &attr, sporadic_server, ctx );
rtems_test_assert( !status );
status = pthread_join( thread, NULL );
rtems_test_assert( !status );
/* switch to Task_1 */
for ( i = 0 ; i < SS_SAMPLE_PERIODS ; ++i ) {
printf( "[%zu] H %6" PRIu64 "us\n", i, ctx->samples[ i ].high );
printf( "[%zu] L %6" PRIu64 "us\n", i, ctx->samples[ i ].low );
rtems_test_assert( ctx->samples[ i ].low / SS_REPL_PERIOD_US == i + 1 );
}
TEST_END();
rtems_test_exit( 0 );

View File

@@ -8,4 +8,10 @@ Init: pthread_create - EINVAL (replenish < budget)
Init: pthread_create - EINVAL (invalid sched_ss_low_priority)
Init: pthread_create - SUCCESSFUL
Sporadic Server: exitting
[0] H 99902us
[0] L 200008us
[1] H 289908us
[1] L 400009us
[2] H 489903us
[2] L 600009us
*** END OF TEST PSX 12 ***