source: rtems/c/src/exec/posix/src/intr.c @ 5e9b32b

4.104.114.84.95
Last change on this file since 5e9b32b was 5e9b32b, checked in by Joel Sherrill <joel.sherrill@…>, on 09/26/95 at 19:27:15

posix support initially added

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