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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1026 ivang
/*
2
 *  kill() support routine
3
 *
4
 *  COPYRIGHT (c) 1989-1999.
5
 *  On-Line Applications Research Corporation (OAR).
6
 *
7
 *  The license and distribution terms for this file may be
8
 *  found in the file LICENSE in this distribution or at
9
 *  http://www.OARcorp.com/rtems/license.html.
10
 *
11
 *  killinfo.c,v 1.8 2002/07/01 22:33:47 joel Exp
12
 */
13
 
14
#if HAVE_CONFIG_H
15
#include "config.h"
16
#endif
17
 
18
#include <pthread.h>
19
#include <signal.h>
20
#include <errno.h>
21
#include <assert.h>
22
 
23
#include <rtems/system.h>
24
#include <rtems/posix/pthread.h>
25
#include <rtems/posix/psignal.h>
26
#include <rtems/seterr.h>
27
#include <rtems/score/isr.h>
28
 
29
/*PAGE
30
 *
31
 *  3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68
32
 *
33
 *  NOTE: Behavior of kill() depends on _POSIX_SAVED_IDS.
34
 */
35
 
36
#define _POSIX_signals_Is_interested( _api, _mask ) \
37
  ( ~(_api)->signals_blocked & (_mask) )
38
 
39
int killinfo(
40
  pid_t               pid,
41
  int                 sig,
42
  const union sigval *value
43
)
44
{
45
  sigset_t                     mask;
46
  POSIX_API_Control           *api;
47
  unsigned32                   the_api;
48
  unsigned32                   index;
49
  unsigned32                   maximum;
50
  Objects_Information         *the_info;
51
  Objects_Control            **object_table;
52
  Thread_Control              *the_thread;
53
  Thread_Control              *interested_thread;
54
  Priority_Control             interested_priority;
55
  Chain_Control               *the_chain;
56
  Chain_Node                  *the_node;
57
  siginfo_t                    siginfo_struct;
58
  siginfo_t                   *siginfo;
59
  POSIX_signals_Siginfo_node  *psiginfo;
60
 
61
  /*
62
   *  Only supported for the "calling process" (i.e. this node).
63
   */
64
 
65
  if ( pid != getpid() )
66
    rtems_set_errno_and_return_minus_one( ESRCH );
67
 
68
  /*
69
   *  Validate the signal passed if not 0.
70
   */
71
 
72
  if ( sig && !is_valid_signo(sig) ) {
73
    rtems_set_errno_and_return_minus_one( EINVAL );
74
  }
75
 
76
  /*
77
   *  If the signal is being ignored, then we are out of here.
78
   */
79
 
80
  if ( !sig || _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN ) {
81
    return 0;
82
  }
83
 
84
  /*
85
   *  P1003.1c/Draft 10, p. 33 says that certain signals should always
86
   *  be directed to the executing thread such as those caused by hardware
87
   *  faults.
88
   */
89
 
90
  switch ( sig ) {
91
    case SIGFPE:
92
    case SIGILL:
93
    case SIGSEGV:
94
      return pthread_kill( pthread_self(), sig );
95
    default:
96
      break;
97
  }
98
 
99
  mask = signo_to_mask( sig );
100
 
101
  /*
102
   *  Build up a siginfo structure
103
   */
104
 
105
  siginfo = &siginfo_struct;
106
  siginfo->si_signo = sig;
107
  siginfo->si_code = SI_USER;
108
  if ( !value ) {
109
    siginfo->si_value.sival_int = 0;
110
  } else {
111
    siginfo->si_value = *value;
112
  }
113
 
114
  _Thread_Disable_dispatch();
115
 
116
  /*
117
   *  Is the currently executing thread interested?  If so then it will
118
   *  get it an execute it as soon as the dispatcher executes.
119
   */
120
 
121
  the_thread = _Thread_Executing;
122
 
123
  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
124
  if ( _POSIX_signals_Is_interested( api, mask ) ) {
125
    goto process_it;
126
  }
127
 
128
  /*
129
   *  Is an interested thread waiting for this signal (sigwait())?
130
   */
131
 
132
  /* XXX violation of visibility -- need to define thread queue support */
133
 
134
  for( index=0 ;
135
       index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
136
       index++ ) {
137
 
138
    the_chain = &_POSIX_signals_Wait_queue.Queues.Priority[ index ];
139
 
140
    for ( the_node = the_chain->first ;
141
          !_Chain_Is_tail( the_chain, the_node ) ;
142
          the_node = the_node->next ) {
143
 
144
      the_thread = (Thread_Control *)the_node;
145
      api = the_thread->API_Extensions[ THREAD_API_POSIX ];
146
 
147
      if ((the_thread->Wait.option & mask) || (~api->signals_blocked & mask)) {
148
        goto process_it;
149
      }
150
 
151
    }
152
  }
153
 
154
  /*
155
   *  Is any other thread interested?  The highest priority interested
156
   *  thread is selected.  In the event of a tie, then the following
157
   *  additional criteria is used:
158
   *
159
   *    + ready thread over blocked
160
   *    + blocked on call interruptible by signal (can return EINTR)
161
   *    + blocked on call not interruptible by signal
162
   *
163
   *  This looks at every thread in the system regardless of the creating API.
164
   *
165
   *  NOTES:
166
   *
167
   *    + rtems internal threads do not receive signals.
168
   */
169
 
170
  interested_thread = NULL;
171
  interested_priority = PRIORITY_MAXIMUM + 1;
172
 
173
  for ( the_api = 2;
174
        the_api <= OBJECTS_APIS_LAST;
175
        the_api++ ) {
176
 
177
    if ( the_api == OBJECTS_INTERNAL_THREADS )
178
      continue;
179
 
180
    if ( !_Objects_Information_table[ the_api ] )  /* API not installed */
181
      continue;
182
 
183
    the_info = _Objects_Information_table[ the_api ][ 1 ];
184
 
185
    if ( !the_info )                        /* manager not installed */
186
      continue;
187
 
188
    maximum = the_info->maximum;
189
    object_table = the_info->local_table;
190
 
191
    assert( object_table );                 /* always at least 1 entry */
192
 
193
    for ( index = 1 ; index <= maximum ; index++ ) {
194
      the_thread = (Thread_Control *) object_table[ index ];
195
 
196
      if ( !the_thread )
197
        continue;
198
 
199
      /*
200
       *  If this thread is of lower priority than the interested thread,
201
       *  go on to the next thread.
202
       */
203
 
204
      if ( the_thread->current_priority > interested_priority )
205
        continue;
206
 
207
      /*
208
       *  If this thread is not interested, then go on to the next thread.
209
       */
210
 
211
      api = the_thread->API_Extensions[ THREAD_API_POSIX ];
212
 
213
      if ( !api || !_POSIX_signals_Is_interested( api, mask ) )
214
        continue;
215
 
216
      /*
217
       *  Now we know the thread under connsideration is interested.
218
       *  If the thread under consideration is of higher priority, then
219
       *  it becomes the interested thread.
220
       */
221
 
222
      if ( the_thread->current_priority < interested_priority ) {
223
        interested_thread   = the_thread;
224
        interested_priority = the_thread->current_priority;
225
        continue;
226
      }
227
 
228
      /*
229
       *  Now the thread and the interested thread have the same priority.
230
       *  If the interested thread is ready, then we don't need to send it
231
       *  to a blocked thread.
232
       */
233
 
234
      if ( _States_Is_ready( interested_thread->current_state ) )
235
        continue;
236
 
237
      /*
238
       *  Now the interested thread is blocked.
239
       *  If the thread we are considering is not, the it becomes the
240
       *  interested thread.
241
       */
242
 
243
      if ( _States_Is_ready( the_thread->current_state ) ) {
244
        interested_thread   = the_thread;
245
        interested_priority = the_thread->current_priority;
246
        continue;
247
      }
248
 
249
      /*
250
       *  Now we know both threads are blocked.
251
       *  If the interested thread is interruptible, then just use it.
252
       */
253
 
254
      /* XXX need a new states macro */
255
      if ( interested_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL )
256
        continue;
257
 
258
      /*
259
       *  Now both threads are blocked and the interested thread is not
260
       *  interruptible.
261
       *  If the thread under consideration is interruptible by a signal,
262
       *  then it becomes the interested thread.
263
       */
264
 
265
      /* XXX need a new states macro */
266
      if ( the_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL ) {
267
        interested_thread   = the_thread;
268
        interested_priority = the_thread->current_priority;
269
      }
270
    }
271
  }
272
 
273
  if ( interested_thread ) {
274
    the_thread = interested_thread;
275
    goto process_it;
276
  }
277
 
278
  /*
279
   *  OK so no threads were interested right now.  It will be left on the
280
   *  global pending until a thread receives it.  The global set of threads
281
   *  can change interest in this signal in one of the following ways:
282
   *
283
   *    + a thread is created with the signal unblocked,
284
   *    + pthread_sigmask() unblocks the signal,
285
   *    + sigprocmask() unblocks the signal, OR
286
   *    + sigaction() which changes the handler to SIG_IGN.
287
   */
288
 
289
  the_thread = NULL;
290
  goto post_process_signal;
291
 
292
  /*
293
   *  We found a thread which was interested, so now we mark that this
294
   *  thread needs to do the post context switch extension so it can
295
   *  evaluate the signals pending.
296
   */
297
 
298
process_it:
299
 
300
  the_thread->do_post_task_switch_extension = TRUE;
301
 
302
  /*
303
   *  Returns TRUE if the signal was synchronously given to a thread
304
   *  blocked waiting for the signal.
305
   */
306
 
307
  if ( _POSIX_signals_Unblock_thread( the_thread, sig, siginfo ) ) {
308
    _Thread_Enable_dispatch();
309
    return 0;
310
  }
311
 
312
post_process_signal:
313
 
314
  /*
315
   *  We may have woken up a thread but we definitely need to post the
316
   *  signal to the process wide information set.
317
   */
318
 
319
  _POSIX_signals_Set_process_signals( mask );
320
 
321
  if ( _POSIX_signals_Vectors[ sig ].sa_flags == SA_SIGINFO ) {
322
 
323
    psiginfo = (POSIX_signals_Siginfo_node *)
324
               _Chain_Get( &_POSIX_signals_Inactive_siginfo );
325
    if ( !psiginfo ) {
326
      rtems_set_errno_and_return_minus_one( EAGAIN );
327
    }
328
 
329
    psiginfo->Info = *siginfo;
330
 
331
    _Chain_Append( &_POSIX_signals_Siginfo[ sig ], &psiginfo->Node );
332
  }
333
 
334
  _Thread_Enable_dispatch();
335
  return 0;
336
}

powered by: WebSVN 2.1.0

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