source: rtems/cpukit/posix/src/psignal.c @ 89b63972

4.104.114.84.95
Last change on this file since 89b63972 was 89b63972, checked in by Joel Sherrill <joel.sherrill@…>, on Nov 1, 1999 at 6:02:44 PM

Removed routines that had already been separated into their own files.

  • Property mode set to 100644
File size: 11.4 KB
Line 
1/*
2 *  $Id$
3 */
4
5#include <assert.h>
6#include <errno.h>
7#include <pthread.h>
8#include <signal.h>
9
10#include <rtems/system.h>
11#include <rtems/score/isr.h>
12#include <rtems/score/thread.h>
13#include <rtems/score/tqdata.h>
14#include <rtems/score/wkspace.h>
15#include <rtems/posix/seterr.h>
16#include <rtems/posix/threadsup.h>
17#include <rtems/posix/psignal.h>
18#include <rtems/posix/pthread.h>
19#include <rtems/posix/time.h>
20#include <stdio.h>
21
22
23/*
24 *  Currently 32 signals numbered 1-32 are defined
25 */
26
27#define SIGNAL_EMPTY_MASK  0x00000000
28#define SIGNAL_ALL_MASK    0xffffffff
29
30#define signo_to_mask( _sig ) (1 << ((_sig) - 1))
31
32#define is_valid_signo( _sig ) \
33  ((_sig) >= 1 && (_sig) <= 32 )
34
35/*** PROCESS WIDE STUFF ****/
36
37sigset_t  _POSIX_signals_Pending;
38
39void _POSIX_signals_Abnormal_termination_handler( int signo )
40{
41  exit( 1 );
42}
43
44#define SIG_ARRAY_MAX  (SIGRTMAX + 1)
45struct sigaction _POSIX_signals_Default_vectors[ SIG_ARRAY_MAX ] = {
46  /* NO SIGNAL 0 */  SIGACTION_IGNORE,
47  /* SIGHUP    1 */  SIGACTION_TERMINATE,
48  /* SIGINT    2 */  SIGACTION_TERMINATE,
49  /* SIGQUIT   3 */  SIGACTION_TERMINATE,
50  /* SIGILL    4 */  SIGACTION_TERMINATE,
51  /* SIGTRAP   5 */  SIGACTION_TERMINATE,
52  /* SIGIOT    6 */  SIGACTION_TERMINATE,
53  /* SIGABRT   6     SIGACTION_TERMINATE, -- alias for SIGIOT */
54  /* SIGEMT    7 */  SIGACTION_TERMINATE,
55  /* SIGFPE    8 */  SIGACTION_TERMINATE,
56  /* SIGKILL   9 */  SIGACTION_TERMINATE,
57  /* SIGBUS   10 */  SIGACTION_TERMINATE,
58  /* SIGSEGV  11 */  SIGACTION_TERMINATE,
59  /* SIGSYS   12 */  SIGACTION_TERMINATE,
60  /* SIGPIPE  13 */  SIGACTION_TERMINATE,
61  /* SIGALRM  14 */  SIGACTION_TERMINATE,
62  /* SIGTERM  15 */  SIGACTION_TERMINATE,
63  /* SIGUSR1  16 */  SIGACTION_TERMINATE,
64  /* SIGUSR2  17 */  SIGACTION_TERMINATE,
65  /* SIGRTMIN 18 */  SIGACTION_TERMINATE,
66  /* SIGRT    19 */  SIGACTION_TERMINATE,
67  /* SIGRT    20 */  SIGACTION_TERMINATE,
68  /* SIGRT    21 */  SIGACTION_TERMINATE,
69  /* SIGRT    22 */  SIGACTION_TERMINATE,
70  /* SIGRT    23 */  SIGACTION_TERMINATE,
71  /* SIGRT    24 */  SIGACTION_TERMINATE,
72  /* SIGRT    25 */  SIGACTION_TERMINATE,
73  /* SIGRT    26 */  SIGACTION_TERMINATE,
74  /* SIGRT    27 */  SIGACTION_TERMINATE,
75  /* SIGRT    28 */  SIGACTION_TERMINATE,
76  /* SIGRT    29 */  SIGACTION_TERMINATE,
77  /* SIGRT    30 */  SIGACTION_TERMINATE,
78  /* SIGRT    31 */  SIGACTION_TERMINATE,
79  /* SIGRTMAX 32 */  SIGACTION_TERMINATE
80};
81
82struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ];
83
84Watchdog_Control _POSIX_signals_Alarm_timer;
85
86Thread_queue_Control _POSIX_signals_Wait_queue;
87
88Chain_Control _POSIX_signals_Inactive_siginfo;
89Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ];
90
91/*PAGE
92 *
93 *  XXX - move these
94 */
95
96#define _States_Is_interruptible_signal( _states ) \
97  ( ((_states) & \
98    (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL)) == \
99      (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL))
100
101/*PAGE
102 *
103 *  _POSIX_signals_Unblock_thread
104 */
105
106/* XXX this routine could probably be cleaned up */
107boolean _POSIX_signals_Unblock_thread( 
108  Thread_Control  *the_thread,
109  int              signo,
110  siginfo_t       *info
111)
112{
113  POSIX_API_Control  *api;
114  sigset_t            mask;
115  siginfo_t          *the_info = NULL;
116
117  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
118
119  mask = signo_to_mask( signo );
120
121  /*
122   *  Is the thread is specifically waiting for a signal?
123   */
124
125  if ( _States_Is_interruptible_signal( the_thread->current_state ) ) {
126
127    if ( (the_thread->Wait.option & mask) || (~api->signals_blocked & mask) ) {
128      the_thread->Wait.return_code = EINTR;
129
130      the_info = (siginfo_t *) the_thread->Wait.return_argument;
131
132      if ( !info ) {
133        the_info->si_signo = signo;
134        the_info->si_code = SI_USER;
135        the_info->si_value.sival_int = 0;
136      } else {
137        *the_info = *info;
138      }
139     
140      _Thread_queue_Extract_with_proxy( the_thread );
141      return TRUE;
142    }
143
144    /*
145     *  This should only be reached via pthread_kill().
146     */
147
148    return FALSE;
149  }
150
151  if ( ~api->signals_blocked & mask ) {
152    the_thread->do_post_task_switch_extension = TRUE;
153
154    if ( the_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL ) {
155      the_thread->Wait.return_code = EINTR;
156      if ( _States_Is_waiting_on_thread_queue(the_thread->current_state) )
157        _Thread_queue_Extract_with_proxy( the_thread );
158      else if ( _States_Is_delaying(the_thread->current_state)){
159        if ( _Watchdog_Is_active( &the_thread->Timer ) )
160          (void) _Watchdog_Remove( &the_thread->Timer );
161        _Thread_Unblock( the_thread );
162      }
163    }
164  }
165  return FALSE;
166
167}
168
169/*PAGE
170 *
171 *  _POSIX_signals_Set_process_signals
172 */
173 
174void _POSIX_signals_Set_process_signals(
175  sigset_t   mask
176)
177{
178  ISR_Level  level;
179 
180  _ISR_Disable( level );
181    if ( !_POSIX_signals_Pending )
182      _Thread_Do_post_task_switch_extension++;
183    _POSIX_signals_Pending |= mask;
184  _ISR_Enable( level );
185}
186
187/*PAGE
188 *
189 *  _POSIX_signals_Clear_process_signals
190 */
191
192void _POSIX_signals_Clear_process_signals(
193  sigset_t   mask
194)
195{
196  ISR_Level  level;
197
198  _ISR_Disable( level );
199    _POSIX_signals_Pending &= ~mask;
200    if ( !_POSIX_signals_Pending )
201      _Thread_Do_post_task_switch_extension--;
202  _ISR_Enable( level );
203}
204
205/*PAGE
206 *
207 *  _POSIX_signals_Clear_signals
208 */
209 
210boolean _POSIX_signals_Clear_signals(
211  POSIX_API_Control  *api,
212  int                 signo,
213  siginfo_t          *info,
214  boolean             is_global,
215  boolean             check_blocked
216)
217{
218  sigset_t                    mask;
219  sigset_t                    signals_blocked;
220  ISR_Level                   level;
221  boolean                     do_callout;
222  POSIX_signals_Siginfo_node *psiginfo;
223 
224  mask = signo_to_mask( signo );
225 
226  do_callout = FALSE;
227 
228  /* set blocked signals based on if checking for them, SIGNAL_ALL_MASK
229   * insures that no signals are blocked and all are checked.
230   */
231
232  if ( check_blocked )
233    signals_blocked = ~api->signals_blocked;
234  else
235    signals_blocked = SIGNAL_ALL_MASK;
236
237  /* XXX this is not right for siginfo type signals yet */
238  /* XXX since they can't be cleared the same way */
239 
240  _ISR_Disable( level );
241    if ( is_global ) {
242       if ( mask & (_POSIX_signals_Pending & signals_blocked) ) {
243         if ( _POSIX_signals_Vectors[ signo ].sa_flags == SA_SIGINFO ) {
244           psiginfo = (POSIX_signals_Siginfo_node *)
245             _Chain_Get_unprotected( &_POSIX_signals_Siginfo[ signo ] );
246           if ( _Chain_Is_empty( &_POSIX_signals_Siginfo[ signo ] ) )
247             _POSIX_signals_Clear_process_signals( mask );
248           if ( psiginfo ) {
249             *info = psiginfo->Info;
250             _Chain_Append_unprotected(
251               &_POSIX_signals_Inactive_siginfo,
252               &psiginfo->Node
253             );
254           } else
255             do_callout = FALSE;
256         } else
257           _POSIX_signals_Clear_process_signals( mask );
258         do_callout = TRUE;
259       }
260    } else {
261      if ( mask & (api->signals_pending & signals_blocked) ) {
262        api->signals_pending &= ~mask;
263        do_callout = TRUE;
264      }
265    }
266  _ISR_Enable( level );
267  return do_callout; 
268}
269
270
271/*PAGE
272 *
273 *  _POSIX_signals_Check_signal
274 */
275
276boolean _POSIX_signals_Check_signal(
277  POSIX_API_Control  *api,
278  int                 signo,
279  boolean             is_global
280)
281{
282  siginfo_t                   siginfo_struct;
283  sigset_t                    saved_signals_blocked;
284
285  if ( ! _POSIX_signals_Clear_signals( api, signo, &siginfo_struct,
286                                       is_global, TRUE ) )
287    return FALSE;
288
289  /*
290   *  Since we made a union of these, only one test is necessary but this is
291   *  safer.
292   */ 
293
294  assert( _POSIX_signals_Vectors[ signo ].sa_handler ||
295          _POSIX_signals_Vectors[ signo ].sa_sigaction );
296 
297  /*
298   *  Just to prevent sending a signal which is currently being ignored.
299   */
300
301  if ( _POSIX_signals_Vectors[ signo ].sa_handler == SIG_IGN )
302    return FALSE;
303
304  /*
305   *  Block the signals requested in sa_mask
306   */
307
308  saved_signals_blocked = api->signals_blocked;
309  api->signals_blocked |= _POSIX_signals_Vectors[ signo ].sa_mask;
310
311  /* Here, the signal handler function executes */
312
313  switch ( _POSIX_signals_Vectors[ signo ].sa_flags ) {
314    case SA_SIGINFO:
315/*
316 *
317 *     assert( is_global );
318 */
319      (*_POSIX_signals_Vectors[ signo ].sa_sigaction)(
320        signo,
321        &siginfo_struct,
322        NULL        /* context is undefined per 1003.1b-1993, p. 66 */
323      );
324      break;
325    default:
326      (*_POSIX_signals_Vectors[ signo ].sa_handler)( signo );
327      break;
328  }
329
330  /*
331   *  Restore the previous set of blocked signals
332   */
333 
334  api->signals_blocked = saved_signals_blocked;
335
336  return TRUE;
337}
338
339void _POSIX_signals_Post_switch_extension(
340  Thread_Control  *the_thread
341)
342{
343  POSIX_API_Control  *api;
344  int                 signo;
345  ISR_Level           level;
346
347  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
348
349  /*
350   *  If we invoke any user code, there is the possibility that
351   *  a new signal has been posted that we should process so we
352   *  restart the loop if a signal handler was invoked.
353   *
354   *  The first thing done is to check there are any signals to be
355   *  processed at all.  No point in doing this loop otherwise.
356   */
357
358restart:
359  _ISR_Disable( level );
360    if ( !(~api->signals_blocked & 
361          (api->signals_pending | _POSIX_signals_Pending)) ) {
362     _ISR_Enable( level );
363     return;
364   }
365  _ISR_Enable( level );
366
367  for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) {
368
369    if ( _POSIX_signals_Check_signal( api, signo, FALSE ) )
370      goto restart;
371
372    if ( _POSIX_signals_Check_signal( api, signo, TRUE ) )
373      goto restart;
374
375  }
376
377/* XXX - add __SIGFIRSTNOTRT or something like that to newlib siginfo.h */
378
379  for ( signo = SIGHUP ; signo <= __SIGLASTNOTRT ; signo++ ) {
380
381    if ( _POSIX_signals_Check_signal( api, signo, FALSE ) )
382      goto restart;
383 
384    if ( _POSIX_signals_Check_signal( api, signo, TRUE ) )
385      goto restart;
386
387  }
388
389}
390
391/*PAGE
392 *
393 *  _POSIX_signals_Alarm_TSR
394 */
395 
396void _POSIX_signals_Alarm_TSR(
397  Objects_Id      id,
398  void           *argument
399)
400{
401  int status;
402
403  status = kill( getpid(), SIGALRM );
404  /* XXX can't print from an ISR, should this be fatal? */
405  assert( !status );
406}
407
408/*PAGE
409 *
410 *  _POSIX_signals_Manager_Initialization
411 */
412
413void _POSIX_signals_Manager_Initialization(
414  int  maximum_queued_signals
415)
416{
417  unsigned32 signo;
418
419  /*
420   *  Insure we have the same number of vectors and default vector entries
421   */
422
423  assert(
424   sizeof(_POSIX_signals_Vectors) == sizeof(_POSIX_signals_Default_vectors)
425  );
426
427  memcpy( 
428    _POSIX_signals_Vectors,
429    _POSIX_signals_Default_vectors,
430    sizeof( _POSIX_signals_Vectors )
431  );
432 
433  /*
434   *  Initialize the set of pending signals for the entire process
435   */
436
437  sigemptyset( &_POSIX_signals_Pending );
438
439  /*
440   *  Initialize the timer used to implement alarm().
441   */
442
443  _Watchdog_Initialize(
444    &_POSIX_signals_Alarm_timer,
445    _POSIX_signals_Alarm_TSR,
446    0,
447    NULL
448  );
449 
450  /*
451   *  Initialize the queue we use to block for signals
452   */
453 
454  _Thread_queue_Initialize(
455    &_POSIX_signals_Wait_queue,
456    OBJECTS_NO_CLASS,
457    THREAD_QUEUE_DISCIPLINE_PRIORITY,
458    STATES_WAITING_FOR_SIGNAL | STATES_INTERRUPTIBLE_BY_SIGNAL,
459    NULL,
460    EAGAIN
461  );
462
463  /* XXX status codes */
464
465  /*
466   *  Allocate the siginfo pools.
467   */
468
469  for ( signo=1 ; signo<= SIGRTMAX ; signo++ )
470    _Chain_Initialize_empty( &_POSIX_signals_Siginfo[ signo ] );
471
472  _Chain_Initialize(
473    &_POSIX_signals_Inactive_siginfo,
474    _Workspace_Allocate_or_fatal_error(
475      maximum_queued_signals * sizeof( POSIX_signals_Siginfo_node )
476    ),
477    maximum_queued_signals,
478    sizeof( POSIX_signals_Siginfo_node )
479  );
480}
Note: See TracBrowser for help on using the repository browser.