source: rtems/cpukit/posix/src/intr.c @ 0553a3a

4.104.114.84.95
Last change on this file since 0553a3a was f4719d5a, checked in by Joel Sherrill <joel.sherrill@…>, on 05/22/96 at 22:32:39

These files have been modified in the initial pass at getting the portion
of the POSIX API necessary to support the GNAT runtime to initially compile.
We now have verified that the specifications for the necessary routines
are correct per the POSIX standards we have.

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