source: rtems/c/src/exec/posix/src/intr.c @ f42b726

4.104.114.84.95
Last change on this file since f42b726 was f42b726, checked in by Joel Sherrill <joel.sherrill@…>, on 01/24/01 at 14:17:28

2001-01-24 Ralf Corsepius <corsepiu@…>

  • configure.in: Add src/config.h
  • src/Makefile.am: Add INCLUDES += -I. to pickup config.h
  • src/.cvsignore: Add config.h and stamp-h
  • src/*.c: Add config.h support.
  • Property mode set to 100644
File size: 8.0 KB
Line 
1/*
2 *  NOTE: Each task has an interrupt semaphore associated with it.
3 *        No matter which interrupt occurs that it has registered,
4 *        the same semaphore is used.
5 *
6 *  This whole interrupt scheme may have been eliminated in a later draft.
7 *
8 *  $Id$
9 */
10
11#if HAVE_CONFIG_H
12#include "config.h"
13#endif
14
15#include <errno.h>
16#include <intr.h>
17#include <pthread.h>
18
19#include <rtems/system.h>
20#include <rtems/score/isr.h>
21#include <rtems/score/coresem.h>
22#include <rtems/score/thread.h>
23#include <rtems/score/watchdog.h>
24#include <rtems/posix/intr.h>
25#include <rtems/posix/time.h>
26#include <rtems/posix/threadsup.h>
27
28/*
29 *  _POSIX_Interrupt_Manager_initialization
30 *
31 *  DESCRIPTION:
32 *
33 *  This routine performs the initialization necessary for this manager.
34 */
35 
36void _POSIX_Interrupt_Manager_initialization(
37  unsigned32  maximum_interrupt_handlers
38)
39{
40  unsigned32                index;
41  POSIX_Interrupt_Control  *the_vector;
42
43  _Objects_Initialize_information(
44    &_POSIX_Interrupt_Handlers_Information,
45    OBJECTS_POSIX_INTERRUPTS,
46    FALSE,
47    maximum_interrupt_handlers,
48    sizeof( POSIX_Interrupt_Handler_control ),
49    FALSE,
50    0,
51    FALSE
52  );
53
54  for ( index=0 ; index < CPU_INTERRUPT_NUMBER_OF_VECTORS ; index++ ) {
55    the_vector = &_POSIX_Interrupt_Information[ index ];
56   
57    the_vector->number_installed = 0;
58    the_vector->lock_count       = 0;
59    the_vector->deferred_count   = 0;
60    _Chain_Initialize_empty( &the_vector->Handlers );
61  }
62}
63
64/*PAGE
65 *
66 *  22.3.1 Associate a User-Written ISR with an Interrupt, P1003.4b/D8, p. 74
67 */
68
69int intr_capture(
70  intr_t          intr,
71  int           (*intr_handler)( void *area ),
72  volatile void   *area,
73  size_t           areasize
74)
75{
76  POSIX_Interrupt_Handler_control   *the_intr;
77  POSIX_Interrupt_Control           *the_vector;
78  POSIX_API_Thread_Support_Control  *thread_support;
79  proc_ptr                           old_handler;
80
81  if ( !_ISR_Is_vector_number_valid( intr ) ||
82       !_ISR_Is_valid_user_handler( intr_handler ) )
83    return EINVAL;
84
85  _Thread_Disable_dispatch();
86
87  the_intr = _POSIX_Interrupt_Allocate();
88 
89  if ( !the_intr ) {
90    _Thread_Enable_dispatch();
91    return ENOMEM;
92  }
93
94  the_vector = &_POSIX_Interrupt_Information[ intr ];
95
96  the_intr->vector         = intr;
97  the_intr->handler        = intr_handler;
98  the_intr->user_data_area = area;
99  the_intr->server         = _Thread_Executing;
100  the_intr->is_active      = TRUE;
101
102  thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
103  thread_support->interrupts_installed++;
104
105/* XXX should we malloc the semaphore on the fly???  if so we probably need to
106   release it when the thread has released all interrupts and keep
107   a count of how many it has installed.  CURRENTLY NO.. ALLOCATED w/TCB
108*/
109
110  /*
111   *  This is sufficient to have the handlers invoked in the opposite
112   *  order of installation.  The loop invoking them can then go from
113   *  the front of the list to the end.
114   */
115
116  _Chain_Prepend( &the_vector->Handlers, &the_intr->Object.Node );
117
118  if ( !the_vector->number_installed++ )
119    _ISR_Install_vector(
120      intr,
121      (proc_ptr) _POSIX_Interrupt_Handler,
122      &old_handler
123    );
124
125  _Objects_Open( &_POSIX_Interrupt_Handlers_Information, &the_intr->Object, 0 );
126 
127  /*
128   *  Normally, an Id would be returned here.
129   */
130 
131  _Thread_Enable_dispatch();
132 
133  return 0;
134}
135
136/*PAGE
137 *
138 *  22.3.1 Associate a User-Written ISR with an Interrupt, P1003.4b/D8, p. 74
139 */
140
141int intr_release(
142  intr_t    intr,
143  int     (*intr_handler)( void *area )
144)
145{
146  boolean                            found;
147  POSIX_Interrupt_Handler_control   *the_intr;
148  POSIX_Interrupt_Control           *the_vector;
149  POSIX_API_Thread_Support_Control  *thread_support;
150  Chain_Node                        *the_node;
151
152  if ( !_ISR_Is_valid_user_handler( intr_handler ) )
153    return EINVAL;
154
155  _Thread_Disable_dispatch();
156
157  /*
158   *  Since interrupt handlers do not have a user visible id, there is
159   *  no choice but to search the entire set of active interrupt handlers
160   *  to find this one.
161   */
162
163  found = FALSE;
164
165  the_vector = &_POSIX_Interrupt_Information[ intr ];
166
167  the_node = _Chain_Head( &the_vector->Handlers );
168
169  for ( ; !_Chain_Is_tail( &the_vector->Handlers, the_node ) ; ) {
170    the_intr = (POSIX_Interrupt_Handler_control *) the_node;
171
172    if ( the_intr->handler == intr_handler ) {
173       found = TRUE;
174       break;
175    }
176    the_node = the_node->next;
177  }
178
179  if ( !found ) {
180    _Thread_Enable_dispatch();
181    return EINVAL;
182  }
183
184  if ( !_Thread_Is_executing( the_intr->server ) ) {
185    _Thread_Enable_dispatch();
186    return EINVAL;  /* XXX should be ENOISR; */
187  }
188   
189  /*
190   *  OK now we have found the interrupt handler and can do some work.
191   */
192
193  _Chain_Extract( &the_intr->Object.Node );
194
195  the_intr->is_active = FALSE;
196 
197  the_vector->number_installed -= 1;
198
199  thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
200  thread_support->interrupts_installed--;
201
202  /*
203   *  It is unnecessary to flush the semaphore since the handler can only
204   *  be "removed" by the thread which installed it.  Thus it cannot be
205   *  blocked on the semaphore or it would not be executing this routine.
206   */
207
208  _Objects_Close( &_POSIX_Interrupt_Handlers_Information, &the_intr->Object );
209
210  _POSIX_Interrupt_Free( the_intr );
211 
212  _Thread_Enable_dispatch();
213
214  return 0;
215}
216
217/*PAGE
218 *
219 *  22.3.1 Associate a User-Written ISR with an Interrupt, P1003.4b/D8, p. 74
220 */
221
222int intr_lock(
223  intr_t  intr
224)
225{
226  POSIX_Interrupt_Control           *the_vector;
227
228  _Thread_Disable_dispatch();
229
230  the_vector = &_POSIX_Interrupt_Information[ intr ];
231
232  the_vector->lock_count++;
233
234  _Thread_Enable_dispatch();
235
236  return 0;
237}
238 
239/*PAGE
240 *
241 *  22.3.1 Associate a User-Written ISR with an Interrupt, P1003.4b/D8, p. 74
242 */
243
244int intr_unlock(
245  intr_t  intr
246)
247{
248  POSIX_Interrupt_Control           *the_vector;
249 
250  _Thread_Disable_dispatch();
251 
252  the_vector = &_POSIX_Interrupt_Information[ intr ];
253 
254  if ( !--the_vector->lock_count ) {
255    while ( --the_vector->deferred_count ) {
256      _POSIX_Interrupt_Handler( intr );
257    }
258  }
259 
260  _Thread_Enable_dispatch();
261 
262  return 0;
263}
264 
265/*
266 *  22.3.2 Await Interrupt Notification, P1003.4b/D8, p. 76
267 */
268
269int intr_timed_wait(
270  int                     flags,
271  const struct timespec  *timeout
272)
273{
274  Watchdog_Interval                  ticks;
275  POSIX_API_Thread_Support_Control  *thread_support;
276
277  ticks = _POSIX_Timespec_to_interval( timeout );
278
279  thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
280
281  _Thread_Disable_dispatch();
282
283    _CORE_semaphore_Seize(
284      &thread_support->Interrupt_Semaphore,
285      0,             /* XXX does id=0 hurt in this case? */
286      TRUE,
287      ticks
288    );
289  _Thread_Enable_dispatch();
290
291  return _Thread_Executing->Wait.return_code;  /* XXX should be POSIX */
292}
293
294/*PAGE
295 *
296 *  _POSIX_Interrupt_Handler
297 *
298 */
299
300void _POSIX_Interrupt_Handler(
301  ISR_Vector_number   vector
302)
303{
304  POSIX_Interrupt_Handler_control   *the_intr;
305  POSIX_Interrupt_Control           *the_vector;
306  POSIX_API_Thread_Support_Control  *thread_support;
307  Chain_Node                        *the_node;
308  int                                status;
309 
310  the_vector = &_POSIX_Interrupt_Information[ vector ];
311 
312  the_node = _Chain_Head( &the_vector->Handlers );
313 
314  for ( ; !_Chain_Is_tail( &the_vector->Handlers, the_node ) ; ) {
315    the_intr = (POSIX_Interrupt_Handler_control *) the_node;
316 
317    status = (*the_intr->handler)( (void *) the_intr->user_data_area );
318
319    switch ( status ) {
320      case INTR_HANDLED_NOTIFY:
321        thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
322
323        _CORE_semaphore_Surrender(
324          &thread_support->Interrupt_Semaphore,
325          0,                         /* XXX is id=0 a problem */
326          0                          /* XXX is this a problem (mp support)*/
327        );
328        return;
329
330      case INTR_HANDLED_DO_NOT_NOTIFY:
331        return;
332
333      case INTR_NOT_HANDLED:
334      default:                            /* this should not happen */
335        break;
336    }
337    the_node = the_node->next;
338  }
339
340  /* XXX
341   *
342   *  This is an unhandled interrupt!!!
343   */
344}
Note: See TracBrowser for help on using the repository browser.