source: rtems/bsps/shared/irq/irq-generic.c

Last change on this file was c7b4eca7, checked in by Sebastian Huber <sebastian.huber@…>, on Jul 27, 2021 at 7:58:43 AM

bsps/irq: bsp_interrupt_facility_initialize()

Do not return a status code in bsp_interrupt_facility_initialize() since this
leads to unreachable code in bsp_interrupt_initialize(). Use RTEMS_DEBUG
assertions in bsp_interrupt_facility_initialize() if necessary.

  • Property mode set to 100644
File size: 7.2 KB
Line 
1/* SPDX-License-Identifier: BSD-2-Clause */
2
3/**
4 * @file
5 *
6 * @ingroup bsp_interrupt
7 *
8 * @brief This source file contains the generic interrupt controller support
9 *   implementation.
10 */
11
12/*
13 * Copyright (C) 2008, 2021 embedded brains GmbH (http://www.embedded-brains.de)
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 *    notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 *    notice, this list of conditions and the following disclaimer in the
22 *    documentation and/or other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include <bsp/irq-generic.h>
38#include <bsp/fatal.h>
39
40#include <stdlib.h>
41
42#include <rtems/malloc.h>
43
44#ifdef BSP_INTERRUPT_USE_INDEX_TABLE
45  bsp_interrupt_handler_index_type bsp_interrupt_handler_index_table
46    [BSP_INTERRUPT_VECTOR_COUNT];
47#endif
48
49rtems_interrupt_entry *
50bsp_interrupt_handler_table[ BSP_INTERRUPT_HANDLER_TABLE_SIZE ];
51
52/* The last entry indicates if everything is initialized */
53uint8_t bsp_interrupt_handler_unique_table
54  [ ( BSP_INTERRUPT_HANDLER_TABLE_SIZE + 7 + 1 ) / 8 ];
55
56static inline void bsp_interrupt_set_initialized(void)
57{
58  bsp_interrupt_set_handler_unique(BSP_INTERRUPT_HANDLER_TABLE_SIZE, true);
59}
60
61#if defined(BSP_INTERRUPT_USE_INDEX_TABLE)
62static inline rtems_vector_number bsp_interrupt_allocate_handler_index(
63  rtems_vector_number vector
64)
65{
66  rtems_vector_number i;
67
68  /* The first entry will remain empty */
69  for ( i = 1; i < BSP_INTERRUPT_HANDLER_TABLE_SIZE; ++i ) {
70    if (  bsp_interrupt_handler_table[ i ] == NULL ) {
71      break;
72    }
73  }
74
75  return i;
76}
77#endif
78
79#if defined(RTEMS_SMP)
80RTEMS_STATIC_ASSERT(
81  sizeof( Atomic_Uintptr ) == sizeof( rtems_interrupt_entry * ),
82  rtems_interrupt_entry_pointer_size
83);
84
85void bsp_interrupt_spurious( rtems_vector_number vector )
86{
87  Atomic_Uintptr        *ptr;
88  rtems_interrupt_entry *first;
89
90  /*
91   * In order to get the last written pointer value to the first entry, we have
92   * to carry out an atomic read-modify-write operation.
93   */
94  ptr = (Atomic_Uintptr *) &bsp_interrupt_handler_table[
95    bsp_interrupt_handler_index( vector )
96  ];
97  first = (rtems_interrupt_entry *)
98    _Atomic_Fetch_add_uintptr( ptr, 0, ATOMIC_ORDER_ACQUIRE );
99
100  if ( first == NULL ) {
101    bsp_interrupt_handler_default( vector );
102  } else {
103    bsp_interrupt_dispatch_entries( first );
104  }
105}
106#endif
107
108rtems_status_code bsp_interrupt_check_and_lock(
109  rtems_vector_number     vector,
110  rtems_interrupt_handler routine
111)
112{
113  if ( !bsp_interrupt_is_initialized() ) {
114    return RTEMS_INCORRECT_STATE;
115  }
116
117  if ( routine == NULL ) {
118    return RTEMS_INVALID_ADDRESS;
119  }
120
121  if ( !bsp_interrupt_is_valid_vector( vector ) ) {
122    return RTEMS_INVALID_ID;
123  }
124
125  if ( rtems_interrupt_is_in_progress() ) {
126    return RTEMS_CALLED_FROM_ISR;
127  }
128
129  bsp_interrupt_lock();
130
131  return RTEMS_SUCCESSFUL;
132}
133
134rtems_interrupt_entry *bsp_interrupt_entry_find(
135  rtems_vector_number      vector,
136  rtems_interrupt_handler  routine,
137  void                    *arg,
138  rtems_interrupt_entry ***previous_next
139)
140{
141  rtems_vector_number    index;
142  rtems_interrupt_entry *entry;
143
144  bsp_interrupt_assert( bsp_interrupt_is_valid_vector( vector ) );
145  index = bsp_interrupt_handler_index( vector );
146  *previous_next = &bsp_interrupt_handler_table[ index ];
147  entry = bsp_interrupt_handler_table[ index ];
148
149  while ( entry != NULL ) {
150    if ( entry->handler == routine && entry->arg == arg ) {
151      return entry;
152    }
153
154    *previous_next = &entry->next;
155    entry = entry->next;
156  }
157
158  return NULL;
159}
160
161void bsp_interrupt_initialize( void )
162{
163  bsp_interrupt_facility_initialize();
164  bsp_interrupt_set_initialized();
165}
166
167static rtems_status_code bsp_interrupt_entry_install_first(
168  rtems_vector_number       vector,
169  rtems_option              options,
170  rtems_interrupt_entry    *entry
171)
172{
173  rtems_vector_number index;
174
175#ifdef BSP_INTERRUPT_USE_INDEX_TABLE
176  index = bsp_interrupt_allocate_handler_index( vector );
177
178  if ( index == BSP_INTERRUPT_HANDLER_TABLE_SIZE ) {
179    /* Handler table is full */
180    return RTEMS_NO_MEMORY;
181  }
182#else
183  index = vector;
184#endif
185
186#ifdef BSP_INTERRUPT_USE_INDEX_TABLE
187  bsp_interrupt_handler_index_table[ vector ] = index;
188#endif
189  bsp_interrupt_entry_store_release(
190    &bsp_interrupt_handler_table[ index ],
191    entry
192  );
193
194  bsp_interrupt_set_handler_unique(
195    index,
196    RTEMS_INTERRUPT_IS_UNIQUE( options )
197  );
198#if defined(bsp_interrupt_vector_install)
199  bsp_interrupt_vector_install( vector );
200#else
201  bsp_interrupt_vector_enable( vector );
202#endif
203
204  return RTEMS_SUCCESSFUL;
205}
206
207static rtems_status_code bsp_interrupt_entry_install(
208  rtems_vector_number    vector,
209  rtems_option           options,
210  rtems_interrupt_entry *entry
211)
212{
213  rtems_vector_number     index;
214  rtems_interrupt_entry  *first;
215  rtems_interrupt_entry  *other;
216  rtems_interrupt_entry **previous_next;
217
218  if ( RTEMS_INTERRUPT_IS_REPLACE( options ) ) {
219    return RTEMS_INVALID_NUMBER;
220  }
221
222  index = bsp_interrupt_handler_index( vector );
223  first = bsp_interrupt_handler_table[ index ];
224
225  if ( first == NULL ) {
226    return bsp_interrupt_entry_install_first( vector, options, entry );
227  }
228
229  if ( RTEMS_INTERRUPT_IS_UNIQUE( options ) ) {
230    /* Cannot install a unique entry if there is already an entry installed */
231    return RTEMS_RESOURCE_IN_USE;
232  }
233
234  if ( bsp_interrupt_is_handler_unique( index ) ) {
235    /*
236     * Cannot install another entry if there is already an unique entry
237     * installed.
238     */
239    return RTEMS_RESOURCE_IN_USE;
240  }
241
242  other = bsp_interrupt_entry_find(
243    vector,
244    entry->handler,
245    entry->arg,
246    &previous_next
247  );
248
249  if ( other != NULL ) {
250    /*
251     * Cannot install an entry which has the same routine and argument as an
252     * already installed entry.
253     */
254    return RTEMS_TOO_MANY;
255  }
256
257  bsp_interrupt_entry_store_release( previous_next, entry );
258
259  return RTEMS_SUCCESSFUL;
260}
261
262rtems_status_code rtems_interrupt_entry_install(
263  rtems_vector_number    vector,
264  rtems_option           options,
265  rtems_interrupt_entry *entry
266)
267{
268  rtems_status_code sc;
269
270  if ( entry == NULL ) {
271    return RTEMS_INVALID_ADDRESS;
272  }
273
274  sc = bsp_interrupt_check_and_lock( vector, entry->handler );
275
276  if ( sc != RTEMS_SUCCESSFUL ) {
277    return sc;
278  }
279
280  sc = bsp_interrupt_entry_install( vector, options, entry );
281  bsp_interrupt_unlock();
282
283  return sc;
284}
Note: See TracBrowser for help on using the repository browser.