source: rtems/c/src/exec/posix/src/psignal.c @ dae18b5

4.104.114.84.95
Last change on this file since dae18b5 was dae18b5, checked in by Joel Sherrill <joel.sherrill@…>, on 02/10/99 at 17:22:16

POSIX timer support.

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