source: rtems/c/src/exec/posix/src/psignal.c @ 98ed15e

4.104.114.84.95
Last change on this file since 98ed15e was 98ed15e, checked in by Joel Sherrill <joel.sherrill@…>, on 06/11/96 at 16:01:37

Basic signal functionality appears to work. pthread_kill() can successfully
send signals to the current thread or to another blocked thread. nanosleep()
can be interrupted by a signal and return the time remaining.

Post switch extension added to dispatch posix signal handlers.

  • Property mode set to 100644
File size: 14.3 KB
Line 
1/*
2 *  $Id$
3 */
4
5#include <assert.h>
6#include <errno.h>
7#include <signal.h>
8
9#include <rtems/system.h>
10#include <rtems/score/isr.h>
11#include <rtems/score/thread.h>
12#include <rtems/posix/seterr.h>
13#include <rtems/posix/threadsup.h>
14#include <rtems/posix/pthread.h>
15
16/*
17 *  Currently 32 signals numbered 1-32 are defined
18 */
19
20#define SIGNAL_EMPTY_MASK  0x00000000
21#define SIGNAL_ALL_MASK    0xffffffff
22
23#define signo_to_mask( _sig ) (1 << ((_sig) - 1))
24
25#define is_valid_signo( _sig ) \
26  ((_sig) >= 1 && (_sig) <= 32 )
27
28/*** PROCESS WIDE STUFF ****/
29
30sigset_t  _POSIX_signals_Pending;
31sigset_t  _POSIX_signals_Ignored;
32
33#define _POSIX_signals_Abormal_termination_handler NULL
34#define _POSIX_signals_Stop_handler NULL
35#define _POSIX_signals_Continue_handler NULL
36
37#define SIGACTION_TERMINATE \
38  { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Abormal_termination_handler} }
39#define SIGACTION_IGNORE \
40  { 0, SIGNAL_ALL_MASK, {SIG_IGN} }
41#define SIGACTION_STOP \
42  { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Stop_handler} }
43#define SIGACTION_CONTINUE \
44  { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Continue_handler} }
45
46#define SIG_ARRAY_MAX  (SIGRTMAX + 1)
47struct sigaction _POSIX_signals_Default_vectors[ SIG_ARRAY_MAX ] = {
48  /* NO SIGNAL 0 */  SIGACTION_IGNORE,
49  /* SIGABRT     */  SIGACTION_TERMINATE,
50  /* SIGALRM     */  SIGACTION_TERMINATE,
51  /* SIGFPE      */  SIGACTION_TERMINATE,
52  /* SIGHUP      */  SIGACTION_TERMINATE,
53  /* SIGILL      */  SIGACTION_TERMINATE,
54  /* SIGINT      */  SIGACTION_TERMINATE,
55  /* SIGKILL     */  SIGACTION_TERMINATE,
56  /* SIGPIPE     */  SIGACTION_TERMINATE,
57  /* SIGQUIT     */  SIGACTION_TERMINATE,
58  /* SIGSEGV     */  SIGACTION_TERMINATE,
59  /* SIGTERM     */  SIGACTION_TERMINATE,
60  /* SIGUSR1     */  SIGACTION_TERMINATE,
61  /* SIGUSR2     */  SIGACTION_TERMINATE,
62  /* SIGCHLD     */  SIGACTION_IGNORE,
63  /* SIGCONT     */  SIGACTION_CONTINUE,
64  /* SIGSTOP     */  SIGACTION_STOP,
65  /* SIGTSTP     */  SIGACTION_STOP,
66  /* SIGTTIN     */  SIGACTION_STOP,
67  /* SIGTTOU     */  SIGACTION_STOP,
68  /* SIGBUS      */  SIGACTION_TERMINATE,
69  /* SIGRTMIN 21 */  SIGACTION_IGNORE,
70  /* SIGRT    22 */  SIGACTION_IGNORE,
71  /* SIGRT    23 */  SIGACTION_IGNORE,
72  /* SIGRT    24 */  SIGACTION_IGNORE,
73  /* SIGRT    25 */  SIGACTION_IGNORE,
74  /* SIGRT    26 */  SIGACTION_IGNORE,
75  /* SIGRT    27 */  SIGACTION_IGNORE,
76  /* SIGRT    28 */  SIGACTION_IGNORE,
77  /* SIGRT    29 */  SIGACTION_IGNORE,
78  /* SIGRT    30 */  SIGACTION_IGNORE,
79  /* SIGRT    31 */  SIGACTION_IGNORE,
80  /* SIGRTMAX 32 */  SIGACTION_IGNORE
81};
82
83struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ];
84
85Watchdog_Control _POSIX_signals_Alarm_timer;
86
87typedef struct {
88  Chain_Node  Node;
89  siginfo_t   Info;
90}  POSIX_signals_Siginfo_node;
91
92Chain_Control _POSIX_signals_Inactive_siginfo;
93Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ];
94
95/*PAGE
96 *
97 *  XXX
98 */
99
100boolean _POSIX_signals_Check_signal(
101  POSIX_API_Control  *api,
102  int                 signo,
103  boolean             is_global
104)
105{
106  sigset_t            mask;
107  ISR_Level           level;
108  boolean             do_callout;
109  siginfo_t          *siginfo = NULL;  /* really needs to be set below */
110  siginfo_t           siginfo_struct;
111
112  mask = signo_to_mask( signo );
113
114  do_callout = FALSE;
115
116  _ISR_Disable( level );
117    if ( is_global ) {
118       ;
119       /* XXX check right place for thread versus global */
120    } else {
121      if ( mask & (api->signals_pending & ~api->signals_blocked ) ) {
122        api->signals_pending &= ~mask;
123        do_callout = TRUE;
124      }
125    }
126  _ISR_Enable( level );
127
128  if ( !do_callout )
129    return FALSE;
130
131  /*
132   *  Since we made a union of these, only one test is necessary but this is
133   *  safer.
134   */
135
136  assert( _POSIX_signals_Vectors[ signo ].sa_handler ||
137          _POSIX_signals_Vectors[ signo ].sa_sigaction );
138 
139  switch ( _POSIX_signals_Vectors[ signo ].sa_flags ) {
140    case SA_SIGINFO:
141      assert( 0 );   /* XXX we haven't completely implemented this yet */
142      if ( !is_global ) {
143        siginfo = &siginfo_struct;
144        siginfo->si_signo = signo;
145        siginfo->si_code = SI_USER;
146        siginfo->si_value.sival_int = 0;
147      }
148      (*_POSIX_signals_Vectors[ signo ].sa_sigaction)(
149        signo,
150        siginfo,
151        NULL        /* context is undefined per 1003.1b-1993, p. 66 */
152      );
153      break;
154    default:
155      (*_POSIX_signals_Vectors[ signo ].sa_handler)( signo );
156      break;
157  }
158  return TRUE;
159}
160
161void _POSIX_signals_Post_switch_extension(
162  Thread_Control  *the_thread
163)
164{
165  POSIX_API_Control  *api;
166  int                 signo;
167
168  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
169
170  /*
171   *  If we invoke any user code, there is the possibility that
172   *  a new signal has been posted that we should process.
173   */
174
175/* XXX somewhere we need to see if all pending signals are gone and clear */
176/* XXX do_post_switch_extension */
177
178restart:
179  for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) {
180
181    if ( _POSIX_signals_Check_signal( api, signo, FALSE ) )
182      goto restart;
183
184    if ( _POSIX_signals_Check_signal( api, signo, TRUE ) )
185      goto restart;
186
187  }
188
189  for ( signo = SIGABRT ; signo <= SIGBUS ; signo++ ) {
190
191    if ( _POSIX_signals_Check_signal( api, signo, FALSE ) )
192      goto restart;
193 
194    if ( _POSIX_signals_Check_signal( api, signo, TRUE ) )
195      goto restart;
196
197  }
198
199}
200
201/*PAGE
202 *
203 *  _POSIX_signals_Alarm_TSR
204 */
205 
206void _POSIX_signals_Alarm_TSR(
207  Objects_Id      id,
208  void           *argument
209)
210{
211  kill( getpid(), SIGALRM );
212}
213
214/*PAGE
215 *
216 *  _POSIX_signals_Manager_Initialization
217 */
218
219void _POSIX_signals_Manager_Initialization( void )
220{
221  unsigned32 signo;
222
223  /*
224   *  Insure we have the same number of vectors and default vector entries
225   */
226
227  assert(
228   sizeof(_POSIX_signals_Vectors) == sizeof(_POSIX_signals_Default_vectors)
229  );
230
231  memcpy(
232    _POSIX_signals_Vectors,
233    _POSIX_signals_Default_vectors,
234    sizeof( _POSIX_signals_Vectors )
235  );
236 
237  /*
238   *  Initialize the set of pending signals for the entire process
239   */
240
241  sigemptyset( &_POSIX_signals_Pending );
242
243  /*
244   *  Calculate the mask for the set of signals which are being ignored.
245   */
246
247  sigemptyset( &_POSIX_signals_Ignored );
248 
249  for ( signo=1 ; signo<= SIGRTMAX ; signo++ )
250    if ( _POSIX_signals_Default_vectors[ signo ].sa_handler == SIG_IGN )
251      sigaddset( &_POSIX_signals_Ignored, signo );
252   
253  /*
254   *  Initialize the timer used to implement alarm().
255   */
256
257  _Watchdog_Initialize(
258    &_POSIX_signals_Alarm_timer,
259    _POSIX_signals_Alarm_TSR,
260    0,
261    NULL
262  );
263 
264  /*
265   *  XXX Allocate the siginfo pools.
266   */
267
268  for ( signo=1 ; signo<= SIGRTMAX ; signo++ )
269    _Chain_Initialize_empty( &_POSIX_signals_Siginfo[ signo ] );
270
271  /* XXX especially the inactive pool */
272}
273
274/*
275 *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
276 */
277
278int sigemptyset(
279  sigset_t   *set
280)
281{
282  if ( !set )
283    set_errno_and_return_minus_one( EFAULT );
284
285  *set = 0;
286  return 0;
287}
288
289/*
290 *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
291 */
292
293int sigfillset(
294  sigset_t   *set
295)
296{
297  if ( !set )
298    set_errno_and_return_minus_one( EFAULT );
299
300  *set = SIGNAL_ALL_MASK;
301  return 0;
302}
303
304/*
305 *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
306 */
307
308int sigaddset(
309  sigset_t   *set,
310  int         signo
311)
312{
313  if ( !set )
314    set_errno_and_return_minus_one( EFAULT );
315
316  if ( !is_valid_signo(signo) )
317    set_errno_and_return_minus_one( EINVAL );
318
319  *set |= signo_to_mask(signo);
320  return 0;
321}
322
323/*
324 *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
325 */
326
327int sigdelset(
328  sigset_t   *set,
329  int         signo
330)
331{
332  if ( !set )
333    set_errno_and_return_minus_one( EFAULT );
334 
335  if ( !is_valid_signo(signo) )
336    set_errno_and_return_minus_one( EINVAL );
337 
338  *set &= ~signo_to_mask(signo);
339  return 0;
340}
341
342/*
343 *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
344 */
345
346int sigismember(
347  const sigset_t   *set,
348  int               signo
349)
350{
351  if ( !set )
352    set_errno_and_return_minus_one( EFAULT );
353 
354  if ( !is_valid_signo(signo) )
355    set_errno_and_return_minus_one( EINVAL );
356 
357  if ( *set & signo_to_mask(signo) )
358    return 1;
359
360  return 0;
361}
362
363/*
364 *  3.3.4 Examine and Change Signal Action, P1003.1b-1993, p. 70
365 */
366
367int sigaction(
368  int                     sig,
369  const struct sigaction *act,
370  struct sigaction       *oact
371)
372{
373  if ( !act )
374    set_errno_and_return_minus_one( EFAULT );
375
376  if ( !is_valid_signo(sig) )
377    set_errno_and_return_minus_one( EINVAL );
378 
379  if ( oact )
380    *oact = _POSIX_signals_Vectors[ sig ];
381
382  /* XXX need to interpret some stuff here */
383  /* XXX some signals cannot be ignored */
384
385  _POSIX_signals_Vectors[ sig ] = *act;
386
387  return 0;
388}
389
390/*
391 *  3.3.5 Examine and Change Blocked Signals, P1003.1b-1993, p. 73
392 *
393 *  NOTE: P1003.1c/D10, p. 37 adds pthread_sigmask().
394 *
395 */
396
397int sigprocmask(
398  int               how,
399  const sigset_t   *set,
400  sigset_t         *oset
401)
402{
403  /*
404   *  P1003.1c/Draft 10, p. 38 maps sigprocmask to pthread_sigmask.
405   */
406
407  return pthread_sigmask( how, set, oset );
408}
409
410/*
411 *  3.3.5 Examine and Change Blocked Signals, P1003.1b-1993, p. 73
412 *
413 *  NOTE: P1003.1c/D10, p. 37 adds pthread_sigmask().
414 */
415
416int pthread_sigmask(
417  int               how,
418  const sigset_t   *set,
419  sigset_t         *oset
420)
421{
422  POSIX_API_Control  *api;
423  boolean             evaluate_signals;
424
425/* XXX some signals can not be ignored */
426
427  if ( !set && !oset )
428    set_errno_and_return_minus_one( EFAULT );
429
430  api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
431
432  if ( oset )
433    *oset = api->signals_blocked;
434 
435  if ( !set )
436    set_errno_and_return_minus_one( EFAULT );
437
438  evaluate_signals = TRUE;
439
440  switch ( how ) {
441    case SIG_BLOCK:
442      api->signals_blocked |= *set;
443      evaluate_signals = FALSE;
444      break;
445    case SIG_UNBLOCK:
446      api->signals_blocked &= ~*set;
447      break;
448    case SIG_SETMASK:
449      api->signals_blocked = *set;
450      break;
451    default:
452      set_errno_and_return_minus_one( EINVAL );
453  }
454
455  /* XXX are there critical section problems here? */
456
457  /* XXX evaluate the new set */
458
459  if ( evaluate_signals == TRUE ) {
460     if ( ~api->signals_blocked &
461          (api->signals_pending | _POSIX_signals_Pending) ) {
462       api->signals_global_pending &= _POSIX_signals_Pending;
463       _Thread_Executing->do_post_task_switch_extension = TRUE;
464       _Thread_Dispatch();
465     }
466  }
467
468  return 0;
469}
470
471/*
472 *  3.3.6 Examine Pending Signals, P1003.1b-1993, p. 75
473 */
474
475int sigpending(
476  sigset_t  *set
477)
478{
479  POSIX_API_Control  *api;
480 
481  if ( !set )
482    set_errno_and_return_minus_one( EFAULT );
483 
484  api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
485 
486  *set = api->signals_pending | _POSIX_signals_Pending;
487 
488  return 0;
489}
490
491/*
492 *  3.3.7 Wait for a Signal, P1003.1b-1993, p. 75
493 */
494
495int sigsuspend(
496  const sigset_t  *sigmask
497)
498{
499  return POSIX_NOT_IMPLEMENTED();
500}
501
502/*
503 *  3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76
504 *
505 *  NOTE: P1003.1c/D10, p. 39 adds sigwait().
506 */
507
508int sigwaitinfo(
509  const sigset_t  *set,
510  siginfo_t       *info
511)
512{
513  return POSIX_NOT_IMPLEMENTED();
514}
515
516/*
517 *  3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76
518 *
519 *  NOTE: P1003.1c/D10, p. 39 adds sigwait().
520 */
521
522int sigtimedwait(
523  const sigset_t         *set,
524  siginfo_t              *info,
525  const struct timespec  *timeout
526)
527{
528  return POSIX_NOT_IMPLEMENTED();
529}
530
531/*
532 *  3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76
533 *
534 *  NOTE: P1003.1c/D10, p. 39 adds sigwait().
535 */
536
537int sigwait(
538  const sigset_t  *set,
539  int             *sig
540)
541{
542  return POSIX_NOT_IMPLEMENTED();
543}
544
545/*
546 *  3.3.9 Queue a Signal to a Process, P1003.1b-1993, p. 78
547 */
548
549int sigqueue(
550  pid_t               pid,
551  int                 signo,
552  const union sigval  value
553)
554{
555  return POSIX_NOT_IMPLEMENTED();
556}
557
558/*
559 *  3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68
560 *
561 *  NOTE: Behavior of kill() depends on _POSIX_SAVED_IDS.
562 */
563
564int kill(
565  pid_t pid,
566  int   sig
567)
568{
569  /*
570   *  Only supported for the "calling process" (i.e. this node).
571   */
572 
573  if( pid != getpid() );
574    set_errno_and_return_minus_one( ESRCH );
575
576  if ( !sig || _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN )
577    return 0;
578
579  /* SIGABRT comes from abort via assert and must work no matter what */
580  if ( sig == SIGABRT ) {
581    exit( 1 );
582  }
583  return POSIX_NOT_IMPLEMENTED();
584}
585
586/*
587 *  3.3.10 Send a Signal to a Thread, P1003.1c/D10, p. 43
588 */
589
590int pthread_kill(
591  pthread_t   thread,
592  int         sig
593)
594{
595  POSIX_API_Control  *api;
596  Thread_Control     *the_thread;
597  Objects_Locations  location;
598
599  if ( sig && !is_valid_signo(sig) )
600    set_errno_and_return_minus_one( EINVAL );
601
602  if ( _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN )
603    return 0;
604
605  the_thread = _POSIX_Threads_Get( thread, &location );
606  switch ( location ) {
607    case OBJECTS_ERROR:
608    case OBJECTS_REMOTE:
609      return ESRCH;
610    case OBJECTS_LOCAL:
611      /*
612       *  If sig == 0 then just validate arguments
613       */
614
615      api = the_thread->API_Extensions[ THREAD_API_POSIX ];
616
617      if ( sig ) {
618
619        /* XXX critical section */
620
621        api->signals_pending |= signo_to_mask( sig );
622
623        if ( api->signals_pending & ~api->signals_blocked ) {
624          the_thread->do_post_task_switch_extension = TRUE;
625
626 
627          /* XXX may have to unblock the task -- this is a kludge -- fix it */
628          if ( the_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL ) {
629            the_thread->Wait.return_code = EINTR;
630            if ( _States_Is_waiting_on_thread_queue(the_thread->current_state) )
631              _Thread_queue_Extract_with_proxy( the_thread );
632            else if ( _States_Is_delaying(the_thread->current_state)){
633              if ( _Watchdog_Is_active( &the_thread->Timer ) )
634                (void) _Watchdog_Remove( &the_thread->Timer );
635              _Thread_Unblock( the_thread );
636            }
637        }
638      }
639    }
640    _Thread_Enable_dispatch();
641    return 0;
642  }
643
644  return POSIX_BOTTOM_REACHED();
645}
646
647/*
648 *  3.4.1 Schedule Alarm, P1003.1b-1993, p. 79
649 */
650
651Watchdog_Control _POSIX_signals_Alarm_timer;
652
653unsigned int alarm(
654  unsigned int seconds
655)
656{
657  unsigned int      remaining = 0;
658  Watchdog_Control *the_timer;
659
660  the_timer = &_POSIX_signals_Alarm_timer;
661
662  switch ( _Watchdog_Remove( the_timer ) ) {
663    case WATCHDOG_INACTIVE:
664    case WATCHDOG_BEING_INSERTED:
665      break;
666 
667    case WATCHDOG_ACTIVE:
668    case WATCHDOG_REMOVE_IT:
669      remaining = the_timer->initial -
670                  (the_timer->stop_time - the_timer->start_time);
671      break;
672  }
673
674  _Watchdog_Insert_seconds( the_timer, seconds );
675
676  return remaining;
677}
678
679/*
680 *  3.4.2 Suspend Process Execution, P1003.1b-1993, p. 81
681 */
682
683int pause( void )
684{
685  return POSIX_NOT_IMPLEMENTED();
686}
Note: See TracBrowser for help on using the repository browser.