[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