source: rtems/cpukit/posix/src/psignal.c @ fdec30b

4.104.114.84.95
Last change on this file since fdec30b was fdec30b, checked in by Joel Sherrill <joel.sherrill@…>, on 06/10/96 at 20:47:23

first attempt at the routine which vectors signals.

  • Property mode set to 100644
File size: 13.6 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  switch ( _POSIX_signals_Vectors[ signo ].sa_flags ) {
132    case SA_SIGINFO:
133      assert( 0 );   /* XXX we haven't completely implemented this yet */
134      if ( !is_global ) {
135        siginfo = &siginfo_struct;
136        siginfo->si_signo = signo;
137        siginfo->si_code = SI_USER;
138        siginfo->si_value.sival_int = 0;
139      }
140      (*_POSIX_signals_Vectors[ signo ].sa_sigaction)(
141        signo,
142        siginfo,
143        NULL        /* context is undefined per 1003.1b-1993, p. 66 */
144      );
145      break;
146    default:
147      (*_POSIX_signals_Vectors[ signo ].sa_handler)( signo );
148      break;
149  }
150  return TRUE;
151}
152
153void _POSIX_signals_Run_Them(
154  Thread_Control  *the_thread
155)
156{
157  POSIX_API_Control  *api;
158  int                 signo;
159
160  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
161
162  /*
163   *  If we invoke any user code, there is the possibility that
164   *  a new signal has been posted that we should process.
165   */
166
167/* XXX somewhere we need to see if all pending signals are gone and clear */
168/* XXX do_post_switch_extension */
169
170restart:
171  for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) {
172
173    if ( _POSIX_signals_Check_signal( api, signo, FALSE ) )
174      goto restart;
175
176    if ( _POSIX_signals_Check_signal( api, signo, TRUE ) )
177      goto restart;
178
179  }
180
181  for ( signo = SIGABRT ; signo <= SIGBUS ; signo++ ) {
182
183    if ( _POSIX_signals_Check_signal( api, signo, FALSE ) )
184      goto restart;
185 
186    if ( _POSIX_signals_Check_signal( api, signo, TRUE ) )
187      goto restart;
188
189  }
190
191}
192
193/*PAGE
194 *
195 *  _POSIX_signals_Alarm_TSR
196 */
197 
198void _POSIX_signals_Alarm_TSR(
199  Objects_Id      id,
200  void           *argument
201)
202{
203  kill( getpid(), SIGALRM );
204}
205
206/*PAGE
207 *
208 *  _POSIX_signals_Manager_Initialization
209 */
210
211void _POSIX_signals_Manager_Initialization( void )
212{
213  unsigned32 signo;
214
215  /*
216   *  Insure we have the same number of vectors and default vector entries
217   */
218
219  assert(
220   sizeof(_POSIX_signals_Vectors) == sizeof(_POSIX_signals_Default_vectors)
221  );
222
223  memcpy(
224    _POSIX_signals_Vectors,
225    _POSIX_signals_Default_vectors,
226    sizeof( _POSIX_signals_Vectors )
227  );
228 
229  /*
230   *  Initialize the set of pending signals for the entire process
231   */
232
233  sigemptyset( &_POSIX_signals_Pending );
234
235  /*
236   *  Calculate the mask for the set of signals which are being ignored.
237   */
238
239  sigemptyset( &_POSIX_signals_Ignored );
240 
241  for ( signo=1 ; signo<= SIGRTMAX ; signo++ )
242    if ( _POSIX_signals_Default_vectors[ signo ].sa_handler == SIG_IGN )
243      sigaddset( &_POSIX_signals_Ignored, signo );
244   
245  /*
246   *  Initialize the timer used to implement alarm().
247   */
248
249  _Watchdog_Initialize(
250    &_POSIX_signals_Alarm_timer,
251    _POSIX_signals_Alarm_TSR,
252    0,
253    NULL
254  );
255 
256  /*
257   *  XXX Allocate the siginfo pools.
258   */
259
260  for ( signo=1 ; signo<= SIGRTMAX ; signo++ )
261    _Chain_Initialize_empty( &_POSIX_signals_Siginfo[ signo ] );
262
263  /* XXX especially the inactive pool */
264}
265
266/*
267 *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
268 */
269
270int sigemptyset(
271  sigset_t   *set
272)
273{
274  if ( !set )
275    set_errno_and_return_minus_one( EFAULT );
276
277  *set = 0;
278  return 0;
279}
280
281/*
282 *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
283 */
284
285int sigfillset(
286  sigset_t   *set
287)
288{
289  if ( !set )
290    set_errno_and_return_minus_one( EFAULT );
291
292  *set = SIGNAL_ALL_MASK;
293  return 0;
294}
295
296/*
297 *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
298 */
299
300int sigaddset(
301  sigset_t   *set,
302  int         signo
303)
304{
305  if ( !set )
306    set_errno_and_return_minus_one( EFAULT );
307
308  if ( !is_valid_signo(signo) )
309    set_errno_and_return_minus_one( EINVAL );
310
311  *set |= signo_to_mask(signo);
312  return 0;
313}
314
315/*
316 *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
317 */
318
319int sigdelset(
320  sigset_t   *set,
321  int         signo
322)
323{
324  if ( !set )
325    set_errno_and_return_minus_one( EFAULT );
326 
327  if ( !is_valid_signo(signo) )
328    set_errno_and_return_minus_one( EINVAL );
329 
330  *set &= ~signo_to_mask(signo);
331  return 0;
332}
333
334/*
335 *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
336 */
337
338int sigismember(
339  const sigset_t   *set,
340  int               signo
341)
342{
343  if ( !set )
344    set_errno_and_return_minus_one( EFAULT );
345 
346  if ( !is_valid_signo(signo) )
347    set_errno_and_return_minus_one( EINVAL );
348 
349  if ( *set & signo_to_mask(signo) )
350    return 1;
351
352  return 0;
353}
354
355/*
356 *  3.3.4 Examine and Change Signal Action, P1003.1b-1993, p. 70
357 */
358
359int sigaction(
360  int                     sig,
361  const struct sigaction *act,
362  struct sigaction       *oact
363)
364{
365  if ( !act )
366    set_errno_and_return_minus_one( EFAULT );
367
368  if ( !is_valid_signo(sig) )
369    set_errno_and_return_minus_one( EINVAL );
370 
371  if ( oact )
372    *oact = _POSIX_signals_Vectors[ sig ];
373
374  /* XXX need to interpret some stuff here */
375  /* XXX some signals cannot be ignored */
376
377  _POSIX_signals_Vectors[ sig ] = *act;
378
379  return POSIX_NOT_IMPLEMENTED();
380}
381
382/*
383 *  3.3.5 Examine and Change Blocked Signals, P1003.1b-1993, p. 73
384 *
385 *  NOTE: P1003.1c/D10, p. 37 adds pthread_sigmask().
386 *
387 */
388
389int sigprocmask(
390  int               how,
391  const sigset_t   *set,
392  sigset_t         *oset
393)
394{
395  /*
396   *  P1003.1c/Draft 10, p. 38 maps sigprocmask to pthread_sigmask.
397   */
398
399  return pthread_sigmask( how, set, oset );
400}
401
402/*
403 *  3.3.5 Examine and Change Blocked Signals, P1003.1b-1993, p. 73
404 *
405 *  NOTE: P1003.1c/D10, p. 37 adds pthread_sigmask().
406 */
407
408int pthread_sigmask(
409  int               how,
410  const sigset_t   *set,
411  sigset_t         *oset
412)
413{
414  POSIX_API_Control  *api;
415  boolean             evaluate_signals;
416
417/* XXX some signals can not be ignored */
418
419  if ( !set && !oset )
420    set_errno_and_return_minus_one( EFAULT );
421
422  api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
423
424  if ( oset )
425    *oset = api->signals_blocked;
426 
427  if ( !set )
428    set_errno_and_return_minus_one( EFAULT );
429
430  evaluate_signals = TRUE;
431
432  switch ( how ) {
433    case SIG_BLOCK:
434      api->signals_blocked |= *set;
435      evaluate_signals = FALSE;
436      break;
437    case SIG_UNBLOCK:
438      api->signals_blocked &= ~*set;
439      break;
440    case SIG_SETMASK:
441      api->signals_blocked = *set;
442      break;
443    default:
444      set_errno_and_return_minus_one( EINVAL );
445  }
446
447  /* XXX are there critical section problems here? */
448
449  /* XXX evaluate the new set */
450
451  if ( evaluate_signals == TRUE ) {
452     if ( ~api->signals_blocked &
453          (api->signals_pending | _POSIX_signals_Pending) ) {
454       api->signals_global_pending &= _POSIX_signals_Pending;
455       _Thread_Executing->do_post_task_switch_extension = TRUE;
456       _Thread_Dispatch();
457     }
458  }
459
460  return 0;
461}
462
463/*
464 *  3.3.6 Examine Pending Signals, P1003.1b-1993, p. 75
465 */
466
467int sigpending(
468  sigset_t  *set
469)
470{
471  POSIX_API_Control  *api;
472 
473  if ( !set )
474    set_errno_and_return_minus_one( EFAULT );
475 
476  api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
477 
478  *set = api->signals_pending | _POSIX_signals_Pending;
479 
480  return 0;
481}
482
483/*
484 *  3.3.7 Wait for a Signal, P1003.1b-1993, p. 75
485 */
486
487int sigsuspend(
488  const sigset_t  *sigmask
489)
490{
491  return POSIX_NOT_IMPLEMENTED();
492}
493
494/*
495 *  3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76
496 *
497 *  NOTE: P1003.1c/D10, p. 39 adds sigwait().
498 */
499
500int sigwaitinfo(
501  const sigset_t  *set,
502  siginfo_t       *info
503)
504{
505  return POSIX_NOT_IMPLEMENTED();
506}
507
508/*
509 *  3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76
510 *
511 *  NOTE: P1003.1c/D10, p. 39 adds sigwait().
512 */
513
514int sigtimedwait(
515  const sigset_t         *set,
516  siginfo_t              *info,
517  const struct timespec  *timeout
518)
519{
520  return POSIX_NOT_IMPLEMENTED();
521}
522
523/*
524 *  3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76
525 *
526 *  NOTE: P1003.1c/D10, p. 39 adds sigwait().
527 */
528
529int sigwait(
530  const sigset_t  *set,
531  int             *sig
532)
533{
534  return POSIX_NOT_IMPLEMENTED();
535}
536
537/*
538 *  3.3.9 Queue a Signal to a Process, P1003.1b-1993, p. 78
539 */
540
541int sigqueue(
542  pid_t               pid,
543  int                 signo,
544  const union sigval  value
545)
546{
547  return POSIX_NOT_IMPLEMENTED();
548}
549
550/*
551 *  3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68
552 *
553 *  NOTE: Behavior of kill() depends on _POSIX_SAVED_IDS.
554 */
555
556int kill(
557  pid_t pid,
558  int   sig
559)
560{
561  /*
562   *  Only supported for the "calling process" (i.e. this node).
563   */
564 
565  if( pid != getpid() );
566    set_errno_and_return_minus_one( ESRCH );
567
568  if ( !sig || _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN )
569    return 0;
570
571  /* SIGABRT comes from abort via assert and must work no matter what */
572  if ( sig == SIGABRT ) {
573    exit( 1 );
574  }
575  return POSIX_NOT_IMPLEMENTED();
576}
577
578/*
579 *  3.3.10 Send a Signal to a Thread, P1003.1c/D10, p. 43
580 */
581
582int pthread_kill(
583  pthread_t   thread,
584  int         sig
585)
586{
587  POSIX_API_Control  *api;
588  Thread_Control     *the_thread;
589  Objects_Locations  location;
590
591  if ( sig && !is_valid_signo(sig) )
592    set_errno_and_return_minus_one( EINVAL );
593
594  if ( _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN )
595    return 0;
596
597  the_thread = _POSIX_Threads_Get( thread, &location );
598  switch ( location ) {
599    case OBJECTS_ERROR:
600    case OBJECTS_REMOTE:
601      return ESRCH;
602    case OBJECTS_LOCAL:
603      /*
604       *  If sig == 0 then just validate arguments
605       */
606
607      api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
608
609      if ( sig ) {
610
611        /* XXX critical section */
612
613        api->signals_pending |= signo_to_mask( sig );
614
615        if ( api->signals_pending & ~api->signals_blocked ) {
616          the_thread->do_post_task_switch_extension = TRUE;
617
618          /* XXX may have to unblock the task */
619
620        }
621      }
622      _Thread_Enable_dispatch();
623      return 0;
624  }
625
626  return POSIX_BOTTOM_REACHED();
627}
628
629/*
630 *  3.4.1 Schedule Alarm, P1003.1b-1993, p. 79
631 */
632
633Watchdog_Control _POSIX_signals_Alarm_timer;
634
635unsigned int alarm(
636  unsigned int seconds
637)
638{
639  unsigned int      remaining = 0;
640  Watchdog_Control *the_timer;
641
642  the_timer = &_POSIX_signals_Alarm_timer;
643
644  switch ( _Watchdog_Remove( the_timer ) ) {
645    case WATCHDOG_INACTIVE:
646    case WATCHDOG_BEING_INSERTED:
647      break;
648 
649    case WATCHDOG_ACTIVE:
650    case WATCHDOG_REMOVE_IT:
651      remaining = the_timer->initial -
652                  (the_timer->stop_time - the_timer->start_time);
653      break;
654  }
655
656  _Watchdog_Insert_seconds( the_timer, seconds );
657
658  return remaining;
659}
660
661/*
662 *  3.4.2 Suspend Process Execution, P1003.1b-1993, p. 81
663 */
664
665int pause( void )
666{
667  return POSIX_NOT_IMPLEMENTED();
668}
Note: See TracBrowser for help on using the repository browser.