Add a test for the sporadic scheduler

This commit is contained in:
Gregory Nutt 2015-07-24 13:50:31 -06:00
parent e5ebfe35f6
commit 2d46cae060
6 changed files with 289 additions and 5 deletions

View File

@ -1363,3 +1363,6 @@
On very fast processors, there are race conditions that make the test On very fast processors, there are race conditions that make the test
failure. Need better interlocking to assure that the threads actually failure. Need better interlocking to assure that the threads actually
do start at the same time (2015-07-24). do start at the same time (2015-07-24).
* apps/examples/ostest: Add a test for the sporadic scheduler. This
test is failing as of this commit (2015-07-24).

View File

@ -63,15 +63,22 @@ endif
ifneq ($(CONFIG_DISABLE_PTHREAD),y) ifneq ($(CONFIG_DISABLE_PTHREAD),y)
CSRCS += cancel.c cond.c mutex.c sem.c semtimed.c barrier.c CSRCS += cancel.c cond.c mutex.c sem.c semtimed.c barrier.c
ifeq ($(CONFIG_FS_NAMED_SEMAPHORES),y) ifeq ($(CONFIG_FS_NAMED_SEMAPHORES),y)
CSRCS += nsem.c CSRCS += nsem.c
endif endif
ifneq ($(CONFIG_RR_INTERVAL),0)
CSRCS += roundrobin.c
endif # CONFIG_RR_INTERVAL
ifeq ($(CONFIG_MUTEX_TYPES),y) ifeq ($(CONFIG_MUTEX_TYPES),y)
CSRCS += rmutex.c CSRCS += rmutex.c
endif # CONFIG_MUTEX_TYPES endif
ifneq ($(CONFIG_RR_INTERVAL),0)
CSRCS += roundrobin.c
endif
ifeq ($(CONFIG_SCHED_SPORADIC),y)
CSRCS += sporadic.c
endif
endif # CONFIG_DISABLE_PTHREAD endif # CONFIG_DISABLE_PTHREAD
ifneq ($(CONFIG_DISABLE_SIGNALS),y) ifneq ($(CONFIG_DISABLE_SIGNALS),y)

View File

@ -187,6 +187,10 @@ void timer_test(void);
void rr_test(void); void rr_test(void);
/* sporadic.c *************************************************************/
void sporadic_test(void);
/* barrier.c ****************************************************************/ /* barrier.c ****************************************************************/
void barrier_test(void); void barrier_test(void);

View File

@ -474,6 +474,14 @@ static int user_main(int argc, char *argv[])
check_test_memory_usage(); check_test_memory_usage();
#endif #endif
#if !defined(CONFIG_DISABLE_PTHREAD) && defined(CONFIG_SCHED_SPORADIC)
/* Verify sporadic scheduling */
printf("\nuser_main: sporadic scheduler test\n");
sporadic_test();
check_test_memory_usage();
#endif
#ifndef CONFIG_DISABLE_PTHREAD #ifndef CONFIG_DISABLE_PTHREAD
/* Verify pthread barriers */ /* Verify pthread barriers */

View File

@ -195,7 +195,7 @@ void rr_test(void)
printf("rr_test: Set thread policy to SCHED_RR\n"); printf("rr_test: Set thread policy to SCHED_RR\n");
} }
/* This semaphore will prevent anything from running */ /* This semaphore will prevent anything from running until we are ready */
sched_lock(); sched_lock();
sem_init(&g_rrsem, 0, 0); sem_init(&g_rrsem, 0, 0);
@ -231,6 +231,7 @@ void rr_test(void)
pthread_join(get_primes2_thread, &result); pthread_join(get_primes2_thread, &result);
pthread_join(get_primes1_thread, &result); pthread_join(get_primes1_thread, &result);
printf("rr_test: Done\n"); printf("rr_test: Done\n");
sem_destroy(&g_rrsem);
} }
#endif /* CONFIG_RR_INTERVAL */ #endif /* CONFIG_RR_INTERVAL */

261
examples/ostest/sporadic.c Normal file
View File

@ -0,0 +1,261 @@
/***********************************************************************
* apps/examples/ostest/sporadic.c
*
* Copyright (C) 2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
***********************************************************************/
/***********************************************************************
* Included Files
***********************************************************************/
#include <nuttx/config.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <sched.h>
#include "ostest.h"
#ifdef CONFIG_SCHED_SPORADIC
/***********************************************************************
* Pre-processor Definitions
***********************************************************************/
#ifndef NULL
# define NULL (void*)0
#endif
/***********************************************************************
* Private Data
***********************************************************************/
static sem_t g_sporadic_sem;
/***********************************************************************
* Private Functions
***********************************************************************/
static void *fifo_func(void *parameter)
{
struct sched_param param;
int ret;
int i;
while (sem_wait(&g_sporadic_sem) < 0);
for (;;)
{
for (i = 0; i < 1000; i++)
{
ret = sched_getparam(0, &param);
if (ret < 0)
{
printf("ERROR: sched_getparam failed\n");
return NULL;
}
}
printf("FIFO: %d\n", param.sched_priority);
}
}
static void *sporadic_func(void *parameter)
{
struct sched_param param;
int prio = 0;
int ret;
int i;
while (sem_wait(&g_sporadic_sem) < 0);
for (;;)
{
for (i = 0; i < 1000; i++)
{
ret = sched_getparam(0, &param);
if (ret < 0)
{
printf("ERROR: sched_getparam failed\n");
return NULL;
}
if (prio != param.sched_priority)
{
break;
}
}
prio = param.sched_priority;
printf("SPORADIC: %d\n", prio);
}
}
/***********************************************************************
* Public Functions
***********************************************************************/
void sporadic_test(void)
{
pthread_t sporadic_thread = (pthread_t)0;
pthread_t fifo_thread = (pthread_t)0;
#ifdef SDCC
pthread_addr_t result;
#endif
FAR void *result;
struct sched_param myparam;
struct sched_param sparam;
int prio_min;
int prio_max;
int prio_low;
int prio_mid;
int prio_high;
pthread_attr_t attr;
int ret;
printf("sporadic_test: Initializing semaphore to 0\n");
sem_init(&g_sporadic_sem, 0, 0);
prio_min = sched_get_priority_min(SCHED_FIFO);
prio_max = sched_get_priority_max(SCHED_FIFO);
prio_low = prio_min + ((prio_max - prio_min) >> 2);
prio_mid = (prio_min + prio_max) >> 1;
prio_high = prio_max - ((prio_max - prio_min) >> 2);
/* Temporarily set our priority to prio_high + 1 */
ret = sched_getparam(0, &myparam);
if (ret != OK)
{
printf("sporadic_test: ERROR: sched_getparam failed, ret=%d\n", ret);
}
sparam.sched_priority = prio_high+1;
ret = sched_setparam(0, &sparam);
if (ret != OK)
{
printf("sporadic_test: ERROR: sched_setparam failed, ret=%d\n", ret);
}
ret = pthread_attr_init(&attr);
if (ret != OK)
{
printf("sporadic_test: ERROR: pthread_attr_init failed, ret=%d\n", ret);
}
/* This semaphore will prevent anything from running until we are ready */
sched_lock();
sem_init(&g_sporadic_sem, 0, 0);
/* Start a FIFO thread at the middle priority */
printf("sporadic_test: Starting FIFO thread at priority %d\n", prio_mid);
ret = pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
if (ret != OK)
{
printf("sporadic_test: ERROR: pthread_attr_setschedpolicy failed, ret=%d\n", ret);
}
sparam.sched_priority = prio_mid;
ret = pthread_attr_setschedparam(&attr, &sparam);
if (ret != OK)
{
printf("sporadic_test: ERROR: pthread_attr_setschedparam failed, ret=%d\n", ret);
}
ret = pthread_create(&fifo_thread, &attr, fifo_func, NULL);
if (ret != 0)
{
printf("sporadic_test: ERROR: FIFO thread creation failed: %d\n", ret);
}
/* Start a sporadic thread, with the following parameters: */
printf("sporadic_test: Starting sporadic thread at priority %d/\n", prio_high, prio_low);
ret = pthread_attr_setschedpolicy(&attr, SCHED_SPORADIC);
if (ret != OK)
{
printf("sporadic_test: ERROR: pthread_attr_setschedpolicy failed, ret=%d\n", ret);
}
sparam.sched_priority = prio_high;
sparam.sched_ss_low_priority = prio_low;
sparam.sched_ss_repl_period.tv_sec = 4;
sparam.sched_ss_repl_period.tv_nsec = 0;
sparam.sched_ss_init_budget.tv_sec = 2;
sparam.sched_ss_max_repl = 5;
ret = pthread_attr_setschedparam(&attr, &sparam);
if (ret != OK)
{
printf("sporadic_test: ERROR: pthread_attr_setsched param failed, ret=%d\n", ret);
}
ret = pthread_create(&sporadic_thread, &attr, sporadic_func, (pthread_addr_t)1);
if (ret != 0)
{
printf("sporadic_test: ERROR: sporadic thread creation failed: %d\n", ret);
}
sem_post(&g_sporadic_sem);
sem_post(&g_sporadic_sem);
/* Wait a while then kill the FIFO thread */
sleep(12);
ret = pthread_cancel(fifo_thread);
pthread_join(fifo_thread, &result);
/* Wait a bit longer */
sleep(12);
ret = pthread_cancel(sporadic_thread);
pthread_join(sporadic_thread, &result);
sched_unlock();
printf("sporadic_test: Done\n");
sem_destroy(&g_sporadic_sem);
ret = sched_setparam(0, &myparam);
if (ret != OK)
{
printf("sporadic_test: ERROR: sched_setparam failed, ret=%d\n", ret);
}
}
#endif /* CONFIG_SCHED_SPORADIC */