source: rtems/cpukit/posix/src/killinfo.c @ 07d880f4

4.104.114.84.95
Last change on this file since 07d880f4 was 07d880f4, checked in by Joel Sherrill <joel.sherrill@…>, on 01/31/99 at 20:45:31

Split psignal.c into many more files. This reduced the amount of
object code that has to be loaded just for initializing the signal
manager.

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