source: rtems/c/src/exec/posix/src/intr.c @ 811fae1

4.104.114.84.95
Last change on this file since 811fae1 was 5b748a1, checked in by Joel Sherrill <joel.sherrill@…>, on 06/03/96 at 17:32:19

renamed _POSIX_Time_Spec_to_interval to _POSIX_Timespec_to_interval

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