OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [cpukit/] [posix/] [src/] [intr.c] - Blame information for rev 1026

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.