[PATCH v2] rtems: Add rtems_interrupt_server_create()
Chris Johns
chrisj at rtems.org
Fri Jul 31 23:53:18 UTC 2020
OK for the 5 branch.
Will there be an update to the configuration section in the Classic API manual?
On 1/8/20 2:10 am, Sebastian Huber wrote:
> Add rtems_interrupt_server_destroy().
>
> Before this patch, the only way to create interrupt servers was
> rtems_interrupt_server_initialize(). This function creates the default
> interrupt server and in SMP configurations additional interrupt servers
> for the additional processors. The interrupt server is heavily used by
> libbsd. This includes the epoch based reclamation which performs time
> consuming resource and memory deallocation work. This does not work well
> with time critical services, for example an UART over SPI or I2C. One
> approach to address this problem is to allow the application to create
> custom interrupt servers with the right priority and task properties.
> The interrupt server API accounted for this, however, it was not
> implemented before this patch.
>
> Closes #4033.
> ---
> bsps/shared/irq/irq-server.c | 365 ++++++++++++++++++---------
> cpukit/include/rtems/irq-extension.h | 143 ++++++++++-
> 2 files changed, 378 insertions(+), 130 deletions(-)
>
> diff --git a/bsps/shared/irq/irq-server.c b/bsps/shared/irq/irq-server.c
> index 93e2d144d8..eb5b0b3998 100644
> --- a/bsps/shared/irq/irq-server.c
> +++ b/bsps/shared/irq/irq-server.c
> @@ -7,13 +7,7 @@
> */
>
> /*
> - * Copyright (c) 2009, 2019 embedded brains GmbH. All rights reserved.
> - *
> - * embedded brains GmbH
> - * Dornierstr. 4
> - * 82178 Puchheim
> - * Germany
> - * <rtems at embedded-brains.de>
> + * Copyright (C) 2009, 2020 embedded brains GmbH (http://www.embedded-brains.de)
> *
> * The license and distribution terms for this file may be
> * found in the file LICENSE in this distribution or at
> @@ -21,6 +15,7 @@
> */
>
> #include <stdlib.h>
> +#include <string.h>
>
> #include <rtems.h>
> #include <rtems/chain.h>
> @@ -30,54 +25,43 @@
>
> #define BSP_INTERRUPT_SERVER_MANAGEMENT_VECTOR (BSP_INTERRUPT_VECTOR_MAX + 1)
>
> -typedef struct {
> - RTEMS_INTERRUPT_LOCK_MEMBER(lock);
> - rtems_chain_control entries;
> - rtems_id server;
> - unsigned errors;
> -} bsp_interrupt_server_context;
> +static rtems_interrupt_server_control bsp_interrupt_server_default;
>
> -#if defined(RTEMS_SMP)
> -static bsp_interrupt_server_context *bsp_interrupt_server_instances;
> -#else
> -static bsp_interrupt_server_context bsp_interrupt_server_instance;
> -#endif
> +static rtems_chain_control bsp_interrupt_server_chain =
> + RTEMS_CHAIN_INITIALIZER_EMPTY(bsp_interrupt_server_chain);
>
> -static bsp_interrupt_server_context *bsp_interrupt_server_get_context(
> +static rtems_interrupt_server_control *bsp_interrupt_server_get_context(
> uint32_t server_index,
> rtems_status_code *sc
> )
> {
> -#if defined(RTEMS_SMP)
> - if (bsp_interrupt_server_instances == NULL) {
> - *sc = RTEMS_INCORRECT_STATE;
> - return NULL;
> - }
> -#else
> - if (bsp_interrupt_server_instance.server == RTEMS_ID_NONE) {
> - *sc = RTEMS_INCORRECT_STATE;
> - return NULL;
> - }
> -#endif
> + rtems_chain_node *node;
> +
> + bsp_interrupt_lock();
> + node = rtems_chain_first(&bsp_interrupt_server_chain);
>
> - if (server_index >= rtems_scheduler_get_processor_maximum()) {
> - *sc = RTEMS_INVALID_ID;
> - return NULL;
> + while (node != rtems_chain_tail(&bsp_interrupt_server_chain)) {
> + rtems_interrupt_server_control *s;
> +
> + s = RTEMS_CONTAINER_OF(node, rtems_interrupt_server_control, node);
> + if (s->index == server_index) {
> + bsp_interrupt_unlock();
> + return s;
> + }
> +
> + node = rtems_chain_next(node);
> }
>
> - *sc = RTEMS_SUCCESSFUL;
> -#if defined(RTEMS_SMP)
> - return &bsp_interrupt_server_instances[server_index];
> -#else
> - return &bsp_interrupt_server_instance;
> -#endif
> + bsp_interrupt_unlock();
> + *sc = RTEMS_INVALID_ID;
> + return NULL;
> }
>
> static void bsp_interrupt_server_trigger(void *arg)
> {
> rtems_interrupt_lock_context lock_context;
> rtems_interrupt_server_entry *e = arg;
> - bsp_interrupt_server_context *s = e->server;
> + rtems_interrupt_server_control *s = e->server;
>
> if (bsp_interrupt_is_valid_vector(e->vector)) {
> bsp_interrupt_vector_disable(e->vector);
> @@ -137,7 +121,7 @@ static rtems_interrupt_server_entry *bsp_interrupt_server_query_entry(
> }
>
> typedef struct {
> - bsp_interrupt_server_context *server;
> + rtems_interrupt_server_control *server;
> rtems_vector_number vector;
> rtems_option options;
> rtems_interrupt_handler handler;
> @@ -281,7 +265,7 @@ static void bsp_interrupt_server_remove_helper(void *arg)
> }
>
> static rtems_status_code bsp_interrupt_server_call_helper(
> - bsp_interrupt_server_context *s,
> + rtems_interrupt_server_control *s,
> rtems_vector_number vector,
> rtems_option options,
> rtems_interrupt_handler handler,
> @@ -314,7 +298,7 @@ static rtems_status_code bsp_interrupt_server_call_helper(
> }
>
> static rtems_interrupt_server_entry *bsp_interrupt_server_get_entry(
> - bsp_interrupt_server_context *s
> + rtems_interrupt_server_control *s
> )
> {
> rtems_interrupt_lock_context lock_context;
> @@ -337,7 +321,7 @@ static rtems_interrupt_server_entry *bsp_interrupt_server_get_entry(
>
> static void bsp_interrupt_server_task(rtems_task_argument arg)
> {
> - bsp_interrupt_server_context *s = (bsp_interrupt_server_context *) arg;
> + rtems_interrupt_server_control *s = (rtems_interrupt_server_control *) arg;
>
> while (true) {
> rtems_event_set events;
> @@ -377,7 +361,7 @@ rtems_status_code rtems_interrupt_server_handler_install(
> )
> {
> rtems_status_code sc;
> - bsp_interrupt_server_context *s;
> + rtems_interrupt_server_control *s;
>
> s = bsp_interrupt_server_get_context(server_index, &sc);
> if (s == NULL) {
> @@ -402,7 +386,7 @@ rtems_status_code rtems_interrupt_server_handler_remove(
> )
> {
> rtems_status_code sc;
> - bsp_interrupt_server_context *s;
> + rtems_interrupt_server_control *s;
>
> s = bsp_interrupt_server_get_context(server_index, &sc);
> if (s == NULL) {
> @@ -464,7 +448,7 @@ rtems_status_code rtems_interrupt_server_handler_iterate(
> {
> rtems_status_code sc;
> bsp_interrupt_server_handler_iterate_helper_data hihd;
> - bsp_interrupt_server_context *s;
> + rtems_interrupt_server_control *s;
>
> s = bsp_interrupt_server_get_context(server_index, &sc);
> if (s == NULL) {
> @@ -487,103 +471,252 @@ rtems_status_code rtems_interrupt_server_handler_iterate(
> );
> }
>
> -rtems_status_code rtems_interrupt_server_initialize(
> +/*
> + * The default server is statically allocated. Just clear the structure so
> + * that it can be re-initialized.
> + */
> +static void bsp_interrupt_server_destroy_default(
> + rtems_interrupt_server_control *s
> +)
> +{
> + memset(s, 0, sizeof(*s));
> +}
> +
> +#if defined(RTEMS_SMP)
> +static void bsp_interrupt_server_destroy_secondary(
> + rtems_interrupt_server_control *s
> +)
> +{
> + free(s);
> +}
> +#endif
> +
> +static rtems_status_code bsp_interrupt_server_create(
> + rtems_interrupt_server_control *s,
> rtems_task_priority priority,
> size_t stack_size,
> rtems_mode modes,
> rtems_attribute attributes,
> - uint32_t *server_count
> + uint32_t cpu_index
> )
> {
> - uint32_t cpu_index;
> - uint32_t cpu_count;
> - uint32_t dummy;
> - bsp_interrupt_server_context *instances;
> + rtems_status_code sc;
> +#if defined(RTEMS_SMP)
> + rtems_id scheduler;
> + cpu_set_t cpu;
> +#endif
>
> - if (server_count == NULL) {
> - server_count = &dummy;
> - }
> + rtems_interrupt_lock_initialize(&s->lock, "Interrupt Server");
> + rtems_chain_initialize_empty(&s->entries);
>
> - cpu_count = rtems_scheduler_get_processor_maximum();
> + sc = rtems_task_create(
> + rtems_build_name('I', 'R', 'Q', 'S'),
> + priority,
> + stack_size,
> + modes,
> + attributes,
> + &s->server
> + );
> + if (sc != RTEMS_SUCCESSFUL) {
> + return sc;
> + }
>
> #if defined(RTEMS_SMP)
> - instances = calloc(cpu_count, sizeof(*instances));
> - if (instances == NULL) {
> - return RTEMS_NO_MEMORY;
> + sc = rtems_scheduler_ident_by_processor(cpu_index, &scheduler);
> + if (sc != RTEMS_SUCCESSFUL) {
> + /* Do not start an interrupt server on a processor without a scheduler */
> + return RTEMS_SUCCESSFUL;
> }
> +
> + sc = rtems_task_set_scheduler(s->server, scheduler, priority);
> + _Assert(sc == RTEMS_SUCCESSFUL);
> +
> + /* Set the task to processor affinity on a best-effort basis */
> + CPU_ZERO(&cpu);
> + CPU_SET(cpu_index, &cpu);
> + (void) rtems_task_set_affinity(s->server, sizeof(cpu), &cpu);
> #else
> - instances = &bsp_interrupt_server_instance;
> + (void) cpu_index;
> #endif
>
> - for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
> - bsp_interrupt_server_context *s = &instances[cpu_index];
> - rtems_status_code sc;
> + rtems_chain_append_unprotected(&bsp_interrupt_server_chain, &s->node);
> +
> + sc = rtems_task_start(
> + s->server,
> + bsp_interrupt_server_task,
> + (rtems_task_argument) s
> + );
> + _Assert(sc == RTEMS_SUCCESSFUL);
> +
> + return sc;
> +}
> +
> +rtems_status_code rtems_interrupt_server_initialize(
> + rtems_task_priority priority,
> + size_t stack_size,
> + rtems_mode modes,
> + rtems_attribute attributes,
> + uint32_t *server_count
> +)
> +{
> + rtems_status_code sc;
> + rtems_interrupt_server_control *s;
> + uint32_t cpu_index;
> #if defined(RTEMS_SMP)
> - rtems_id scheduler;
> - cpu_set_t cpu;
> + uint32_t cpu_count;
> #endif
>
> - rtems_interrupt_lock_initialize(&s->lock, "Interrupt Server");
> - rtems_chain_initialize_empty(&s->entries);
> + cpu_index = 0;
> + s = &bsp_interrupt_server_default;
> +
> + bsp_interrupt_lock();
> +
> + if (s->server != 0) {
> + sc = RTEMS_INCORRECT_STATE;
> + goto done;
> + }
> +
> + s->destroy = bsp_interrupt_server_destroy_default;
> + sc = bsp_interrupt_server_create(
> + s,
> + priority,
> + stack_size,
> + modes,
> + attributes,
> + cpu_index
> + );
> + if (sc != RTEMS_SUCCESSFUL) {
> + goto done;
> + }
> +
> + cpu_index = 1;
> +
> +#if defined(RTEMS_SMP)
> + cpu_count = rtems_scheduler_get_processor_maximum();
> +
> + while (cpu_index < cpu_count) {
> + s = calloc(1, sizeof(*s));
>
> - sc = rtems_task_create(
> - rtems_build_name('I', 'R', 'Q', 'S'),
> + if (s == NULL) {
> + sc = RTEMS_NO_MEMORY;
> + goto done;
> + }
> +
> + s->destroy = bsp_interrupt_server_destroy_secondary;
> + s->index = cpu_index;
> + sc = bsp_interrupt_server_create(
> + s,
> priority,
> stack_size,
> modes,
> attributes,
> - &s->server
> + cpu_index
> );
> if (sc != RTEMS_SUCCESSFUL) {
> - *server_count = cpu_index;
> -
> -#if defined(RTEMS_SMP)
> - if (cpu_index > 0) {
> - bsp_interrupt_server_instances = instances;
> - return RTEMS_SUCCESSFUL;
> - }
> + goto done;
> + }
>
> - free(instances);
> + ++cpu_index;
> + }
> #endif
>
> - return RTEMS_TOO_MANY;
> - }
> +done:
> + bsp_interrupt_unlock();
>
> -#if defined(RTEMS_SMP)
> - sc = rtems_scheduler_ident_by_processor(cpu_index, &scheduler);
> - if (sc != RTEMS_SUCCESSFUL) {
> - /* Do not start an interrupt server on a processor without a scheduler */
> - continue;
> - }
> + if (server_count != NULL) {
> + *server_count = cpu_index;
> + }
>
> - sc = rtems_task_set_scheduler(s->server, scheduler, priority);
> - _Assert(sc == RTEMS_SUCCESSFUL);
> + return sc;
> +}
>
> - /* Set the task to processor affinity on a best-effort basis */
> - CPU_ZERO(&cpu);
> - CPU_SET(cpu_index, &cpu);
> - (void) rtems_task_set_affinity(s->server, sizeof(cpu), &cpu);
> -#endif
> +rtems_status_code rtems_interrupt_server_create(
> + rtems_interrupt_server_control *s,
> + const rtems_interrupt_server_config *config,
> + uint32_t *server_index
> +)
> +{
> + rtems_status_code sc;
>
> - sc = rtems_task_start(
> - s->server,
> - bsp_interrupt_server_task,
> - (rtems_task_argument) s
> - );
> - _Assert(sc == RTEMS_SUCCESSFUL);
> + sc = rtems_task_create(
> + config->name,
> + config->priority,
> + config->storage_size,
> + config->modes,
> + config->attributes,
> + &s->server
> + );
> + if (sc != RTEMS_SUCCESSFUL) {
> + return sc;
> }
>
> -#if defined(RTEMS_SMP)
> - bsp_interrupt_server_instances = instances;
> -#endif
> - *server_count = cpu_index;
> + rtems_interrupt_lock_initialize(&s->lock, "Interrupt Server");
> + rtems_chain_initialize_empty(&s->entries);
> + s->destroy = config->destroy;
> + s->index = rtems_object_id_get_index(s->server)
> + + rtems_scheduler_get_processor_maximum();
> + *server_index = s->index;
>
> + bsp_interrupt_lock();
> + rtems_chain_initialize_node(&s->node);
> + rtems_chain_append_unprotected(&bsp_interrupt_server_chain, &s->node);
> + bsp_interrupt_unlock();
> +
> + sc = rtems_task_start(
> + s->server,
> + bsp_interrupt_server_task,
> + (rtems_task_argument) s
> + );
> + _Assert(sc == RTEMS_SUCCESSFUL);
> +
> + return sc;
> +}
> +
> +static void bsp_interrupt_server_destroy_helper(void *arg)
> +{
> + bsp_interrupt_server_helper_data *hd = arg;
> + rtems_interrupt_server_control *s = hd->server;
> + rtems_status_code sc;
> +
> + bsp_interrupt_lock();
> + rtems_chain_extract_unprotected(&s->node);
> + bsp_interrupt_unlock();
> +
> + if (s->destroy != NULL) {
> + (*s->destroy)(s);
> + }
> +
> + sc = rtems_event_transient_send(hd->task);
> + _Assert(sc == RTEMS_SUCCESSFUL);
> + (void) sc;
> +
> + rtems_task_exit();
> +}
> +
> +rtems_status_code rtems_interrupt_server_destroy(uint32_t server_index)
> +{
> + rtems_status_code sc;
> + rtems_interrupt_server_control *s;
> +
> + s = bsp_interrupt_server_get_context(server_index, &sc);
> + if (s == NULL) {
> + return sc;
> + }
> +
> + bsp_interrupt_server_call_helper(
> + s,
> + BSP_INTERRUPT_SERVER_MANAGEMENT_VECTOR,
> + 0,
> + NULL,
> + NULL,
> + bsp_interrupt_server_destroy_helper
> + );
> return RTEMS_SUCCESSFUL;
> }
>
> static void bsp_interrupt_server_entry_initialize(
> rtems_interrupt_server_entry *entry,
> - bsp_interrupt_server_context *s
> + rtems_interrupt_server_control *s
> )
> {
> rtems_chain_set_off_chain(&entry->node);
> @@ -611,7 +744,7 @@ rtems_status_code rtems_interrupt_server_entry_initialize(
> )
> {
> rtems_status_code sc;
> - bsp_interrupt_server_context *s;
> + rtems_interrupt_server_control *s;
>
> s = bsp_interrupt_server_get_context(server_index, &sc);
> if (s == NULL) {
> @@ -645,7 +778,7 @@ rtems_status_code rtems_interrupt_server_entry_move(
> )
> {
> rtems_status_code sc;
> - bsp_interrupt_server_context *s;
> + rtems_interrupt_server_control *s;
>
> s = bsp_interrupt_server_get_context(destination_server_index, &sc);
> if (s == NULL) {
> @@ -667,7 +800,7 @@ void rtems_interrupt_server_entry_destroy(
> rtems_interrupt_server_entry *entry
> )
> {
> - bsp_interrupt_server_context *s;
> + rtems_interrupt_server_control *s;
> rtems_interrupt_lock_context lock_context;
>
> s = entry->server;
> @@ -698,7 +831,7 @@ rtems_status_code rtems_interrupt_server_request_initialize(
> )
> {
> rtems_status_code sc;
> - bsp_interrupt_server_context *s;
> + rtems_interrupt_server_control *s;
>
> s = bsp_interrupt_server_get_context(server_index, &sc);
> if (s == NULL) {
> @@ -727,8 +860,8 @@ static void bsp_interrupt_server_handler_move_helper(void *arg)
> e = bsp_interrupt_server_query_entry(hd->vector, &trigger_options);
> if (e != NULL) {
> rtems_interrupt_lock_context lock_context;
> - bsp_interrupt_server_context *src = e->server;
> - bsp_interrupt_server_context *dst = hihd->arg;
> + rtems_interrupt_server_control *src = e->server;
> + rtems_interrupt_server_control *dst = hihd->arg;
> bool pending;
>
> /* The source server is only used in SMP configurations for the lock */
> @@ -763,8 +896,8 @@ rtems_status_code rtems_interrupt_server_move(
> )
> {
> rtems_status_code sc;
> - bsp_interrupt_server_context *src;
> - bsp_interrupt_server_context *dst;
> + rtems_interrupt_server_control *src;
> + rtems_interrupt_server_control *dst;
> bsp_interrupt_server_handler_iterate_helper_data hihd;
>
> src = bsp_interrupt_server_get_context(source_server_index, &sc);
> @@ -810,7 +943,7 @@ static void bsp_interrupt_server_entry_suspend_helper(void *arg)
> rtems_status_code rtems_interrupt_server_suspend(uint32_t server_index)
> {
> rtems_status_code sc;
> - bsp_interrupt_server_context *s;
> + rtems_interrupt_server_control *s;
>
> s = bsp_interrupt_server_get_context(server_index, &sc);
> if (s == NULL) {
> @@ -831,7 +964,7 @@ rtems_status_code rtems_interrupt_server_suspend(uint32_t server_index)
> rtems_status_code rtems_interrupt_server_resume(uint32_t server_index)
> {
> rtems_status_code sc;
> - bsp_interrupt_server_context *s;
> + rtems_interrupt_server_control *s;
>
> s = bsp_interrupt_server_get_context(server_index, &sc);
> if (s == NULL) {
> @@ -858,7 +991,7 @@ rtems_status_code rtems_interrupt_server_set_affinity(
> )
> {
> rtems_status_code sc;
> - bsp_interrupt_server_context *s;
> + rtems_interrupt_server_control *s;
> rtems_id scheduler;
>
> s = bsp_interrupt_server_get_context(server_index, &sc);
> diff --git a/cpukit/include/rtems/irq-extension.h b/cpukit/include/rtems/irq-extension.h
> index 0d77b320bc..bde75ec765 100644
> --- a/cpukit/include/rtems/irq-extension.h
> +++ b/cpukit/include/rtems/irq-extension.h
> @@ -9,13 +9,7 @@
> /*
> * Based on concepts of Pavel Pisa, Till Straumann and Eric Valette.
> *
> - * Copyright (C) 2008, 2019 embedded brains GmbH
> - *
> - * embedded brains GmbH
> - * Dornierstr. 4
> - * 82178 Puchheim
> - * Germany
> - * <rtems at embedded-brains.de>
> + * Copyright (C) 2008, 2020 embedded brains GmbH (http://www.embedded-brains.de)
> *
> * The license and distribution terms for this file may be
> * found in the file LICENSE in this distribution or at
> @@ -259,6 +253,76 @@ typedef struct rtems_interrupt_server_action {
> */
> #define RTEMS_INTERRUPT_SERVER_DEFAULT 0
>
> +/**
> + * @brief An interrupt server control.
> + *
> + * This structure must be treated as an opaque data type. Members must not be
> + * accessed directly.
> + *
> + * @see rtems_interrupt_server_create()
> + */
> +typedef struct rtems_interrupt_server_control {
> + RTEMS_INTERRUPT_LOCK_MEMBER( lock )
> + rtems_chain_control entries;
> + rtems_id server;
> + unsigned long errors;
> + uint32_t index;
> + rtems_chain_node node;
> + void ( *destroy )( struct rtems_interrupt_server_control * );
> +} rtems_interrupt_server_control;
> +
> +/**
> + * @brief An interrupt server configuration.
> + *
> + * @see rtems_interrupt_server_create()
> + */
> +typedef struct {
> + /**
> + * @brief The task name of the interrupt server.
> + */
> + rtems_name name;
> +
> + /**
> + * @brief The initial task priority of the interrupt server.
> + */
> + rtems_task_priority priority;
> +
> + /**
> + * @brief The task storage area of the interrupt server.
> + *
> + * It shall be NULL for interrupt servers created by
> + * rtems_interrupt_server_create().
> + */
> + void *storage_area;
> +
> + /**
> + * @brief The task storage size of the interrupt server.
> + *
> + * For interrupt servers created by rtems_interrupt_server_create() this is
> + * the task stack size.
> + */
> + size_t storage_size;
> +
> + /**
> + * @brief The initial task modes of the interrupt server.
> + */
> + rtems_mode modes;
> +
> + /**
> + * @brief The task attributes of the interrupt server.
> + */
> + rtems_attribute attributes;
> +
> + /**
> + * @brief An optional handler to destroy the interrupt server control handed
> + * over to rtems_interrupt_server_create().
> + *
> + * This handler is called in the context of the interrupt server to be
> + * destroyed.
> + */
> + void ( *destroy )( rtems_interrupt_server_control * );
> +} rtems_interrupt_server_config;
> +
> /**
> * @brief An interrupt server entry.
> *
> @@ -309,16 +373,19 @@ typedef struct {
> *
> * The server count pointer @a server_count may be @a NULL.
> *
> + * The task name of interrupt servers created by this function is
> + * rtems_build_name( 'I', 'R', 'Q', 'S' ).
> + *
> * This function may block.
> *
> - * @see rtems_task_create().
> + * @retval RTEMS_SUCCESSFUL The operation was successful.
> *
> - * @retval RTEMS_SUCCESSFUL Successful operation.
> - * @retval RTEMS_INCORRECT_STATE The interrupt servers are not initialized.
> - * @retval RTEMS_NO_MEMORY Not enough memory.
> - * @retval RTEMS_TOO_MANY No free task available to create at least one server task.
> - * @retval RTEMS_UNSATISFIED Task stack size too large.
> - * @retval RTEMS_INVALID_PRIORITY Invalid task priority.
> + * @retval RTEMS_INCORRECT_STATE The interrupt servers were already initialized.
> + *
> + * @return The function uses rtems_task_create(). If this operation is not
> + * successful, then its status code is returned.
> + *
> + * @see rtems_interrupt_server_create() and rtems_interrupt_server_destroy().
> */
> rtems_status_code rtems_interrupt_server_initialize(
> rtems_task_priority priority,
> @@ -328,6 +395,54 @@ rtems_status_code rtems_interrupt_server_initialize(
> uint32_t *server_count
> );
>
> +/**
> + * @brief Creates an interrupt server.
> + *
> + * This function may block.
> + *
> + * @param[out] control is the interrupt server control. The ownership of this
> + * structure is transferred from the caller of this function to the interrupt
> + * server management.
> + *
> + * @param config is the interrupt server configuration.
> + *
> + * @param[out] server_index is the pointer to a server index variable. The
> + * index of the built interrupt server will be stored in the referenced
> + * variable if the operation was successful.
> + *
> + * @retval RTEMS_SUCCESSFUL The operation was successful.
> + *
> + * @return The function uses rtems_task_create(). If this operation is not
> + * successful, then its status code is returned.
> + *
> + * @see rtems_interrupt_server_initialize() and
> + * rtems_interrupt_server_destroy().
> + */
> +rtems_status_code rtems_interrupt_server_create(
> + rtems_interrupt_server_control *control,
> + const rtems_interrupt_server_config *config,
> + uint32_t *server_index
> +);
> +
> +/**
> + * @brief Destroys the interrupt server.
> + *
> + * This function may block.
> + *
> + * The interrupt server deletes itself, so after the return of the function the
> + * interrupt server may be still in the termination process depending on the
> + * task priorities of the system.
> + *
> + * @param server_index is the index of the interrupt server to destroy. Use
> + * ::RTEMS_INTERRUPT_SERVER_DEFAULT to specify the default server.
> + *
> + * @retval RTEMS_SUCCESSFUL The operation was successful.
> + * @retval RTEMS_INVALID_ID The interrupt server index was invalid.
> + *
> + * @see rtems_interrupt_server_create()
> + */
> +rtems_status_code rtems_interrupt_server_destroy( uint32_t server_index );
> +
> /**
> * @brief Installs the interrupt handler routine @a handler for the interrupt
> * vector with number @a vector on the server @a server.
>
More information about the devel
mailing list