source: rtems/c/src/exec/posix/src/killinfo.c @ 7558283

4.104.114.84.95
Last change on this file since 7558283 was 7558283, checked in by Joel Sherrill <joel.sherrill@…>, on 01/11/00 at 15:43:16

Fixed spacing.

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