source: rtems/cpukit/posix/src/killinfo.c @ f22ebf0

4.104.114.84.95
Last change on this file since f22ebf0 was e180a77e, checked in by Joel Sherrill <joel.sherrill@…>, on 01/04/02 at 18:28:24

2002-01-04 Ralf Corsepius <corsepiu@…>

  • src/clockgetres.c: Apply rtems_set_errno_and_return_minus_one.
  • src/clockgettime.c: Apply rtems_set_errno_and_return_minus_one.
  • src/clocksettime.c: Apply rtems_set_errno_and_return_minus_one.
  • src/killinfo.c: Apply rtems_set_errno_and_return_minus_one.
  • src/mqueueclose.c: Apply rtems_set_errno_and_return_minus_one.
  • src/mqueuecreatesupp.c: Apply rtems_set_errno_and_return_minus_one.
  • src/mqueuegetattr.c: Apply rtems_set_errno_and_return_minus_one.
  • src/mqueuenotify.c: Apply rtems_set_errno_and_return_minus_one.
  • src/mqueueopen.c: Apply rtems_set_errno_and_return_minus_one.
  • src/mqueuerecvsupp.c: Apply rtems_set_errno_and_return_minus_one.
  • src/mqueuesendsupp.c: Apply rtems_set_errno_and_return_minus_one.
  • src/mqueuesetattr.c: Apply rtems_set_errno_and_return_minus_one.
  • src/mqueueunlink.c: Apply rtems_set_errno_and_return_minus_one.
  • src/nanosleep.c: Apply rtems_set_errno_and_return_minus_one.
  • src/pthreadkill.c: Apply rtems_set_errno_and_return_minus_one.
  • src/pthreadsigmask.c: Apply rtems_set_errno_and_return_minus_one.
  • src/ptimer1.c: Apply rtems_set_errno_and_return_minus_one.
  • src/sched.c: Apply rtems_set_errno_and_return_minus_one.
  • src/semaphorecreatesupp.c: Apply rtems_set_errno_and_return_minus_one.
  • src/semaphorewaitsupp.c: Apply rtems_set_errno_and_return_minus_one.
  • src/semclose.c: Apply rtems_set_errno_and_return_minus_one.
  • src/semdestroy.c: Apply rtems_set_errno_and_return_minus_one.
  • src/semgetvalue.c: Apply rtems_set_errno_and_return_minus_one.
  • src/seminit.c: Apply rtems_set_errno_and_return_minus_one.
  • src/semopen.c: Apply rtems_set_errno_and_return_minus_one.
  • src/sempost.c: Apply rtems_set_errno_and_return_minus_one.
  • src/semunlink.c: Apply rtems_set_errno_and_return_minus_one.
  • src/setpgid.c: Apply rtems_set_errno_and_return_minus_one.
  • src/setsid.c: Apply rtems_set_errno_and_return_minus_one.
  • src/sigaction.c: Apply rtems_set_errno_and_return_minus_one.
  • src/sigaddset.c: Apply rtems_set_errno_and_return_minus_one.
  • src/sigdelset.c: Apply rtems_set_errno_and_return_minus_one.
  • src/sigemptyset.c: Apply rtems_set_errno_and_return_minus_one.
  • src/sigfillset.c: Apply rtems_set_errno_and_return_minus_one.
  • src/sigismember.c: Apply rtems_set_errno_and_return_minus_one.
  • src/sigpending.c: Apply rtems_set_errno_and_return_minus_one.
  • src/sigtimedwait.c: Apply rtems_set_errno_and_return_minus_one.
  • src/utsname.c: Apply rtems_set_errno_and_return_minus_one.
  • 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#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         
39int 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_class;
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_class = OBJECTS_CLASSES_FIRST_THREAD_CLASS;
174        the_class <= OBJECTS_CLASSES_LAST_THREAD_CLASS;
175        the_class++ ) {
176
177    if ( the_class == OBJECTS_INTERNAL_THREADS )
178      continue;
179
180    the_info = _Objects_Information_table[ the_class ];
181
182    if ( !the_info )                        /* manager not installed */
183      continue;
184
185    maximum = the_info->maximum;
186    object_table = the_info->local_table;
187
188    assert( object_table );                 /* always at least 1 entry */
189
190    for ( index = 1 ; index <= maximum ; index++ ) {
191      the_thread = (Thread_Control *) object_table[ index ];
192
193      if ( !the_thread )
194        continue;
195
196      /*
197       *  If this thread is of lower priority than the interested thread,
198       *  go on to the next thread.
199       */
200
201      if ( the_thread->current_priority > interested_priority )
202        continue;
203
204      /*
205       *  If this thread is not interested, then go on to the next thread.
206       */
207
208      api = the_thread->API_Extensions[ THREAD_API_POSIX ];
209
210      if ( !api || !_POSIX_signals_Is_interested( api, mask ) )
211        continue;
212
213      /*
214       *  Now we know the thread under connsideration is interested.
215       *  If the thread under consideration is of higher priority, then
216       *  it becomes the interested thread.
217       */
218
219      if ( the_thread->current_priority < interested_priority ) {
220        interested_thread   = the_thread;
221        interested_priority = the_thread->current_priority;
222        continue;
223      }
224
225      /*
226       *  Now the thread and the interested thread have the same priority.
227       *  If the interested thread is ready, then we don't need to send it
228       *  to a blocked thread.
229       */
230
231      if ( _States_Is_ready( interested_thread->current_state ) )
232        continue;
233
234      /*
235       *  Now the interested thread is blocked.
236       *  If the thread we are considering is not, the it becomes the
237       *  interested thread.
238       */
239
240      if ( _States_Is_ready( the_thread->current_state ) ) {
241        interested_thread   = the_thread;
242        interested_priority = the_thread->current_priority;
243        continue;
244      }
245
246      /*
247       *  Now we know both threads are blocked.
248       *  If the interested thread is interruptible, then just use it.
249       */
250
251      /* XXX need a new states macro */
252      if ( interested_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL )
253        continue;
254
255      /*
256       *  Now both threads are blocked and the interested thread is not
257       *  interruptible.
258       *  If the thread under consideration is interruptible by a signal,
259       *  then it becomes the interested thread.
260       */
261
262      /* XXX need a new states macro */
263      if ( the_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL ) {
264        interested_thread   = the_thread;
265        interested_priority = the_thread->current_priority;
266      }
267    }
268  }
269
270  if ( interested_thread ) {
271    the_thread = interested_thread;
272    goto process_it;
273  }
274
275  /*
276   *  OK so no threads were interested right now.  It will be left on the
277   *  global pending until a thread receives it.  The global set of threads
278   *  can change interest in this signal in one of the following ways:
279   *
280   *    + a thread is created with the signal unblocked,
281   *    + pthread_sigmask() unblocks the signal,
282   *    + sigprocmask() unblocks the signal, OR
283   *    + sigaction() which changes the handler to SIG_IGN.
284   */
285
286  the_thread = NULL;
287  goto post_process_signal;
288
289  /*
290   *  We found a thread which was interested, so now we mark that this
291   *  thread needs to do the post context switch extension so it can
292   *  evaluate the signals pending.
293   */
294
295process_it:
296 
297  the_thread->do_post_task_switch_extension = TRUE;
298
299  /*
300   *  Returns TRUE if the signal was synchronously given to a thread
301   *  blocked waiting for the signal.
302   */
303
304  if ( _POSIX_signals_Unblock_thread( the_thread, sig, siginfo ) ) {
305    _Thread_Enable_dispatch();
306    return 0;
307  }
308
309post_process_signal:
310
311  /*
312   *  We may have woken up a thread but we definitely need to post the
313   *  signal to the process wide information set.
314   */
315
316  _POSIX_signals_Set_process_signals( mask );
317
318  if ( _POSIX_signals_Vectors[ sig ].sa_flags == SA_SIGINFO ) {
319
320    psiginfo = (POSIX_signals_Siginfo_node *)
321               _Chain_Get( &_POSIX_signals_Inactive_siginfo );
322    if ( !psiginfo ) {
323      rtems_set_errno_and_return_minus_one( EAGAIN );
324    }
325
326    psiginfo->Info = *siginfo;
327
328    _Chain_Append( &_POSIX_signals_Siginfo[ sig ], &psiginfo->Node );
329  }
330
331  _Thread_Enable_dispatch();
332  return 0;
333}
Note: See TracBrowser for help on using the repository browser.