diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2012-04-16 08:56:41 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2012-04-16 08:56:41 +0200 |
commit | 9502079586fa3034865bdcff91cf4e5f881762f0 (patch) | |
tree | 93a289c651acfcb522fcd06e01c62f661e5bf26a | |
parent | Filesystem: Remove NULL pointer check (diff) | |
parent | PR1908: QoS library for CBS scheduler (diff) | |
download | rtems-9502079586fa3034865bdcff91cf4e5f881762f0.tar.bz2 |
Merge branch 'upstream'
28 files changed, 1651 insertions, 88 deletions
diff --git a/c/src/lib/libbsp/arm/stm32f4/Makefile.am b/c/src/lib/libbsp/arm/stm32f4/Makefile.am index 88445fe3a4..a54d974a05 100644 --- a/c/src/lib/libbsp/arm/stm32f4/Makefile.am +++ b/c/src/lib/libbsp/arm/stm32f4/Makefile.am @@ -79,6 +79,7 @@ libbsp_a_SOURCES += startup/bspstarthook.c libbsp_a_SOURCES += startup/bspreset.c libbsp_a_SOURCES += startup/io.c libbsp_a_SOURCES += startup/rcc.c +libbsp_a_SOURCES += startup/start-config-io.c # IRQ libbsp_a_SOURCES += ../../shared/src/irq-default-handler.c diff --git a/c/src/lib/libbsp/arm/stm32f4/configure.ac b/c/src/lib/libbsp/arm/stm32f4/configure.ac index 1e0e7db983..fc1bc9649f 100644 --- a/c/src/lib/libbsp/arm/stm32f4/configure.ac +++ b/c/src/lib/libbsp/arm/stm32f4/configure.ac @@ -35,13 +35,13 @@ RTEMS_BSPOPTS_HELP([STM32F4_PCLK2],[PCLK2 frequency in Hz]) RTEMS_BSPOPTS_SET([STM32F4_USART_BAUD],[*],[115200]) RTEMS_BSPOPTS_HELP([STM32F4_USART_BAUD],[baud for USARTs]) -RTEMS_BSPOPTS_SET([STM32F4_ENABLE_USART_1],[*],[1]) +RTEMS_BSPOPTS_SET([STM32F4_ENABLE_USART_1],[*],[]) RTEMS_BSPOPTS_HELP([STM32F4_ENABLE_USART_1],[enable USART 1]) RTEMS_BSPOPTS_SET([STM32F4_ENABLE_USART_2],[*],[]) RTEMS_BSPOPTS_HELP([STM32F4_ENABLE_USART_2],[enable USART 2]) -RTEMS_BSPOPTS_SET([STM32F4_ENABLE_USART_3],[*],[]) +RTEMS_BSPOPTS_SET([STM32F4_ENABLE_USART_3],[*],[1]) RTEMS_BSPOPTS_HELP([STM32F4_ENABLE_USART_3],[enable USART 3]) RTEMS_BSPOPTS_SET([STM32F4_ENABLE_UART_4],[*],[]) diff --git a/c/src/lib/libbsp/arm/stm32f4/console/usart.c b/c/src/lib/libbsp/arm/stm32f4/console/usart.c index f18dd7124f..40280ad937 100644 --- a/c/src/lib/libbsp/arm/stm32f4/console/usart.c +++ b/c/src/lib/libbsp/arm/stm32f4/console/usart.c @@ -118,48 +118,6 @@ static uint32_t usart_get_bbr( | STM32F4_USART_BBR_DIV_FRACTION(div_fraction); } -#define USART_CFG(port, idx, altfunc) \ - { \ - .pin = STM32F4_GPIO_PIN(port, idx), \ - .mode = STM32F4_GPIO_MODE_AF, \ - .otype = STM32F4_GPIO_OTYPE_PUSH_PULL, \ - .ospeed = STM32F4_GPIO_OSPEED_2_MHZ, \ - .pupd = STM32F4_GPIO_PULL_UP, \ - .af = altfunc \ - } - -static const stm32f4_gpio_config usart_gpio_config [] [2] = { - { - USART_CFG(0, 9, STM32F4_GPIO_AF_USART1), - USART_CFG(0, 10, STM32F4_GPIO_AF_USART1) - }, { - USART_CFG(0, 2, STM32F4_GPIO_AF_USART2), - USART_CFG(0, 3, STM32F4_GPIO_AF_USART2) - }, { - USART_CFG(3, 8, STM32F4_GPIO_AF_USART3), - USART_CFG(3, 9, STM32F4_GPIO_AF_USART3) - }, { - USART_CFG(0, 1, STM32F4_GPIO_AF_UART4), - USART_CFG(0, 2, STM32F4_GPIO_AF_UART4) - }, { - USART_CFG(2, 11, STM32F4_GPIO_AF_UART5), - USART_CFG(2, 12, STM32F4_GPIO_AF_UART5) - }, { - USART_CFG(2, 6, STM32F4_GPIO_AF_USART6), - USART_CFG(2, 7, STM32F4_GPIO_AF_USART6) - } -}; - -static void usart_set_gpio_config(const console_tbl *ct) -{ - const stm32f4_gpio_config *config = usart_gpio_config [ct->ulCtrlPort2]; - - stm32f4_rcc_set_gpio_clock(config [0].pin, true); - stm32f4_gpio_set_config(&config [0]); - stm32f4_rcc_set_gpio_clock(config [1].pin, true); - stm32f4_gpio_set_config(&config [1]); -} - static void usart_initialize(int minor) { const console_tbl *ct = Console_Port_Tbl [minor]; @@ -169,7 +127,6 @@ static void usart_initialize(int minor) stm32f4_rcc_index rcc_index = usart_get_rcc_index(ct); stm32f4_rcc_set_clock(rcc_index, true); - usart_set_gpio_config(ct); usart->cr1 = 0; usart->cr2 = 0; diff --git a/c/src/lib/libbsp/arm/stm32f4/include/io.h b/c/src/lib/libbsp/arm/stm32f4/include/io.h index 539bba567e..032664c48a 100644 --- a/c/src/lib/libbsp/arm/stm32f4/include/io.h +++ b/c/src/lib/libbsp/arm/stm32f4/include/io.h @@ -92,21 +92,80 @@ typedef enum { #define STM32F4_GPIO_INDEX_OF_PIN(pin) ((pin) & 0xf) -typedef struct { - uint32_t pin : 8; - uint32_t mode : 2; - uint32_t otype : 1; - uint32_t ospeed : 2; - uint32_t pupd : 2; - uint32_t af : 4; +typedef union { + struct { + uint32_t pin_first : 8; + uint32_t pin_last : 8; + uint32_t mode : 2; + uint32_t otype : 1; + uint32_t ospeed : 2; + uint32_t pupd : 2; + uint32_t output : 1; + uint32_t af : 4; + uint32_t reserved : 4; + } fields; + + uint32_t value; } stm32f4_gpio_config; +extern const stm32f4_gpio_config stm32f4_start_config_gpio []; + +void stm32f4_gpio_set_clock(int pin, bool set); + void stm32f4_gpio_set_config(const stm32f4_gpio_config *config); +#define STM32F4_GPIO_CONFIG_TERMINAL \ + { { 0xff, 0xff, 0x3, 0x1, 0x3, 0x3, 0x1, 0xf, 0xf } } + +/** + * @brief Sets the GPIO configuration of an array terminated by + * STM32F4_GPIO_CONFIG_TERMINAL. + */ +void stm32f4_gpio_set_config_array(const stm32f4_gpio_config *configs); + void stm32f4_gpio_set_output(int pin, bool set); bool stm32f4_gpio_get_input(int pin); +#define STM32F4_PIN_USART(port, idx, altfunc) \ + { \ + { \ + .pin_first = STM32F4_GPIO_PIN(port, idx), \ + .pin_last = STM32F4_GPIO_PIN(port, idx), \ + .mode = STM32F4_GPIO_MODE_AF, \ + .otype = STM32F4_GPIO_OTYPE_PUSH_PULL, \ + .ospeed = STM32F4_GPIO_OSPEED_2_MHZ, \ + .pupd = STM32F4_GPIO_PULL_UP, \ + .af = altfunc \ + } \ + } + +#define STM32F4_PIN_USART1_TX_PA9 STM32F4_PIN_USART(0, 9, STM32F4_GPIO_AF_USART1) +#define STM32F4_PIN_USART1_TX_PB6 STM32F4_PIN_USART(1, 6, STM32F4_GPIO_AF_USART1) +#define STM32F4_PIN_USART1_RX_PA10 STM32F4_PIN_USART(0, 10, STM32F4_GPIO_AF_USART1) +#define STM32F4_PIN_USART1_RX_PB7 STM32F4_PIN_USART(1, 7, STM32F4_GPIO_AF_USART1) + +#define STM32F4_PIN_USART2_TX_PA2 STM32F4_PIN_USART(0, 2, STM32F4_GPIO_AF_USART2) +#define STM32F4_PIN_USART2_TX_PD5 STM32F4_PIN_USART(3, 5, STM32F4_GPIO_AF_USART2) +#define STM32F4_PIN_USART2_RX_PA3 STM32F4_PIN_USART(0, 3, STM32F4_GPIO_AF_USART2) +#define STM32F4_PIN_USART2_RX_PD6 STM32F4_PIN_USART(3, 6, STM32F4_GPIO_AF_USART2) + +#define STM32F4_PIN_USART3_TX_PC10 STM32F4_PIN_USART(2, 10, STM32F4_GPIO_AF_USART3) +#define STM32F4_PIN_USART3_TX_PD8 STM32F4_PIN_USART(3, 8, STM32F4_GPIO_AF_USART3) +#define STM32F4_PIN_USART3_RX_PC11 STM32F4_PIN_USART(2, 11, STM32F4_GPIO_AF_USART3) +#define STM32F4_PIN_USART3_RX_PD9 STM32F4_PIN_USART(3, 9, STM32F4_GPIO_AF_USART3) + +#define STM32F4_PIN_UART4_TX_PA0 STM32F4_PIN_USART(0, 0, STM32F4_GPIO_AF_UART4) +#define STM32F4_PIN_UART4_TX_PC10 STM32F4_PIN_USART(2, 10, STM32F4_GPIO_AF_UART4) +#define STM32F4_PIN_UART4_RX_PA1 STM32F4_PIN_USART(0, 1, STM32F4_GPIO_AF_UART4) +#define STM32F4_PIN_UART4_RX_PC11 STM32F4_PIN_USART(2, 11, STM32F4_GPIO_AF_UART4) + +#define STM32F4_PIN_UART5_TX_PC12 STM32F4_PIN_USART(2, 12, STM32F4_GPIO_AF_UART5) +#define STM32F4_PIN_UART5_RX_PD2 STM32F4_PIN_USART(3, 2, STM32F4_GPIO_AF_UART5) + +#define STM32F4_PIN_USART6_TX_PC6 STM32F4_PIN_USART(2, 6, STM32F4_GPIO_AF_USART6) +#define STM32F4_PIN_USART6_RX_PC7 STM32F4_PIN_USART(2, 7, STM32F4_GPIO_AF_USART6) + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/c/src/lib/libbsp/arm/stm32f4/include/rcc.h b/c/src/lib/libbsp/arm/stm32f4/include/rcc.h index e2e4d13c79..7d49527b83 100644 --- a/c/src/lib/libbsp/arm/stm32f4/include/rcc.h +++ b/c/src/lib/libbsp/arm/stm32f4/include/rcc.h @@ -88,11 +88,11 @@ typedef enum { STM32F4_RCC_TIM1 = STM32F4_RCC_INDEX(5, 0), } stm32f4_rcc_index; -void stm32f4_rcc_reset(stm32f4_rcc_index index, bool set); +void stm32f4_rcc_reset(stm32f4_rcc_index index); -void stm32f4_rcc_set_clock(stm32f4_rcc_index index, bool set); +void stm32f4_rcc_set_reset(stm32f4_rcc_index index, bool set); -void stm32f4_rcc_set_gpio_clock(int pin, bool set); +void stm32f4_rcc_set_clock(stm32f4_rcc_index index, bool set); void stm32f4_rcc_set_low_power_clock(stm32f4_rcc_index index, bool set); diff --git a/c/src/lib/libbsp/arm/stm32f4/startup/bspstart.c b/c/src/lib/libbsp/arm/stm32f4/startup/bspstart.c index 219c09365c..fb1d5b1f86 100644 --- a/c/src/lib/libbsp/arm/stm32f4/startup/bspstart.c +++ b/c/src/lib/libbsp/arm/stm32f4/startup/bspstart.c @@ -13,13 +13,15 @@ */ #include <bsp.h> +#include <bsp/io.h> +#include <bsp/irq.h> #include <bsp/bootcard.h> #include <bsp/irq-generic.h> -#include <bsp/irq.h> -#include <bsp/linker-symbols.h> void bsp_start(void) { + stm32f4_gpio_set_config_array(&stm32f4_start_config_gpio [0]); + if (bsp_interrupt_initialize() != RTEMS_SUCCESSFUL) { _CPU_Fatal_halt(0xe); } diff --git a/c/src/lib/libbsp/arm/stm32f4/startup/io.c b/c/src/lib/libbsp/arm/stm32f4/startup/io.c index 1bba73cd37..5ecbabe394 100644 --- a/c/src/lib/libbsp/arm/stm32f4/startup/io.c +++ b/c/src/lib/libbsp/arm/stm32f4/startup/io.c @@ -13,9 +13,20 @@ */ #include <bsp/io.h> +#include <bsp/rcc.h> #include <rtems.h> +RTEMS_STATIC_ASSERT(sizeof(stm32f4_gpio_config) == 4, size_of_config); + +void stm32f4_gpio_set_clock(int pin, bool set) +{ + int port = STM32F4_GPIO_PORT_OF_PIN(pin); + stm32f4_rcc_index index = STM32F4_RCC_GPIOA + port; + + stm32f4_rcc_set_clock(index, set); +} + static void clear_and_set( volatile uint32_t *reg, unsigned index, @@ -23,8 +34,7 @@ static void clear_and_set( uint32_t set ) { - uint32_t one = 1; - uint32_t mask = (one << width) - one; + uint32_t mask = (1U << width) - 1U; unsigned shift = width * index; uint32_t val = *reg; @@ -34,34 +44,56 @@ static void clear_and_set( *reg = val; } -void stm32f4_gpio_set_config(const stm32f4_gpio_config *config) +static void set_config(unsigned pin, const stm32f4_gpio_config *config) { - unsigned pin = config->pin; unsigned port = STM32F4_GPIO_PORT_OF_PIN(pin); volatile stm32f4_gpio *gpio = STM32F4_GPIO(port); unsigned index = STM32F4_GPIO_INDEX_OF_PIN(pin); - unsigned af_reg = index >> 8; - unsigned af_index = index & 0x3; + unsigned af_reg = index >> 3; + unsigned af_index = index & 0x7; + int set_or_clear_offset = config->fields.output ? 0 : 16; rtems_interrupt_level level; rtems_interrupt_disable(level); - clear_and_set(&gpio->moder, index, 2, config->mode); - clear_and_set(&gpio->afr [af_reg], af_index, 4, config->af); - clear_and_set(&gpio->pupdr, index, 2, config->pupd); - clear_and_set(&gpio->otyper, index, 1, config->otype); - clear_and_set(&gpio->ospeedr, index, 2, config->ospeed); + gpio->bsrr = 1U << (index + set_or_clear_offset); + clear_and_set(&gpio->pupdr, index, 2, config->fields.pupd); + clear_and_set(&gpio->otyper, index, 1, config->fields.otype); + clear_and_set(&gpio->ospeedr, index, 2, config->fields.ospeed); + clear_and_set(&gpio->afr [af_reg], af_index, 4, config->fields.af); + clear_and_set(&gpio->moder, index, 2, config->fields.mode); rtems_interrupt_enable(level); } +void stm32f4_gpio_set_config(const stm32f4_gpio_config *config) +{ + int current = config->fields.pin_first; + int last = config->fields.pin_last; + + while (current <= last) { + stm32f4_gpio_set_clock(current, true); + set_config(current, config); + ++current; + } +} + +void stm32f4_gpio_set_config_array(const stm32f4_gpio_config *configs) +{ + stm32f4_gpio_config terminal = STM32F4_GPIO_CONFIG_TERMINAL; + + while (configs->value != terminal.value) { + stm32f4_gpio_set_config(configs); + ++configs; + } +} + void stm32f4_gpio_set_output(int pin, bool set) { int port = STM32F4_GPIO_PORT_OF_PIN(pin); volatile stm32f4_gpio *gpio = STM32F4_GPIO(port); int index = STM32F4_GPIO_INDEX_OF_PIN(pin); - int offset = set ? 0 : 16; - uint32_t one = 1; + int set_or_clear_offset = set ? 0 : 16; - gpio->bsrr = one << (index + offset); + gpio->bsrr = 1U << (index + set_or_clear_offset); } bool stm32f4_gpio_get_input(int pin) @@ -69,7 +101,6 @@ bool stm32f4_gpio_get_input(int pin) int port = STM32F4_GPIO_PORT_OF_PIN(pin); volatile stm32f4_gpio *gpio = STM32F4_GPIO(port); int index = STM32F4_GPIO_INDEX_OF_PIN(pin); - uint32_t one = 1; - return (gpio->idr & (one << index)) != 0; + return (gpio->idr & (1U << index)) != 0; } diff --git a/c/src/lib/libbsp/arm/stm32f4/startup/rcc.c b/c/src/lib/libbsp/arm/stm32f4/startup/rcc.c index aa3022cef7..b2cbadff0f 100644 --- a/c/src/lib/libbsp/arm/stm32f4/startup/rcc.c +++ b/c/src/lib/libbsp/arm/stm32f4/startup/rcc.c @@ -13,7 +13,6 @@ */ #include <bsp/rcc.h> -#include <bsp/io.h> #include <rtems.h> @@ -40,7 +39,13 @@ static void rcc_set( rtems_interrupt_enable(level); } -void stm32f4_rcc_reset(stm32f4_rcc_index index, bool set) +void stm32f4_rcc_reset(stm32f4_rcc_index index) +{ + stm32f4_rcc_set_reset(index, true); + stm32f4_rcc_set_reset(index, false); +} + +void stm32f4_rcc_set_reset(stm32f4_rcc_index index, bool set) { volatile stm32f4_rcc *rcc = STM32F4_RCC; @@ -54,14 +59,6 @@ void stm32f4_rcc_set_clock(stm32f4_rcc_index index, bool set) rcc_set(index, set, &rcc->ahbenr [0]); } -void stm32f4_rcc_set_gpio_clock(int pin, bool set) -{ - int port = STM32F4_GPIO_PORT_OF_PIN(pin); - stm32f4_rcc_index index = STM32F4_RCC_GPIOA + port; - - stm32f4_rcc_set_clock(index, set); -} - void stm32f4_rcc_set_low_power_clock(stm32f4_rcc_index index, bool set) { volatile stm32f4_rcc *rcc = STM32F4_RCC; diff --git a/c/src/lib/libbsp/arm/stm32f4/startup/start-config-io.c b/c/src/lib/libbsp/arm/stm32f4/startup/start-config-io.c new file mode 100644 index 0000000000..2cd542ccda --- /dev/null +++ b/c/src/lib/libbsp/arm/stm32f4/startup/start-config-io.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2012 Sebastian Huber. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#include <bsp/io.h> +#include <bsp.h> + +const stm32f4_gpio_config stm32f4_start_config_gpio [] = { + #ifdef STM32F4_ENABLE_USART_1 + STM32F4_PIN_USART1_TX_PA9, + STM32F4_PIN_USART1_RX_PA10, + #endif + #ifdef STM32F4_ENABLE_USART_2 + STM32F4_PIN_USART2_TX_PA2, + STM32F4_PIN_USART2_RX_PA3, + #endif + #ifdef STM32F4_ENABLE_USART_3 + STM32F4_PIN_USART3_TX_PD8, + STM32F4_PIN_USART3_RX_PD9, + #endif + #ifdef STM32F4_ENABLE_UART_4 + STM32F4_PIN_UART4_TX_PA0, + STM32F4_PIN_UART4_RX_PA1, + #endif + #ifdef STM32F4_ENABLE_UART_5 + STM32F4_PIN_UART5_TX_PC12, + STM32F4_PIN_UART5_RX_PD2, + #endif + #ifdef STM32F4_ENABLE_USART_6 + STM32F4_PIN_USART6_TX_PC6, + STM32F4_PIN_USART6_RX_PC7, + #endif + STM32F4_GPIO_CONFIG_TERMINAL +}; diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am index 1cb9dc7b93..9df5533735 100644 --- a/cpukit/Makefile.am +++ b/cpukit/Makefile.am @@ -15,6 +15,7 @@ SUBDIRS += libi2c SUBDIRS += libmisc SUBDIRS += libmd SUBDIRS += libgnat +SUBDIRS += libqos SUBDIRS += wrapup SUBDIRS += zlib diff --git a/cpukit/configure.ac b/cpukit/configure.ac index 24bcdc2f20..30443488db 100644 --- a/cpukit/configure.ac +++ b/cpukit/configure.ac @@ -384,6 +384,7 @@ librpc/Makefile libmisc/Makefile libi2c/Makefile libmd/Makefile +libqos/Makefile zlib/Makefile ftpd/Makefile telnetd/Makefile diff --git a/cpukit/libqos/Makefile.am b/cpukit/libqos/Makefile.am new file mode 100644 index 0000000000..3223dcddd2 --- /dev/null +++ b/cpukit/libqos/Makefile.am @@ -0,0 +1,12 @@ +## +## $Id$ +## + +include $(top_srcdir)/automake/multilib.am +include $(top_srcdir)/automake/compile.am + +include_HEADERS = qreslib.h +include_HEADERS += qreslib.inl + +include $(srcdir)/preinstall.am +include $(top_srcdir)/automake/local.am diff --git a/cpukit/libqos/qreslib.h b/cpukit/libqos/qreslib.h new file mode 100644 index 0000000000..22bbd3ee62 --- /dev/null +++ b/cpukit/libqos/qreslib.h @@ -0,0 +1,81 @@ +/** + * @file qreslib.h + * + * This include file contains all the constants and structures associated + * with the QoS RES library in RTEMS. + * + * @note The library is available only together with CBS scheduler. + */ + +/* + * Copyright (C) 2011 Petr Benes. + * Copyright (C) 2011 On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef CONFIGURE_SCHEDULER_CBS + #error "qreslib.h available only with CONFIGURE_SCHEDULER_CBS" +#endif + +#ifndef _QRESLIB_H +#define _QRESLIB_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> +#include <rtems/score/schedulercbs.h> + +/** Return values. */ +typedef int qos_rv; + +/* Return codes. */ +#define QOS_OK SCHEDULER_CBS_OK +#define QOS_E_GENERIC SCHEDULER_CBS_ERROR_GENERIC +#define QOS_E_NO_MEMORY SCHEDULER_CBS_ERROR_NO_MEMORY +#define QOS_E_INVALID_PARAM SCHEDULER_CBS_ERROR_INVALID_PARAMETER +#define QOS_E_UNAUTHORIZED SCHEDULER_CBS_ERROR_UNAUTHORIZED +#define QOS_E_UNIMPLEMENTED SCHEDULER_CBS_ERROR_UNIMPLEMENTED +#define QOS_E_MISSING_COMPONENT SCHEDULER_CBS_ERROR_MISSING_COMPONENT +#define QOS_E_INCONSISTENT_STATE SCHEDULER_CBS_ERROR_INCONSISTENT_STATE +#define QOS_E_SYSTEM_OVERLOAD SCHEDULER_CBS_ERROR_SYSTEM_OVERLOAD +#define QOS_E_INTERNAL_ERROR SCHEDULER_CBS_ERROR_INTERNAL_ERROR +#define QOS_E_NOT_FOUND SCHEDULER_CBS_ERROR_NOT_FOUND +#define QOS_E_FULL SCHEDULER_CBS_ERROR_FULL +#define QOS_E_EMPTY SCHEDULER_CBS_ERROR_EMPTY +#define QOS_E_NOSERVER SCHEDULER_CBS_ERROR_NOSERVER + +/** Server id. */ +typedef Scheduler_CBS_Server_id qres_sid_t; + +/** Task id. */ +typedef rtems_id tid_t; + +/** Time value. */ +typedef time_t qres_time_t; + +/** Absolute time value */ +typedef time_t qres_atime_t; + +/** Server parameters. */ +typedef struct { + /** Relative deadline of the server. */ + uint32_t P; + /** Budget (computation time) of the server. */ + uint32_t Q; +} qres_params_t; + +#include <qreslib.inl> + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ diff --git a/cpukit/libqos/qreslib.inl b/cpukit/libqos/qreslib.inl new file mode 100644 index 0000000000..094d1e6cdd --- /dev/null +++ b/cpukit/libqos/qreslib.inl @@ -0,0 +1,214 @@ +/** + * @file qreslib.inl + * + * This include file contains all the constants and structures associated + * with the QoS RES library. + * + * @note The library is available only together with CBS scheduler. + */ + +/* + * Copyright (C) 2011 Petr Benes. + * Copyright (C) 2011 On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _QRESLIB_H +# error "Never use <qreslib.inl> directly; include <qreslib.h> instead." +#endif + +#include <rtems/score/schedulercbs.h> + +/** + * @brief qres init + * + * Initializes the QoS RES library. + * + * @return status code. + */ +RTEMS_INLINE_ROUTINE qos_rv qres_init ( void ) +{ + return _Scheduler_CBS_Initialize(); +} + +/** + * @brief qres cleanup + * + * Cleanup resources associated to the QoS RES Library. + * + * @return status code. + */ +RTEMS_INLINE_ROUTINE qos_rv qres_cleanup ( void ) +{ + return _Scheduler_CBS_Cleanup(); +} + +/** + * @brief qres create server + * + * Create a new server with specified parameters. + * + * @return status code. + */ +RTEMS_INLINE_ROUTINE qos_rv qres_create_server ( + qres_params_t *params, + qres_sid_t *server_id +) +{ + return _Scheduler_CBS_Create_server( + (Scheduler_CBS_Parameters *) params, + NULL, + server_id + ); +} + +/** + * @brief qres attach thread + * + * Attach a task to an already existing server. + * + * @return status code. + */ +RTEMS_INLINE_ROUTINE qos_rv qres_attach_thread ( + qres_sid_t server_id, + pid_t pid, + tid_t task_id +) +{ + return _Scheduler_CBS_Attach_thread( server_id, task_id ); +} + +/** + * @brief qres detach thread + * + * Detach from the QoS Server. + * + * @return status code. + */ +RTEMS_INLINE_ROUTINE qos_rv qres_detach_thread ( + qres_sid_t server_id, + pid_t pid, + tid_t task_id +) +{ + return _Scheduler_CBS_Detach_thread( server_id, task_id ); +} + +/** + * @brief qres destroy server + * + * Detach all tasks from a server and destroy it. + * + * @return status code. + */ +RTEMS_INLINE_ROUTINE qos_rv qres_destroy_server ( + qres_sid_t server_id +) +{ + return _Scheduler_CBS_Destroy_server( server_id ); +} + +/** + * @brief qres get server id + * + * Get a thread server id, or QOS_E_NOT_FOUND if it is not + * attached to any server. + * + * @return status code. + */ +RTEMS_INLINE_ROUTINE qos_rv qres_get_sid ( + pid_t pid, + tid_t task_id, + qres_sid_t *server_id +) +{ + return _Scheduler_CBS_Get_server_id( task_id, server_id ); +} + +/** + * @brief qres get params + * + * Retrieve QoS scheduling parameters. + * + * @return status code. + */ +RTEMS_INLINE_ROUTINE qos_rv qres_get_params ( + qres_sid_t server_id, + qres_params_t *params +) +{ + return _Scheduler_CBS_Get_parameters( + server_id, + (Scheduler_CBS_Parameters *) params + ); +} + +/** + * @brief qres set params + * + * Change QoS scheduling parameters. + * + * @return status code. + */ +RTEMS_INLINE_ROUTINE qos_rv qres_set_params ( + qres_sid_t server_id, + qres_params_t *params +) +{ + return _Scheduler_CBS_Set_parameters( + server_id, + (Scheduler_CBS_Parameters *) params + ); +} + +/** + * @brief qres get execution time + * + * Retrieve time info relative to the current server. + * + * @return status code. + */ +RTEMS_INLINE_ROUTINE qos_rv qres_get_exec_time ( + qres_sid_t server_id, + qres_time_t *exec_time, + qres_atime_t *abs_time +) +{ + return _Scheduler_CBS_Get_execution_time( server_id, exec_time, abs_time ); +} + +/** + * @brief qres get current budget + * + * Retrieve remaining budget for the current server instance. + * + * @return status code. + */ +RTEMS_INLINE_ROUTINE qos_rv qres_get_curr_budget ( + qres_sid_t server_id, + qres_time_t *current_budget +) +{ + return _Scheduler_CBS_Get_remaining_budget( server_id, current_budget ); +} + +/** + * @brief qres get approved budget + * + * Retrieve the budget that has been approved for the subsequent + * server instances. + * + * @return status code. + */ +RTEMS_INLINE_ROUTINE qos_rv qres_get_appr_budget ( + qres_sid_t server_id, + qres_time_t *appr_budget +) +{ + return _Scheduler_CBS_Get_approved_budget( server_id, appr_budget ); +} diff --git a/doc/ada_user/Makefile.am b/doc/ada_user/Makefile.am index 9ba4feedae..d4b8bac599 100644 --- a/doc/ada_user/Makefile.am +++ b/doc/ada_user/Makefile.am @@ -27,7 +27,7 @@ COMMON_FILES += \ $(top_builddir)/user/task.texi $(top_builddir)/user/timer.texi \ $(top_builddir)/user/userext.texi $(top_builddir)/user/stackchk.texi \ $(top_builddir)/user/cpuuse.texi $(top_srcdir)/common/cpright.texi \ - $(top_builddir)/user/object.texi + $(top_builddir)/user/object.texi $(top_builddir)/user/cbs.texi FILES = example.texi diff --git a/doc/ada_user/ada_user.texi b/doc/ada_user/ada_user.texi index 279f219922..c7073fc01f 100644 --- a/doc/ada_user/ada_user.texi +++ b/doc/ada_user/ada_user.texi @@ -112,6 +112,7 @@ @include user/cpuuse.texi @include user/object.texi @include user/chains.texi +@include user/cbs.texi @include user/dirstat.texi @include example.texi @include user/glossary.texi @@ -149,6 +150,7 @@ * CPU Usage Statistics:: * Object Services:: * Chains:: +* Constant Bandwidth Server Scheduler API:: * Directive Status Codes:: * Example Application:: * Glossary:: diff --git a/doc/user/Makefile.am b/doc/user/Makefile.am index af2b24dbca..de950b168c 100644 --- a/doc/user/Makefile.am +++ b/doc/user/Makefile.am @@ -17,7 +17,7 @@ GENERATED_FILES = overview.texi concepts.texi datatypes.texi init.texi \ task.texi intr.texi clock.texi timer.texi sem.texi msg.texi event.texi \ signal.texi part.texi region.texi dpmem.texi io.texi fatal.texi \ schedule.texi rtmon.texi barrier.texi bsp.texi userext.texi conf.texi \ - mp.texi stackchk.texi cpuuse.texi object.texi chains.texi + mp.texi stackchk.texi cpuuse.texi object.texi chains.texi cbs.texi COMMON_FILES += $(top_srcdir)/common/cpright.texi @@ -183,9 +183,14 @@ object.texi: object.t chains.texi: chains.t $(BMENU2) -p "Object Services OBJECT_GET_CLASS_INFORMATION - Obtain Class Information" \ -u "Top" \ + -n "Constant Bandwidth Server Scheduler API" < $< > $@ + +cbs.texi: cbs.t + $(BMENU2) -p "Chains Prepend a Node" \ + -u "Top" \ -n "Directive Status Codes" < $< > $@ -EXTRA_DIST = bsp.t clock.t chains.t concepts.t cpuuse.t datatypes.t conf.t \ +EXTRA_DIST = bsp.t cbs.t clock.t chains.t concepts.t cpuuse.t datatypes.t conf.t \ dpmem.t event.t fatal.t init.t intr.t io.t mp.t msg.t overview.t \ part.t region.t rtmon.t sem.t schedule.t signal.t stackchk.t \ task.t timer.t userext.t $(TXT_FILES) $(PNG_FILES) $(EPS_IMAGES) \ diff --git a/doc/user/c_user.texi b/doc/user/c_user.texi index b1bc087406..27c49b15cb 100644 --- a/doc/user/c_user.texi +++ b/doc/user/c_user.texi @@ -111,6 +111,7 @@ @include cpuuse.texi @include object.texi @include chains.texi +@include cbs.texi @include dirstat.texi @include example.texi @include glossary.texi @@ -148,6 +149,7 @@ * CPU Usage Statistics:: * Object Services:: * Chains:: +* Constant Bandwidth Server Scheduler API:: * Directive Status Codes:: * Example Application:: * Glossary:: diff --git a/doc/user/cbs.t b/doc/user/cbs.t new file mode 100644 index 0000000000..425885d321 --- /dev/null +++ b/doc/user/cbs.t @@ -0,0 +1,646 @@ +@c +@c COPYRIGHT (c) 2011. +@c On-Line Applications Research Corporation (OAR). +@c All rights reserved. +@c +@c $Id:$ +@c + +@chapter Constant Bandwidth Server Scheduler API + +@cindex cbs + +@section Introduction + +Unlike simple schedulers, the Constant Bandwidth Server (CBS) requires +a special API for tasks to indicate their scheduling parameters. +The directives provided by the CBS API are: + +@itemize @bullet +@item @code{@value{DIRPREFIX}cbs_initialize} - Initialize the CBS library +@item @code{@value{DIRPREFIX}cbs_cleanup} - Cleanup the CBS library +@item @code{@value{DIRPREFIX}cbs_create_server} - Create a new bandwidth server +@item @code{@value{DIRPREFIX}cbs_attach_thread} - Attach a thread to server +@item @code{@value{DIRPREFIX}cbs_detach_thread} - Detach a thread from server +@item @code{@value{DIRPREFIX}cbs_destroy_server} - Destroy a bandwidth server +@item @code{@value{DIRPREFIX}cbs_get_server_id} - Get an ID of a server +@item @code{@value{DIRPREFIX}cbs_get_parameters} - Get scheduling parameters of a server +@item @code{@value{DIRPREFIX}cbs_set_parameters} - Set scheduling parameters of a server +@item @code{@value{DIRPREFIX}cbs_get_execution_time} - Get elapsed execution time +@item @code{@value{DIRPREFIX}cbs_get_remaining_budget} - Get remainig execution time +@item @code{@value{DIRPREFIX}cbs_get_approved_budget} - Get scheduler approved execution time +@end itemize + +@section Background + +@subsection Constant Bandwidth Server Definitions + +@cindex CBS parameters + +@findex rtems_cbs_parameters + +The Constant Bandwidth Server API enables tasks to communicate with +the scheduler and indicate its scheduling parameters. The scheduler +has to be set up first (by defining @code{CONFIGURE_SCHEDULER_CBS} macro). + +The difference to a plain EDF is the presence of servers. +It is a budget aware extention of the EDF scheduler, therefore, tasks +attached to servers behave in a similar way as with EDF unless they +exceed their budget. + +The intention of servers is reservation of a certain computation +time (budget) of the processor for all subsequent periods. The structure +@code{rtems_cbs_parameters} determines the behavior of +a server. It contains @code{deadline} which is equal to period, +and @code{budget} which is the time the server is allowed to +spend on CPU per each period. The ratio between those two parameters +yields the maximum percentage of the CPU the server can use +(bandwidth). Moreover, thanks to this limitation the overall +utilization of CPU is under control, and the sum of bandwidths +of all servers in the system yields the overall reserved portion +of processor. The rest is still available for ordinary tasks that +are not attached to any server. + +In order to make the server effective to the executing tasks, +tasks have to be attached to the servers. The +@code{rtems_cbs_server_id} is a type denoting an id of a server +and @code{rtems_id} a type for id of tasks. + +@subsection Handling Periodic Tasks + +@cindex CBS periodic tasks + +Each task's execution begins with a default background priority +(see the chapter Scheduling Concepts to understand the concept of +priorities in EDF). Once you decide the tasks should start periodic +execution, you have two possibilities. Either you use only the Rate +Monotonic manager which takes care of periodic behavior, or you declare +deadline and budget using the CBS API in which case these properties +are constant for all subsequent periods, unless you change them using +the CBS API again. Task now only has to indicate and end of +each period using @code{rtems_rate_monotonic_period}. + +@subsection Registering a Callback Function + +@cindex CBS overrun handler + +In case tasks attached to servers are not aware of their execution time +and happen to exceed it, the scheduler does not guarantee execution any +more and pulls the priority of the task to background, which would +possibly lead to immediate preemption (if there is at least one ready +task with a higher pirority). However, the task is not blocked but a +callback function is invoked. The callback function +(@code{rtems_cbs_budget_overrun}) might be optionally registered upon +a server creation (@code{rtems_cbs_create_server}). + +This enables the user to define what should happen in case of budget +overrun. There is obviously no space for huge operations because the +priority is down and not real time any more, however, you still can at +least in release resources for other tasks, restart the task or log an +error information. Since the routine is called directly from kernel, +use @code{printk()} instead of @code{printf()}. + +The calling convention of the callback function is: +@ifset is-C +@findex rtems_asr +@example +void overrun_handler( + rtems_cbs_server_id server_id +); +@end example +@end ifset + +@subsection Limitations + +@cindex CBS limitations + +When using this scheduler you have to keep in mind several things: + +@itemize @bullet +@c it_limitations +@item In the current implementation it is possible to attach only +a single task to each server. +@item If you have a task attached to a server and you voluntatily +block it in the beginning of its execution, its priority will be +probably pulled to background upon unblock, thus not guaranteed +deadline any more. This is because you are effectively raising +computation time of the task. When unbocking, you should be always +sure that the ratio between remaining computation time and remaining +deadline is not higher that the utilization you have agreed with the +scheduler. +@end itemize + +@section Operations + +@subsection Setting up a server + +The directive @code{rtems_cbs_create_server} is used to create a new +server that is characterized by @code{rtems_cbs_parameters}. You also +might want to register the @code{rtems_cbs_budget_overrun} callback +routine. After this step tasks can be attached to the server. The directive +@code{rtems_cbs_set_parameters} can change the scheduling parameters +to avoid destroying and creating a new server again. + +@subsection Attaching Task to a Server + +If a task is attached to a server using @code{rtems_cbs_attach_thread}, +the task's computation time per period is limited by the server and +the deadline (period) of task is equal to deadline of the server which +means if you conclude a period using @code{rate_monotonic_period}, +the length of next period is always determined by the server's property. + +The task has a guaranteed bandwidth given by the server but should not +exceed it, otherwise the priority is pulled to background until the +start of next period and the @code{rtems_cbs_budget_overrun} callback +function is invoked. + +When attaching a task to server, the preemptability flag of the task +is raised, otherwise it would not be possible to control the execution +of the task. + +@subsection Detaching Task from a Server + +The directive @code{rtems_cbs_detach_thread} is just an inverse +operation to the previous one, the task continues its execution with +the initial priority. + +Preemptability of the task is restored to the initial value. + +@subsection Examples + +The following example presents a simple common use of the API. + +You can see the initialization and cleanup call here, if there are +multiple tasks in the system, it is obvious that the initialization +should be called before creating the task. + +Notice also that in this case we decided to register an overrun handler, +instead of which there could be @code{NULL}. This handler just prints +a message to terminal, what else may be done here depends on a specific +application. + +During the periodic execution, remaining budget should be watched +to avoid overrun. + +@example +void overrun_handler ( + rtems_cbs_server_id server_id +) +@{ + printk( "Budget overrun, fixing the task\n" ); + return; +@} + +rtems_task Tasks_Periodic( + rtems_task_argument argument +) +@{ + rtems_id rmid; + + rtems_cbs_server_id server_id; + rtems_cbs_parameters params; + + params.deadline = 10; + params.budget = 4; + + rtems_cbs_initialize(); + + rtems_cbs_create_server( ¶ms, &overrun_handler, &server_id ) + + rtems_cbs_attach_thread( server_id, SELF ); + + rtems_rate_monotonic_create( argument, &rmid ); + + while ( 1 ) @{ + if (rtems_rate_monotonic_period(rmid, params.deadline)==RTEMS_TIMEOUT) + break; + + /* Perform some periodic action */ + @} + + rtems_rate_monotonic_delete( rmid ); + + rtems_cbs_cleanup(); + exit( 1 ); +@} +@end example + +@section Directives + +This section details the Constant Bandwidth Server's directives. +A subsection is dedicated to each of this manager's directives +and describes the calling sequence, related constants, usage, +and status codes. + +@c +@c +@c +@page +@subsection CBS_INITIALIZE - Initialize the CBS library + +@cindex initialize the CBS library + +@subheading CALLING SEQUENCE: + +@ifset is-C +@findex rtems_cbs_initialize +@example +int rtems_cbs_initialize( void ); +@end example +@end ifset + +@subheading DIRECTIVE STATUS CODES: +@code{@value{RPREFIX}CBS_OK} - successful initialization@* +@code{@value{RPREFIX}CBS_ERROR_NO_MEMORY} - not enough memory for data@* + +@subheading DESCRIPTION: + +This routine initializes the library in terms of allocating necessary memory +for the servers. In case not enough memory is available in the system, +@code{@value{RPREFIX}CBS_ERROR_NO_MEMORY} is returned, otherwise +@code{@value{RPREFIX}CBS_OK}. + +@subheading NOTES: + +Additional memory per each server is allocated upon invocation of +@code{rtems_cbs_create_server}. + +Tasks in the system are not influenced, they still keep executing +with their initial parameters. + +@c +@c +@c +@page +@subsection CBS_CLEANUP - Cleanup the CBS library + +@cindex cleanup the CBS library + +@subheading CALLING SEQUENCE: + +@ifset is-C +@findex rtems_cbs_cleanup +@example +int rtems_cbs_cleanup( void ); +@end example +@end ifset + +@subheading DIRECTIVE STATUS CODES: +@code{@value{RPREFIX}CBS_OK} - always successful + +@subheading DESCRIPTION: + +This routine detaches all tasks from their servers, destroys all servers +and returns memory back to the system. + +@subheading NOTES: + +All tasks continue executing with their initial priorities. + +@c +@c +@c +@page +@subsection CBS_CREATE_SERVER - Create a new bandwidth server + +@cindex create a new bandwidth server + +@subheading CALLING SEQUENCE: + +@ifset is-C +@findex rtems_cbs_create_server +@example +int rtems_cbs_create_server ( + rtems_cbs_parameters *params, + rtems_cbs_budget_overrun budget_overrun_callback, + rtems_cbs_server_id *server_id +); +@end example +@end ifset + +@subheading DIRECTIVE STATUS CODES: +@code{@value{RPREFIX}CBS_OK} - successfully created@* +@code{@value{RPREFIX}CBS_ERROR_NO_MEMORY} - not enough memory for data@* +@code{@value{RPREFIX}CBS_ERROR_FULL} - maximum servers exceeded@* +@code{@value{RPREFIX}CBS_ERROR_INVALID_PARAMETER} - invalid input argument@* + +@subheading DESCRIPTION: + +This routine prepares an instance of a constant bandwidth server. +The input parameter @code{rtems_cbs_parameters} specifies scheduling +parameters of the server (period and budget). If these are not valid, +@code{@value{RPREFIX}CBS_ERROR_INVALID_PARAMETER} is returned. +The @code{budget_overrun_callback} is an optional callback function, which is +invoked in case the server's budget within one period is exceeded. +Output parameter @code{server_id} becomes an id of the newly created server. +If there is not enough memory, the @code{@value{RPREFIX}CBS_ERROR_NO_MEMORY} +is returned. If the maximum server count in the system is exceeded, +@code{@value{RPREFIX}CBS_ERROR_FULL} is returned. + +@subheading NOTES: + +No task execution is being influenced so far. + +@c +@c +@c +@page +@subsection CBS_ATTACH_THREAD - Attach a thread to server + +@cindex attach a thread to server + +@subheading CALLING SEQUENCE: + +@ifset is-C +@findex rtems_cbs_attach_thread +@example +int rtems_cbs_attach_thread ( + rtems_cbs_server_id server_id, + rtems_id task_id +); +@end example +@end ifset + +@subheading DIRECTIVE STATUS CODES: +@code{@value{RPREFIX}CBS_OK} - successfully attached@* +@code{@value{RPREFIX}CBS_ERROR_FULL} - server maximum tasks exceeded@* +@code{@value{RPREFIX}CBS_ERROR_INVALID_PARAMETER} - invalid input argument@* +@code{@value{RPREFIX}CBS_ERROR_NOSERVER} - server is not valid@* + +@subheading DESCRIPTION: + +Attaches a task (@code{task_id}) to a server (@code{server_id}). +The server has to be previously created. Now, the task starts +to be scheduled according to the server parameters and not +using initial priority. This implementation allows only one task +per server, if the user tries to bind another task to the same +server, @code{@value{RPREFIX}CBS_ERROR_FULL} is returned. + +@subheading NOTES: + +Tasks attached to servers become preemptible. + +@c +@c +@c +@page +@subsection CBS_DETACH_THREAD - Detach a thread from server + +@cindex detach a thread from server + +@subheading CALLING SEQUENCE: + +@ifset is-C +@findex rtems_cbs_detach_thread +@example +int rtems_cbs_detach_thread ( + rtems_cbs_server_id server_id, + rtems_id task_id +); +@end example +@end ifset + +@subheading DIRECTIVE STATUS CODES: +@code{@value{RPREFIX}CBS_OK} - successfully detached@* +@code{@value{RPREFIX}CBS_ERROR_INVALID_PARAMETER} - invalid input argument@* +@code{@value{RPREFIX}CBS_ERROR_NOSERVER} - server is not valid@* + +@subheading DESCRIPTION: + +This directive detaches a thread from server. The task continues its +execution with initial priority. + +@subheading NOTES: + +The server can be reused for any other task. + +@c +@c +@c +@page +@subsection CBS_DESTROY_SERVER - Destroy a bandwidth server + +@cindex destroy a bandwidth server + +@subheading CALLING SEQUENCE: + +@ifset is-C +@findex rtems_cbs_destroy_server +@example +int rtems_cbs_destroy_server ( + rtems_cbs_server_id server_id +); +@end example +@end ifset + +@subheading DIRECTIVE STATUS CODES: +@code{@value{RPREFIX}CBS_OK} - successfully destroyed@* +@code{@value{RPREFIX}CBS_ERROR_INVALID_PARAMETER} - invalid input argument@* +@code{@value{RPREFIX}CBS_ERROR_NOSERVER} - server is not valid@* + +@subheading DESCRIPTION: + +This directive destroys a server. If any task was attached to the server, +the task is detached and continues its execution according to EDF rules +with initial properties. + +@subheading NOTES: + +This again enables one more task to be created. + +@c +@c +@c +@page +@subsection CBS_GET_SERVER_ID - Get an ID of a server + +@cindex get an ID of a server + +@subheading CALLING SEQUENCE: + +@ifset is-C +@findex rtems_cbs_get_server_id +@example +int rtems_cbs_get_server_id ( + rtems_id task_id, + rtems_cbs_server_id *server_id +); +@end example +@end ifset + +@subheading DIRECTIVE STATUS CODES: +@code{@value{RPREFIX}CBS_OK} - successful@* +@code{@value{RPREFIX}CBS_ERROR_NOSERVER} - server is not valid@* + +@subheading DESCRIPTION: + +This directive returns an id of server belonging to a given task. + +@c +@c +@c +@page +@subsection CBS_GET_PARAMETERS - Get scheduling parameters of a server + +@cindex get scheduling parameters of a server + +@subheading CALLING SEQUENCE: + +@ifset is-C +@findex rtems_cbs_get_parameters +@example +rtems_cbs_get_parameters ( + rtems_cbs_server_id server_id, + rtems_cbs_parameters *params +); +@end example +@end ifset + +@subheading DIRECTIVE STATUS CODES: +@code{@value{RPREFIX}CBS_OK} - successful@* +@code{@value{RPREFIX}CBS_ERROR_INVALID_PARAMETER} - invalid input argument@* +@code{@value{RPREFIX}CBS_ERROR_NOSERVER} - server is not valid@* + +@subheading DESCRIPTION: + +This directive returns a structure with current scheduling parameters +of a given server (period and execution time). + +@subheading NOTES: + +It makes no difference if any task is assigned or not. + +@c +@c +@c +@page +@subsection CBS_SET_PARAMETERS - Set scheduling parameters + +@cindex set scheduling parameters + +@subheading CALLING SEQUENCE: + +@ifset is-C +@findex rtems_cbs_set_parameters +@example +int rtems_cbs_set_parameters ( + rtems_cbs_server_id server_id, + rtems_cbs_parameters *params +); +@end example +@end ifset + +@subheading DIRECTIVE STATUS CODES: +@code{@value{RPREFIX}CBS_OK} - successful@* +@code{@value{RPREFIX}CBS_ERROR_INVALID_PARAMETER} - invalid input argument@* +@code{@value{RPREFIX}CBS_ERROR_NOSERVER} - server is not valid@* + +@subheading DESCRIPTION: + +This directive sets new scheduling parameters to the server. This operation +can be performed regardless of whether a task is assigned or not. +If a task is assigned, the parameters become effective imediately, therefore it +is recommended to apply the change between two subsequent periods. + +@subheading NOTES: + +There is an upper limit on both period and budget equal to (2^31)-1 ticks. + +@c +@c +@c +@page +@subsection CBS_GET_EXECUTION_TIME - Get elapsed execution time + +@cindex get elapsed execution time + +@subheading CALLING SEQUENCE: + +@ifset is-C +@findex rtems_cbs_get_execution_time +@example +int rtems_cbs_get_execution_time ( + rtems_cbs_server_id server_id, + time_t *exec_time, + time_t *abs_time +); +@end example +@end ifset + +@subheading DIRECTIVE STATUS CODES: +@code{@value{RPREFIX}CBS_OK} - successful@* +@code{@value{RPREFIX}CBS_ERROR_INVALID_PARAMETER} - invalid input argument@* +@code{@value{RPREFIX}CBS_ERROR_NOSERVER} - server is not valid@* + +@subheading DESCRIPTION: + +This routine returns consumed execution time (@code{exec_time}) of a server +during the current period. + +@subheading NOTES: + +Absolute time (@code{abs_time}) not supported now. + +@c +@c +@c +@page +@subsection CBS_GET_REMAINING_BUDGET - Get remaining execution time + +@cindex get remaining execution time + +@subheading CALLING SEQUENCE: + +@ifset is-C +@findex rtems_cbs_get_remaining_budget +@example +int rtems_cbs_get_remaining_budget ( + rtems_cbs_server_id server_id, + time_t *remaining_budget +); +@end example +@end ifset + +@subheading DIRECTIVE STATUS CODES: +@code{@value{RPREFIX}CBS_OK} - successful@* +@code{@value{RPREFIX}CBS_ERROR_INVALID_PARAMETER} - invalid input argument@* +@code{@value{RPREFIX}CBS_ERROR_NOSERVER} - server is not valid@* + +@subheading DESCRIPTION: + +This directive returns remaining execution time of a given server for +current period. + +@subheading NOTES: + +If the execution time approaches zero, the assigned task should finish +computations of the current period. + +@c +@c +@c +@page +@subsection CBS_GET_APPROVED_BUDGET - Get scheduler approved execution time + +@cindex get scheduler approved execution time + +@subheading CALLING SEQUENCE: + +@ifset is-C +@findex rtems_cbs_get_approved_budget +@example +int rtems_cbs_get_approved_budget ( + rtems_cbs_server_id server_id, + time_t *appr_budget +); +@end example +@end ifset + +@subheading DIRECTIVE STATUS CODES: +@code{@value{RPREFIX}CBS_OK} - successful@* +@code{@value{RPREFIX}CBS_ERROR_INVALID_PARAMETER} - invalid input argument@* +@code{@value{RPREFIX}CBS_ERROR_NOSERVER} - server is not valid@* + +@subheading DESCRIPTION: + +This directive returns server's approved budget for subsequent periods. diff --git a/doc/user/dirstat.texi b/doc/user/dirstat.texi index 25c4ece1f2..9ad866cf52 100644 --- a/doc/user/dirstat.texi +++ b/doc/user/dirstat.texi @@ -6,7 +6,7 @@ @c $Id$ @c -@node Directive Status Codes, Example Application, Chains Prepend a Node, Top +@node Directive Status Codes, Example Application, Constant Bandwidth Server Scheduler API CBS_GET_APPROVED_BUDGET - Get scheduler approved execution time, Top @chapter Directive Status Codes @table @b @item @code{@value{RPREFIX}SUCCESSFUL} - successful completion diff --git a/testsuites/sptests/Makefile.am b/testsuites/sptests/Makefile.am index 5cb24d1eba..4a1ac8a0cc 100644 --- a/testsuites/sptests/Makefile.am +++ b/testsuites/sptests/Makefile.am @@ -31,7 +31,7 @@ SUBDIRS = \ spintrcritical17 spmkdir spmountmgr01 spheapprot \ spsimplesched01 spsimplesched02 spsimplesched03 spnsext01 \ spedfsched01 spedfsched02 spedfsched03 \ - spcbssched01 spcbssched02 spcbssched03 + spcbssched01 spcbssched02 spcbssched03 spqreslib include $(top_srcdir)/../automake/subdirs.am include $(top_srcdir)/../automake/local.am diff --git a/testsuites/sptests/configure.ac b/testsuites/sptests/configure.ac index bf79928a25..17c56caf4b 100644 --- a/testsuites/sptests/configure.ac +++ b/testsuites/sptests/configure.ac @@ -174,6 +174,7 @@ spnsext01/Makefile spobjgetnext/Makefile spprintk/Makefile spprivenv01/Makefile +spqreslib/Makefile sprbtree01/Makefile spsimplesched01/Makefile spsimplesched02/Makefile diff --git a/testsuites/sptests/spqreslib/Makefile.am b/testsuites/sptests/spqreslib/Makefile.am new file mode 100644 index 0000000000..bd8323ff9d --- /dev/null +++ b/testsuites/sptests/spqreslib/Makefile.am @@ -0,0 +1,28 @@ +## +## $Id$ +## + +MANAGERS = io rate_monotonic semaphore clock + +rtems_tests_PROGRAMS = spqreslib +spqreslib_SOURCES = init.c task_periodic.c system.h + +dist_rtems_tests_DATA = spqreslib.scn +dist_rtems_tests_DATA += spqreslib.doc + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../automake/compile.am +include $(top_srcdir)/../automake/leaf.am + +spqreslib_LDADD = $(MANAGERS_NOT_WANTED:%=$(PROJECT_LIB)/no-%.rel) + +AM_CPPFLAGS += -I$(top_srcdir)/../support/include + +LINK_OBJS = $(spqreslib_OBJECTS) $(spqreslib_LDADD) +LINK_LIBS = $(spqreslib_LDLIBS) + +spqreslib$(EXEEXT): $(spqreslib_OBJECTS) $(spqreslib_DEPENDENCIES) + @rm -f spqreslib$(EXEEXT) + $(make-exe) + +include $(top_srcdir)/../automake/local.am diff --git a/testsuites/sptests/spqreslib/init.c b/testsuites/sptests/spqreslib/init.c new file mode 100644 index 0000000000..20745d7ea2 --- /dev/null +++ b/testsuites/sptests/spqreslib/init.c @@ -0,0 +1,227 @@ +/* Init + * + * This routine is the initialization task for this test program. + * It is a user initialization task and has the responsibility for creating + * and starting the tasks that make up the test. If the time of day + * clock is required for the test, it should also be set to a known + * value by this function. + * + * Input params: + * argument - task argument + * + * Output params: NONE + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#define CONFIGURE_INIT +#include "system.h" + +rtems_task Init( + rtems_task_argument argument +) +{ + rtems_status_code status; + qres_sid_t server_id, server_id2; + time_t approved_budget, exec_time, abs_time, current_budget; + qres_params_t params, params1, params2, params3, params4; + + Priority = 30; + Period = 30; + Execution = 10; + Phase = 0; + + params.P = 1; + params.Q = 1; + + params1 = params2 = params3 = params4 = params; + params1.Q = -1; + params2.Q = SCHEDULER_EDF_PRIO_MSB + 1; + params3.P = -1; + params4.P = SCHEDULER_EDF_PRIO_MSB + 1; + + puts( "\n\n*** TEST QRES LIBRARY ***" ); + + Task_name = rtems_build_name( 'P', 'T', '1', ' ' ); + + status = rtems_task_create( + Task_name, + Priority, + RTEMS_MINIMUM_STACK_SIZE * 4, + RTEMS_DEFAULT_MODES, + RTEMS_DEFAULT_ATTRIBUTES, + &Task_id + ); + directive_failed( status, "rtems_task_create loop" ); + + printf( "Init: Initializing the qres library\n" ); + if ( qres_init() ) + printf( "ERROR: QRES INITIALIZATION FAILED\n" ); + + /* Error checks for Create server and Destroy server */ + printf( "Init: Create server and Destroy server\n" ); + if ( qres_destroy_server( -5 ) != + QOS_E_INVALID_PARAM ) + printf( "ERROR: DESTROY SERVER PASSED UNEXPECTEDLY\n" ); + if ( qres_destroy_server( 5 ) != + QOS_E_INVALID_PARAM ) + printf( "ERROR: DESTROY SERVER PASSED UNEXPECTEDLY\n" ); + if ( qres_destroy_server( 0 ) != QOS_E_NOSERVER ) + printf( "ERROR: DESTROY SERVER PASSED UNEXPECTEDLY\n" ); + if ( qres_create_server( ¶ms1, &server_id ) != + QOS_E_INVALID_PARAM ) + printf( "ERROR: CREATE SERVER PASSED UNEXPECTEDLY\n" ); + if ( qres_create_server( ¶ms2, &server_id ) != + QOS_E_INVALID_PARAM ) + printf( "ERROR: CREATE SERVER PASSED UNEXPECTEDLY\n" ); + if ( qres_create_server( ¶ms3, &server_id ) != + QOS_E_INVALID_PARAM ) + printf( "ERROR: CREATE SERVER PASSED UNEXPECTEDLY\n" ); + if ( qres_create_server( ¶ms4, &server_id ) != + QOS_E_INVALID_PARAM ) + printf( "ERROR: CREATE SERVER PASSED UNEXPECTEDLY\n" ); + if ( qres_create_server( ¶ms, &server_id2 ) ) + printf( "ERROR: CREATE SERVER FAILED\n" ); + if ( qres_create_server( ¶ms, &server_id ) ) + printf( "ERROR: CREATE SERVER FAILED\n" ); + if ( qres_create_server( ¶ms, &server_id ) != + QOS_E_FULL ) + printf( "ERROR: CREATE SERVER PASSED UNEXPECTEDLY\n" ); + + /* Error checks for Attach thread and Detach thread */ + printf( "Init: Attach thread\n" ); + if ( qres_attach_thread( -5, 0, RTEMS_SELF ) != + QOS_E_INVALID_PARAM ) + printf( "ERROR: ATTACH THREAD PASSED UNEXPECTEDLY\n" ); + if ( qres_attach_thread( 5, 0, RTEMS_SELF ) != + QOS_E_INVALID_PARAM ) + printf( "ERROR: ATTACH THREAD PASSED UNEXPECTEDLY\n" ); + if ( qres_attach_thread( server_id, 0, 1234 ) != + QOS_E_INVALID_PARAM ) + printf( "ERROR: ATTACH THREAD PASSED UNEXPECTEDLY\n" ); + if ( qres_attach_thread( server_id, 0, RTEMS_SELF ) ) + printf( "ERROR: ATTACH THREAD FAILED\n" ); + if ( qres_attach_thread( server_id, 0, RTEMS_SELF ) != + QOS_E_FULL ) + printf( "ERROR: ATTACH THREAD AGAIN PASSED UNEXPECTEDLY\n" ); + if ( qres_attach_thread( server_id, 0, Task_id ) != + QOS_E_FULL ) + printf( "ERROR: ATTACH THREAD TO FULL SERVER PASSED UNEXPECTEDLY \n" ); + if ( qres_destroy_server( server_id ) ) + printf( "ERROR: DESTROY SERVER WITH THREAD ATTACHED FAILED\n" ); + if ( qres_attach_thread( server_id, 0, RTEMS_SELF ) != + QOS_E_NOSERVER ) + printf( "ERROR: ATTACH THREAD PASSED UNEXPECTEDLY\n" ); + + printf( "Init: Detach thread\n" ); + if ( qres_detach_thread( -5, 0, RTEMS_SELF ) != + QOS_E_INVALID_PARAM ) + printf( "ERROR: DETACH THREAD PASSED UNEXPECTEDLY\n" ); + if ( qres_detach_thread( 5, 0, RTEMS_SELF ) != + QOS_E_INVALID_PARAM ) + printf( "ERROR: DETACH THREAD PASSED UNEXPECTEDLY\n" ); + if ( qres_detach_thread( server_id2, 0, 1234 ) != + QOS_E_INVALID_PARAM ) + printf( "ERROR: DETACH THREAD PASSED UNEXPECTEDLY \n" ); + if ( qres_detach_thread( server_id, 0, RTEMS_SELF ) != + QOS_E_NOSERVER ) + printf( "ERROR: DETACH THREAD PASSED UNEXPECTEDLY4\n" ); + qres_destroy_server( server_id2 ); + + /* Error checks for Set params and Get params */ + printf( "Init: Set params and Get params\n" ); + if ( qres_set_params( -5, ¶ms ) != + QOS_E_INVALID_PARAM ) + printf( "ERROR: SET PARAMS PASSED UNEXPECTEDLY\n" ); + if ( qres_set_params( 5, ¶ms ) != + QOS_E_INVALID_PARAM ) + printf( "ERROR: SET PARAMS PASSED UNEXPECTEDLY\n" ); + if ( qres_set_params( server_id, ¶ms ) != + QOS_E_NOSERVER ) + printf( "ERROR: SET PARAMS PASSED UNEXPECTEDLY\n" ); + + if ( qres_get_params( -5, ¶ms ) != + QOS_E_INVALID_PARAM ) + printf( "ERROR: GET PARAMS PASSED UNEXPECTEDLY\n" ); + if ( qres_get_params( 5, ¶ms ) != + QOS_E_INVALID_PARAM ) + printf( "ERROR: GET PARAMS PASSED UNEXPECTEDLY\n" ); + if ( qres_get_params( server_id, ¶ms ) != + QOS_E_NOSERVER ) + printf( "ERROR: GET PARAMS PASSED UNEXPECTEDLY\n" ); + + if ( qres_set_params( server_id, ¶ms1 ) != + QOS_E_INVALID_PARAM ) + printf( "ERROR: SET PARAMS PASSED UNEXPECTEDLY\n" ); + if ( qres_set_params( server_id, ¶ms2 ) != + QOS_E_INVALID_PARAM ) + printf( "ERROR: SET PARAMS PASSED UNEXPECTEDLY\n" ); + if ( qres_set_params( server_id, ¶ms3 ) != + QOS_E_INVALID_PARAM ) + printf( "ERROR: SET PARAMS PASSED UNEXPECTEDLY\n" ); + if ( qres_set_params( server_id, ¶ms4 ) != + QOS_E_INVALID_PARAM ) + printf( "ERROR: SET PARAMS PASSED UNEXPECTEDLY\n" ); + + /* Error checks for Get server id */ + printf( "Init: Get server id\n" ); + if ( qres_get_sid( 0, RTEMS_SELF, &server_id ) != + QOS_E_NOSERVER ) + printf( "ERROR: GET SERVER ID PASSED UNEXPECTEDLY\n" ); + + /* Error checks for Get approved budget */ + printf( "Init: Get approved budget\n" ); + if ( qres_get_appr_budget( -5, &approved_budget ) != + QOS_E_INVALID_PARAM ) + printf( "ERROR: GET APPROVED BUDGET PASSED UNEXPECTEDLY\n" ); + if ( qres_get_appr_budget( 5, &approved_budget ) != + QOS_E_INVALID_PARAM ) + printf( "ERROR: GET APPROVED BUDGET PASSED UNEXPECTEDLY\n" ); + if ( qres_get_appr_budget( server_id, &approved_budget ) != + QOS_E_NOSERVER ) + printf( "ERROR: GET APPROVED BUDGET PASSED UNEXPECTEDLY\n" ); + + /* Error checks for Get current budget */ + printf( "Init: Get current budget\n" ); + if ( qres_get_curr_budget( -5, ¤t_budget ) != + QOS_E_INVALID_PARAM ) + printf( "ERROR: GET REMAINING BUDGET PASSED UNEXPECTEDLY\n" ); + if ( qres_get_curr_budget( 5, ¤t_budget ) != + QOS_E_INVALID_PARAM ) + printf( "ERROR: GET REMAINING BUDGET PASSED UNEXPECTEDLY\n" ); + if ( qres_get_curr_budget( server_id, ¤t_budget ) != + QOS_E_NOSERVER ) + printf( "ERROR: GET REMAINING BUDGET PASSED UNEXPECTEDLY\n" ); + + /* Error checks for Get execution time */ + printf( "Init: Get execution time\n" ); + if ( qres_get_exec_time( -5, &exec_time, &abs_time ) != + QOS_E_INVALID_PARAM ) + printf( "ERROR: GET EXECUTION TIME PASSED UNEXPECTEDLY\n" ); + if ( qres_get_exec_time( 5, &exec_time, &abs_time ) != + QOS_E_INVALID_PARAM ) + printf( "ERROR: GET EXECUTION TIME PASSED UNEXPECTEDLY\n" ); + if ( qres_get_exec_time( server_id, &exec_time, &abs_time ) != + QOS_E_NOSERVER ) + printf( "ERROR: GET EXECUTION TIME PASSED UNEXPECTEDLY\n" ); + + /* Restart QRES library */ + printf( "Init: Cleaning up QRES\n" ); + if ( qres_cleanup() ) + printf( "ERROR: QRES CLEANUP FAILED\n" ); + printf( "Init: Initializing the QRES\n" ); + if ( qres_init() ) + printf( "ERROR: QRES INITIALIZATION FAILED\n" ); + + /* Start periodic task */ + printf( "Init: Starting periodic task\n" ); + status = rtems_task_start( Task_id, Task_Periodic, 1 ); + directive_failed( status, "rtems_task_start periodic" ); + + status = rtems_task_delete( RTEMS_SELF ); + directive_failed( status, "rtems_task_delete of RTEMS_SELF" ); +} diff --git a/testsuites/sptests/spqreslib/spqreslib.doc b/testsuites/sptests/spqreslib/spqreslib.doc new file mode 100644 index 0000000000..f590216547 --- /dev/null +++ b/testsuites/sptests/spqreslib/spqreslib.doc @@ -0,0 +1,22 @@ +# +# $Id$ +# +# COPYRIGHT (c) 1989-1999. +# On-Line Applications Research Corporation (OAR). +# +# The license and distribution terms for this file may be +# found in the file LICENSE in this distribution or at +# http://www.rtems.com/license/LICENSE. +# + + +This file describes the directives and concepts tested by this test set. + +test set name: spqreslib + +directives: + + +concepts: + + a. Verifies QRES library functionality. diff --git a/testsuites/sptests/spqreslib/spqreslib.scn b/testsuites/sptests/spqreslib/spqreslib.scn new file mode 100644 index 0000000000..de79c34fec --- /dev/null +++ b/testsuites/sptests/spqreslib/spqreslib.scn @@ -0,0 +1,30 @@ +*** TEST QRES LIBRARY *** +Init: Initializing the qres library +Init: Create server and Destroy server +Init: Attach thread +Init: Detach thread +Init: Set params and Get params +Init: Get server id +Init: Get approved budget +Init: Get current budget +Init: Get execution time +Init: Cleaning up QRES +Init: Initializing the QRES +Init: Starting periodic task +Periodic task: Create server and Attach thread +Periodic task: ID and Get parameters +Periodic task: Detach thread and Destroy server +Periodic task: Current budget and Execution time +Periodic task: Set parameters +Periodic task: Approved budget +Periodic task: Starting periodic behavior +P1-S ticks:1 +P1-F ticks:11 +P1-S ticks:31 +P1-F ticks:41 +P1-S ticks:61 +P1-F ticks:71 +P1-S ticks:91 +P1-F ticks:101 +P1-S ticks:121 +*** END OF TEST QRES LIBRARY *** diff --git a/testsuites/sptests/spqreslib/system.h b/testsuites/sptests/spqreslib/system.h new file mode 100644 index 0000000000..f99b5f459d --- /dev/null +++ b/testsuites/sptests/spqreslib/system.h @@ -0,0 +1,62 @@ +/* system.h + * + * This include file contains information that is included in every + * function in the test set. + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include <tmacros.h> + +/* functions */ + +rtems_task Init( + rtems_task_argument argument +); + +rtems_task Task_Periodic( + rtems_task_argument argument +); + +/* configuration information */ + +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER + +#define CONFIGURE_MICROSECONDS_PER_TICK 100000 + +#define CONFIGURE_MAXIMUM_TASKS 2 +#define CONFIGURE_MAXIMUM_PERIODS 10 + +#define CONFIGURE_INIT_TASK_PRIORITY 100 +#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +#define CONFIGURE_EXTRA_TASK_STACKS (6 * 4 * RTEMS_MINIMUM_STACK_SIZE) + +#define CONFIGURE_SCHEDULER_CBS + +#include <rtems/confdefs.h> + +#include <rtems/rtems/clock.h> +#include <rtems/score/isr.h> +#include <rtems/rtems/intr.h> +#include <qreslib.h> + +/* global variables */ + +rtems_id Task_id; +rtems_name Task_name; +rtems_task_priority Priority; +time_t Period; +time_t Execution; +time_t Phase; + +/* end of include file */ diff --git a/testsuites/sptests/spqreslib/task_periodic.c b/testsuites/sptests/spqreslib/task_periodic.c new file mode 100644 index 0000000000..eb353c5c0c --- /dev/null +++ b/testsuites/sptests/spqreslib/task_periodic.c @@ -0,0 +1,138 @@ +/* Tasks_Periodic + * + * This routine serves as a test task for the CBS scheduler + * implementation. + * + * Input parameters: + * argument - task argument + * + * Output parameters: NONE + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include "system.h" + +rtems_task Task_Periodic( + rtems_task_argument argument +) +{ + rtems_id rmid; + rtems_status_code status; + + time_t approved_budget, exec_time, abs_time, current_budget; + + int start, stop, now; + + qres_sid_t server_id, tsid; + qres_params_t params, tparams; + + params.P = Period; + params.Q = Execution+1; + + printf( "Periodic task: Create server and Attach thread\n" ); + if ( qres_create_server( ¶ms, &server_id ) ) + printf( "ERROR: CREATE SERVER FAILED\n" ); + if ( qres_attach_thread( server_id, 0, Task_id ) ) + printf( "ERROR: ATTACH THREAD FAILED\n" ); + + printf( "Periodic task: ID and Get parameters\n" ); + if ( qres_get_sid( 0, Task_id, &tsid ) ) + printf( "ERROR: GET SERVER ID FAILED\n" ); + if ( tsid != server_id ) + printf( "ERROR: SERVER ID MISMATCH\n" ); + if ( qres_get_params( server_id, &tparams ) ) + printf( "ERROR: GET PARAMETERS FAILED\n" ); + if ( params.P != tparams.P || + params.Q != tparams.Q ) + printf( "ERROR: PARAMETERS MISMATCH\n" ); + + printf( "Periodic task: Detach thread and Destroy server\n" ); + if ( qres_detach_thread( server_id, 0, Task_id ) ) + printf( "ERROR: DETACH THREAD FAILED\n" ); + if ( qres_destroy_server( server_id ) ) + printf( "ERROR: DESTROY SERVER FAILED\n" ); + if ( qres_create_server( ¶ms, &server_id ) ) + printf( "ERROR: CREATE SERVER FAILED\n" ); + + printf( "Periodic task: Current budget and Execution time\n" ); + if ( qres_get_curr_budget( server_id, ¤t_budget ) ) + printf( "ERROR: GET REMAINING BUDGET FAILED\n" ); + if ( current_budget != params.Q ) + printf( "ERROR: REMAINING BUDGET MISMATCH\n" ); + if ( qres_get_exec_time( server_id, &exec_time, &abs_time ) ) + printf( "ERROR: GET EXECUTION TIME FAILED\n" ); + + printf( "Periodic task: Set parameters\n" ); + if ( qres_attach_thread( server_id, 0, Task_id ) ) + printf( "ERROR: ATTACH THREAD FAILED\n" ); + params.P = Period * 2; + params.Q = Execution * 2 +1; + if ( qres_set_params( server_id, ¶ms ) ) + printf( "ERROR: SET PARAMS FAILED\n" ); + if ( qres_get_params( server_id, &tparams ) ) + printf( "ERROR: GET PARAMS FAILED\n" ); + if ( params.P != tparams.P || + params.Q != tparams.Q ) + printf( "ERROR: PARAMS MISMATCH\n" ); + params.P = Period; + params.Q = Execution+1; + if ( qres_set_params( server_id, ¶ms ) ) + printf( "ERROR: SET PARAMS FAILED\n" ); + if ( qres_get_appr_budget( server_id, &approved_budget ) ) + printf( "ERROR: GET APPROVED BUDGET FAILED\n" ); + + printf( "Periodic task: Approved budget\n" ); + if ( approved_budget != params.Q ) + printf( "ERROR: APPROVED BUDGET MISMATCH\n" ); + + status = rtems_rate_monotonic_create( argument, &rmid ); + directive_failed( status, "rtems_rate_monotonic_create" ); + + /* Starting periodic behavior of the task */ + printf( "Periodic task: Starting periodic behavior\n" ); + status = rtems_task_wake_after( 1 + Phase ); + directive_failed( status, "rtems_task_wake_after" ); + + while ( FOREVER ) { + if ( rtems_rate_monotonic_period(rmid, Period) == RTEMS_TIMEOUT ) + printf( "P%" PRIdPTR " - Deadline miss\n", argument ); + + rtems_clock_get( RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &start ); + printf( "P%" PRIdPTR "-S ticks:%d\n", argument, start ); + if ( start > 4*Period+Phase ) break; /* stop */ + /* active computing */ + while(FOREVER) { + rtems_clock_get( RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now ); + if ( now >= start + Execution ) break; + + if ( qres_get_exec_time( server_id, &exec_time, &abs_time ) ) + printf( "ERROR: GET EXECUTION TIME FAILED\n" ); + if ( qres_get_curr_budget( server_id, ¤t_budget) ) + printf( "ERROR: GET CURRENT BUDGET FAILED\n" ); + if ( (current_budget + exec_time) > (Execution + 1) ) { + printf( "ERROR: CURRENT BUDGET AND EXECUTION TIME MISMATCH\n" ); + rtems_test_exit( 0 ); + } + } + rtems_clock_get( RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &stop ); + printf( "P%" PRIdPTR "-F ticks:%d\n", argument, stop ); + } + + /* delete period and SELF */ + status = rtems_rate_monotonic_delete( rmid ); + if ( status != RTEMS_SUCCESSFUL ) { + printf("rtems_rate_monotonic_delete failed with status of %d.\n", status); + rtems_test_exit( 0 ); + } + if ( qres_cleanup() ) + printf( "ERROR: QRES CLEANUP\n" ); + + fflush(stdout); + puts( "*** END OF TEST QRES LIBRARY ***" ); + rtems_test_exit( 0 ); +} |