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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [exec/] [posix/] [src/] [intr.c] - Blame information for rev 214

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

Line No. Rev Author Line
1 30 unneback
/*
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: intr.c,v 1.2 2001-09-27 11:59:17 chris Exp $
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
 
32
void _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
 
65
int 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
 
137
int 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
 
218
int 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
 
240
int 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
 
265
int 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
 
296
void _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
 
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
}

powered by: WebSVN 2.1.0

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