From ccc87c8b9ed61d2bcf01c5721a0336a611be970e Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Tue, 11 Jul 2017 11:20:06 +0200 Subject: Add interrupt server move Update #3071. --- c/src/lib/libbsp/shared/src/irq-server.c | 75 ++++++++++++++++++++++++++++++++ cpukit/include/rtems/irq-extension.h | 26 +++++++++++ 2 files changed, 101 insertions(+) diff --git a/c/src/lib/libbsp/shared/src/irq-server.c b/c/src/lib/libbsp/shared/src/irq-server.c index 61d31754c2..a7b277c62c 100644 --- a/c/src/lib/libbsp/shared/src/irq-server.c +++ b/c/src/lib/libbsp/shared/src/irq-server.c @@ -694,6 +694,81 @@ rtems_status_code rtems_interrupt_server_request_initialize( return RTEMS_SUCCESSFUL; } +static void bsp_interrupt_server_handler_move_helper(void *arg) +{ + bsp_interrupt_server_helper_data *hd = arg; + bsp_interrupt_server_handler_iterate_helper_data *hihd = hd->arg; + rtems_interrupt_server_entry *e; + rtems_option trigger_options; + + bsp_interrupt_lock(); + + 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; + bool pending; + + rtems_interrupt_lock_acquire(&src->lock, &lock_context); + + pending = !rtems_chain_is_node_off_chain(&e->node); + if (pending) { + rtems_chain_extract_unprotected(&e->node); + rtems_chain_set_off_chain(&e->node); + } + + rtems_interrupt_lock_release(&src->lock, &lock_context); + + e->server = dst; + + if (pending) { + bsp_interrupt_server_trigger(e); + } + } + + bsp_interrupt_unlock(); + + rtems_event_transient_send(hd->task); +} + +rtems_status_code rtems_interrupt_server_move( + uint32_t source_server_index, + rtems_vector_number vector, + uint32_t destination_server_index +) +{ + rtems_status_code sc; + bsp_interrupt_server_context *src; + bsp_interrupt_server_context *dst; + bsp_interrupt_server_handler_iterate_helper_data hihd; + + src = bsp_interrupt_server_get_context(source_server_index, &sc); + if (src == NULL) { + return sc; + } + + dst = bsp_interrupt_server_get_context(destination_server_index, &sc); + if (dst == NULL) { + return sc; + } + + if (!bsp_interrupt_is_valid_vector(vector)) { + return RTEMS_INVALID_ID; + } + + hihd.arg = dst; + bsp_interrupt_server_call_helper( + src, + vector, + 0, + NULL, + &hihd, + bsp_interrupt_server_handler_move_helper + ); + return RTEMS_SUCCESSFUL; +} + static void bsp_interrupt_server_entry_suspend_helper(void *arg) { bsp_interrupt_server_helper_data *hd = arg; diff --git a/cpukit/include/rtems/irq-extension.h b/cpukit/include/rtems/irq-extension.h index 9cade113ad..e3fb4c5fea 100644 --- a/cpukit/include/rtems/irq-extension.h +++ b/cpukit/include/rtems/irq-extension.h @@ -361,6 +361,32 @@ rtems_status_code rtems_interrupt_server_handler_iterate( void *arg ); +/** + * @brief Moves the interrupt handlers installed on the specified source + * interrupt server to the destination interrupt server. + * + * This function must be called from thread context. It may block. Calling + * this function within the context of an interrupt server is undefined + * behaviour. + * + * @param[in] source_server_index The source interrupt server index. Use + * @c RTEMS_INTERRUPT_SERVER_DEFAULT to specify the default server. + * @param[in] vector The interrupt vector number. + * @param[in] destination_server_index The destination interrupt server index. + * Use @c RTEMS_INTERRUPT_SERVER_DEFAULT to specify the default server. + * + * @retval RTEMS_SUCCESSFUL Successful operation + * @retval RTEMS_INCORRECT_STATE The interrupt servers are not initialized. + * @retval RTEMS_INVALID_ID The destination interrupt server index is invalid. + * @retval RTEMS_INVALID_ID The vector number is invalid. + * @retval RTEMS_INVALID_ID The destination interrupt server index is invalid. + */ +rtems_status_code rtems_interrupt_server_move( + uint32_t source_server_index, + rtems_vector_number vector, + uint32_t destination_server_index +); + /** * @brief Suspends the specified interrupt server. * -- cgit v1.2.3