source: rtems/cpukit/posix/src/intr.c @ 92262ab

4.104.114.84.95
Last change on this file since 92262ab was eb5a7e07, checked in by Joel Sherrill <joel.sherrill@…>, on 10/06/95 at 20:48:38

fixed missing CVS IDs

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