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

4.104.114.84.95
Last change on this file since ea1a5bef was ea1a5bef, checked in by Joel Sherrill <joel.sherrill@…>, on 06/11/96 at 22:52:42

first attempt at adding algorithm to select the thread which will
receive a process-directed signal.

  • Property mode set to 100644
File size: 21.2 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/posix/seterr.h>
14#include <rtems/posix/threadsup.h>
15#include <rtems/posix/pthread.h>
16
17/*
18 *  Currently 32 signals numbered 1-32 are defined
19 */
20
21#define SIGNAL_EMPTY_MASK  0x00000000
22#define SIGNAL_ALL_MASK    0xffffffff
23
24#define signo_to_mask( _sig ) (1 << ((_sig) - 1))
25
26#define is_valid_signo( _sig ) \
27  ((_sig) >= 1 && (_sig) <= 32 )
28
29/*** PROCESS WIDE STUFF ****/
30
31sigset_t  _POSIX_signals_Pending;
32
33void _POSIX_signals_Abormal_termination_handler( int signo )
34{
35  exit( 1 );
36}
37
38#define _POSIX_signals_Stop_handler NULL
39#define _POSIX_signals_Continue_handler NULL
40
41#define SIGACTION_TERMINATE \
42  { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Abormal_termination_handler} }
43#define SIGACTION_IGNORE \
44  { 0, SIGNAL_ALL_MASK, {SIG_IGN} }
45#define SIGACTION_STOP \
46  { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Stop_handler} }
47#define SIGACTION_CONTINUE \
48  { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Continue_handler} }
49
50#define SIG_ARRAY_MAX  (SIGRTMAX + 1)
51struct sigaction _POSIX_signals_Default_vectors[ SIG_ARRAY_MAX ] = {
52  /* NO SIGNAL 0 */  SIGACTION_IGNORE,
53  /* SIGABRT     */  SIGACTION_TERMINATE,
54  /* SIGALRM     */  SIGACTION_TERMINATE,
55  /* SIGFPE      */  SIGACTION_TERMINATE,
56  /* SIGHUP      */  SIGACTION_TERMINATE,
57  /* SIGILL      */  SIGACTION_TERMINATE,
58  /* SIGINT      */  SIGACTION_TERMINATE,
59  /* SIGKILL     */  SIGACTION_TERMINATE,
60  /* SIGPIPE     */  SIGACTION_TERMINATE,
61  /* SIGQUIT     */  SIGACTION_TERMINATE,
62  /* SIGSEGV     */  SIGACTION_TERMINATE,
63  /* SIGTERM     */  SIGACTION_TERMINATE,
64  /* SIGUSR1     */  SIGACTION_TERMINATE,
65  /* SIGUSR2     */  SIGACTION_TERMINATE,
66  /* SIGRTMIN 14 */  SIGACTION_IGNORE,
67  /* SIGRT    15 */  SIGACTION_IGNORE,
68  /* SIGRT    16 */  SIGACTION_IGNORE,
69  /* SIGRT    17 */  SIGACTION_IGNORE,
70  /* SIGRT    18 */  SIGACTION_IGNORE,
71  /* SIGRT    19 */  SIGACTION_IGNORE,
72  /* SIGRT    20 */  SIGACTION_IGNORE,
73  /* SIGRT    21 */  SIGACTION_IGNORE,
74  /* SIGRT    22 */  SIGACTION_IGNORE,
75  /* SIGRT    23 */  SIGACTION_IGNORE,
76  /* SIGRT    24 */  SIGACTION_IGNORE,
77  /* SIGRT    25 */  SIGACTION_IGNORE,
78  /* SIGRT    26 */  SIGACTION_IGNORE,
79  /* SIGRT    27 */  SIGACTION_IGNORE,
80  /* SIGRT    28 */  SIGACTION_IGNORE,
81  /* SIGRT    29 */  SIGACTION_IGNORE,
82  /* SIGRT    30 */  SIGACTION_IGNORE,
83  /* SIGRT    31 */  SIGACTION_IGNORE,
84  /* SIGRTMAX 32 */  SIGACTION_IGNORE
85};
86
87struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ];
88
89Watchdog_Control _POSIX_signals_Alarm_timer;
90
91typedef struct {
92  Chain_Node  Node;
93  siginfo_t   Info;
94}  POSIX_signals_Siginfo_node;
95
96Chain_Control _POSIX_signals_Inactive_siginfo;
97Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ];
98
99/*PAGE
100 *
101 *  XXX
102 */
103
104boolean _POSIX_signals_Check_signal(
105  POSIX_API_Control  *api,
106  int                 signo,
107  boolean             is_global
108)
109{
110  sigset_t            mask;
111  ISR_Level           level;
112  boolean             do_callout;
113  siginfo_t          *siginfo = NULL;  /* really needs to be set below */
114  siginfo_t           siginfo_struct;
115  sigset_t            saved_signals_blocked;
116
117  mask = signo_to_mask( signo );
118
119  do_callout = FALSE;
120
121  /* XXX this is not right for siginfo type signals yet */
122  /* XXX since they can't be cleared the same way */
123  _ISR_Disable( level );
124    if ( is_global ) {
125       if ( mask & (_POSIX_signals_Pending & ~api->signals_blocked ) ) {
126         _POSIX_signals_Pending &= ~mask;
127         do_callout = TRUE;
128       }
129    } else {
130      if ( mask & (api->signals_pending & ~api->signals_blocked ) ) {
131        api->signals_pending &= ~mask;
132        do_callout = TRUE;
133      }
134    }
135  _ISR_Enable( level );
136
137  if ( !do_callout )
138    return FALSE;
139
140  /*
141   *  Since we made a union of these, only one test is necessary but this is
142   *  safer.
143   */
144
145  assert( _POSIX_signals_Vectors[ signo ].sa_handler ||
146          _POSIX_signals_Vectors[ signo ].sa_sigaction );
147 
148  /*
149   *  Just to prevent sending a signal which is currently being ignored.
150   */
151
152  if ( _POSIX_signals_Vectors[ signo ].sa_handler == SIG_IGN )
153    return FALSE;
154
155  /*
156   *  Block the signals requested in sa_mask
157   */
158
159  saved_signals_blocked = api->signals_blocked;
160  api->signals_blocked |= _POSIX_signals_Vectors[ signo ].sa_mask;
161
162  switch ( _POSIX_signals_Vectors[ signo ].sa_flags ) {
163    case SA_SIGINFO:
164      assert( 0 );   /* XXX we haven't completely implemented this yet */
165      if ( !is_global ) {
166        siginfo = &siginfo_struct;
167        siginfo->si_signo = signo;
168        siginfo->si_code = SI_USER;
169        siginfo->si_value.sival_int = 0;
170      }
171      (*_POSIX_signals_Vectors[ signo ].sa_sigaction)(
172        signo,
173        siginfo,
174        NULL        /* context is undefined per 1003.1b-1993, p. 66 */
175      );
176      break;
177    default:
178      (*_POSIX_signals_Vectors[ signo ].sa_handler)( signo );
179      break;
180  }
181
182  /*
183   *  Restore the previous set of blocked signals
184   */
185 
186  api->signals_blocked = saved_signals_blocked;
187
188  return TRUE;
189}
190
191void _POSIX_signals_Post_switch_extension(
192  Thread_Control  *the_thread
193)
194{
195  POSIX_API_Control  *api;
196  int                 signo;
197  ISR_Level           level;
198
199  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
200
201  /*
202   *  If we invoke any user code, there is the possibility that
203   *  a new signal has been posted that we should process so we
204   *  restart the loop if a signal handler was invoked.
205   *
206   *  The first thing done is to check there are any signals to be
207   *  processed at all.  No point in doing this loop otherwise.
208   */
209
210restart:
211  _ISR_Disable( level );
212    if ( !(~api->signals_blocked &
213          (api->signals_pending | _POSIX_signals_Pending)) )
214      return;
215  _ISR_Enable( level );
216
217  for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) {
218
219    if ( _POSIX_signals_Check_signal( api, signo, FALSE ) )
220      goto restart;
221
222    if ( _POSIX_signals_Check_signal( api, signo, TRUE ) )
223      goto restart;
224
225  }
226
227  for ( signo = SIGABRT ; signo <= __SIGLASTNOTRT ; signo++ ) {
228
229    if ( _POSIX_signals_Check_signal( api, signo, FALSE ) )
230      goto restart;
231 
232    if ( _POSIX_signals_Check_signal( api, signo, TRUE ) )
233      goto restart;
234
235  }
236
237}
238
239/*PAGE
240 *
241 *  _POSIX_signals_Alarm_TSR
242 */
243 
244void _POSIX_signals_Alarm_TSR(
245  Objects_Id      id,
246  void           *argument
247)
248{
249  kill( getpid(), SIGALRM );
250}
251
252/*PAGE
253 *
254 *  _POSIX_signals_Manager_Initialization
255 */
256
257void _POSIX_signals_Manager_Initialization( void )
258{
259  unsigned32 signo;
260
261  /*
262   *  Insure we have the same number of vectors and default vector entries
263   */
264
265  assert(
266   sizeof(_POSIX_signals_Vectors) == sizeof(_POSIX_signals_Default_vectors)
267  );
268
269  memcpy(
270    _POSIX_signals_Vectors,
271    _POSIX_signals_Default_vectors,
272    sizeof( _POSIX_signals_Vectors )
273  );
274 
275  /*
276   *  Initialize the set of pending signals for the entire process
277   */
278
279  sigemptyset( &_POSIX_signals_Pending );
280
281  /*
282   *  Initialize the timer used to implement alarm().
283   */
284
285  _Watchdog_Initialize(
286    &_POSIX_signals_Alarm_timer,
287    _POSIX_signals_Alarm_TSR,
288    0,
289    NULL
290  );
291 
292  /*
293   *  XXX Allocate the siginfo pools.
294   */
295
296  for ( signo=1 ; signo<= SIGRTMAX ; signo++ )
297    _Chain_Initialize_empty( &_POSIX_signals_Siginfo[ signo ] );
298
299  /* XXX especially the inactive pool */
300}
301
302/*
303 *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
304 */
305
306int sigemptyset(
307  sigset_t   *set
308)
309{
310  if ( !set )
311    set_errno_and_return_minus_one( EFAULT );
312
313  *set = 0;
314  return 0;
315}
316
317/*
318 *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
319 */
320
321int sigfillset(
322  sigset_t   *set
323)
324{
325  if ( !set )
326    set_errno_and_return_minus_one( EFAULT );
327
328  *set = SIGNAL_ALL_MASK;
329  return 0;
330}
331
332/*
333 *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
334 */
335
336int sigaddset(
337  sigset_t   *set,
338  int         signo
339)
340{
341  if ( !set )
342    set_errno_and_return_minus_one( EFAULT );
343
344  if ( !is_valid_signo(signo) )
345    set_errno_and_return_minus_one( EINVAL );
346
347  *set |= signo_to_mask(signo);
348  return 0;
349}
350
351/*
352 *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
353 */
354
355int sigdelset(
356  sigset_t   *set,
357  int         signo
358)
359{
360  if ( !set )
361    set_errno_and_return_minus_one( EFAULT );
362 
363  if ( !is_valid_signo(signo) )
364    set_errno_and_return_minus_one( EINVAL );
365 
366  *set &= ~signo_to_mask(signo);
367  return 0;
368}
369
370/*
371 *  3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
372 */
373
374int sigismember(
375  const sigset_t   *set,
376  int               signo
377)
378{
379  if ( !set )
380    set_errno_and_return_minus_one( EFAULT );
381 
382  if ( !is_valid_signo(signo) )
383    set_errno_and_return_minus_one( EINVAL );
384 
385  if ( *set & signo_to_mask(signo) )
386    return 1;
387
388  return 0;
389}
390
391/*
392 *  3.3.4 Examine and Change Signal Action, P1003.1b-1993, p. 70
393 */
394
395int sigaction(
396  int                     sig,
397  const struct sigaction *act,
398  struct sigaction       *oact
399)
400{
401  ISR_Level     level;
402
403  if ( !is_valid_signo(sig) )
404    set_errno_and_return_minus_one( EINVAL );
405 
406  if ( oact )
407    *oact = _POSIX_signals_Vectors[ sig ];
408
409  /*
410   *  Some signals cannot be ignored (P1003.1b-1993, pp. 70-72 and references.
411   *
412   *  NOTE: Solaris documentation claims to "silently enforce" this which
413   *        contradicts the POSIX specification.
414   */
415
416  if ( sig == SIGKILL )
417    set_errno_and_return_minus_one( EINVAL );
418 
419  /*
420   *  Evaluate the new action structure and set the global signal vector
421   *  appropriately.
422   */
423
424  if ( act ) {
425
426    _ISR_Disable( level );
427      if ( act->sa_handler == SIG_DFL ) {
428        _POSIX_signals_Vectors[ sig ] = _POSIX_signals_Default_vectors[ sig ];
429      } else if ( act->sa_handler == SIG_DFL ) {
430        _POSIX_signals_Pending &= ~signo_to_mask( sig );
431      } else {
432        _POSIX_signals_Pending &= ~signo_to_mask( sig );
433        _POSIX_signals_Vectors[ sig ] = *act;
434      }
435    _ISR_Enable( level );
436  }
437
438  /*
439   *  No need to evaluate or dispatch because:
440   *
441   *    + If we were ignoring the signal before, none could be pending
442   *      now (signals not posted when SIG_IGN).
443   *    + If we are now ignoring a signal that was previously pending,
444   *      we clear the pending signal indicator.
445   */
446
447  return 0;
448}
449
450/*
451 *  3.3.5 Examine and Change Blocked Signals, P1003.1b-1993, p. 73
452 *
453 *  NOTE: P1003.1c/D10, p. 37 adds pthread_sigmask().
454 *
455 */
456
457int sigprocmask(
458  int               how,
459  const sigset_t   *set,
460  sigset_t         *oset
461)
462{
463  /*
464   *  P1003.1c/Draft 10, p. 38 maps sigprocmask to pthread_sigmask.
465   */
466
467  return pthread_sigmask( how, set, oset );
468}
469
470/*
471 *  3.3.5 Examine and Change Blocked Signals, P1003.1b-1993, p. 73
472 *
473 *  NOTE: P1003.1c/D10, p. 37 adds pthread_sigmask().
474 */
475
476int pthread_sigmask(
477  int               how,
478  const sigset_t   *set,
479  sigset_t         *oset
480)
481{
482  POSIX_API_Control  *api;
483
484  if ( !set && !oset )
485    set_errno_and_return_minus_one( EFAULT );
486
487  api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
488
489  if ( oset )
490    *oset = api->signals_blocked;
491 
492  if ( !set )
493    set_errno_and_return_minus_one( EFAULT );
494
495  switch ( how ) {
496    case SIG_BLOCK:
497      api->signals_blocked |= *set;
498      break;
499    case SIG_UNBLOCK:
500      api->signals_blocked &= ~*set;
501      break;
502    case SIG_SETMASK:
503      api->signals_blocked = *set;
504      break;
505    default:
506      set_errno_and_return_minus_one( EINVAL );
507  }
508
509  /* XXX are there critical section problems here? */
510
511  /* XXX evaluate the new set */
512
513  if ( ~api->signals_blocked &
514       (api->signals_pending | _POSIX_signals_Pending) ) {
515    _Thread_Executing->do_post_task_switch_extension = TRUE;
516    _Thread_Dispatch();
517  }
518
519  return 0;
520}
521
522/*
523 *  3.3.6 Examine Pending Signals, P1003.1b-1993, p. 75
524 */
525
526int sigpending(
527  sigset_t  *set
528)
529{
530  POSIX_API_Control  *api;
531 
532  if ( !set )
533    set_errno_and_return_minus_one( EFAULT );
534 
535  api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
536 
537  *set = api->signals_pending | _POSIX_signals_Pending;
538 
539  return 0;
540}
541
542/*
543 *  3.3.7 Wait for a Signal, P1003.1b-1993, p. 75
544 */
545
546int sigsuspend(
547  const sigset_t  *sigmask
548)
549{
550  return POSIX_NOT_IMPLEMENTED();
551}
552
553/*
554 *  3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76
555 *
556 *  NOTE: P1003.1c/D10, p. 39 adds sigwait().
557 */
558
559int sigwaitinfo(
560  const sigset_t  *set,
561  siginfo_t       *info
562)
563{
564  return POSIX_NOT_IMPLEMENTED();
565}
566
567/*
568 *  3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76
569 *
570 *  NOTE: P1003.1c/D10, p. 39 adds sigwait().
571 */
572
573int sigtimedwait(
574  const sigset_t         *set,
575  siginfo_t              *info,
576  const struct timespec  *timeout
577)
578{
579  return POSIX_NOT_IMPLEMENTED();
580}
581
582/*
583 *  3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76
584 *
585 *  NOTE: P1003.1c/D10, p. 39 adds sigwait().
586 */
587
588int sigwait(
589  const sigset_t  *set,
590  int             *sig
591)
592{
593  return POSIX_NOT_IMPLEMENTED();
594}
595
596/*
597 *  3.3.9 Queue a Signal to a Process, P1003.1b-1993, p. 78
598 */
599
600int sigqueue(
601  pid_t               pid,
602  int                 signo,
603  const union sigval  value
604)
605{
606  return POSIX_NOT_IMPLEMENTED();
607}
608
609/*
610 *  3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68
611 *
612 *  NOTE: Behavior of kill() depends on _POSIX_SAVED_IDS.
613 */
614
615#define _POSIX_signals_Is_interested( _api, _mask ) \
616  ( ~(_api)->signals_blocked & (_mask) )
617         
618int kill(
619  pid_t pid,
620  int   sig
621)
622{
623  sigset_t              mask;
624  POSIX_API_Control    *api;
625  unsigned32            the_class;
626  unsigned32            index;
627  unsigned32            maximum;
628  Objects_Information  *the_info;
629  Objects_Control     **object_table;
630  Thread_Control       *the_thread;
631  Thread_Control       *interested_thread;
632  Priority_Control      interested_priority;
633
634
635  /*
636   *  Only supported for the "calling process" (i.e. this node).
637   */
638 
639  if( pid != getpid() );
640    set_errno_and_return_minus_one( ESRCH );
641
642  /*
643   *  If the signal is being ignored, then we are out of here.
644   */
645
646  if ( !sig || _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN )
647    return 0;
648
649  /*
650   *  P1003.1c/Draft 10, p. 33 says that certain signals should always
651   *  be directed to the executing thread such as those caused by hardware
652   *  faults.
653   */
654
655  switch ( sig ) {
656    case SIGFPE:
657    case SIGILL:
658    case SIGSEGV:
659      return pthread_kill( pthread_self(), sig );
660    default:
661      break;
662  }
663
664  mask = signo_to_mask( sig );
665
666  _Thread_Disable_dispatch();
667
668  _POSIX_signals_Pending |= mask;
669
670  /*
671   *  Is the currently executing thread interested?
672   */
673
674  the_thread = _Thread_Executing;
675
676  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
677  if ( _POSIX_signals_Is_interested( api, mask ) )
678    goto process_it;
679
680  /*
681   *  Is an interested thread waiting for this signal (sigwait())?
682   */
683
684  /* XXX wait for signal functions need to be done */
685
686  /*
687   *  Is any other thread interested?  The highest priority interested
688   *  thread is selected.  In the event of a tie, then the following
689   *  additional criteria is used:
690   *
691   *    + ready thread over blocked
692   *    + blocked on call interruptible by signal (can return EINTR)
693   *    + blocked on call not interruptible by signal
694   *
695   *  This looks at every thread in the system regardless of the creating API.
696   *
697   *  NOTES:
698   *
699   *    + rtems internal threads do not receive signals.
700   */
701
702  interested_thread = NULL;
703  interested_priority = PRIORITY_MAXIMUM + 1;
704
705  for ( the_class = OBJECTS_CLASSES_FIRST_THREAD_CLASS;
706        the_class <= OBJECTS_CLASSES_LAST_THREAD_CLASS;
707        the_class++ ) {
708
709    if ( the_class == OBJECTS_INTERNAL_THREADS )
710      continue;
711
712    the_info = _Objects_Information_table[ the_class ];
713
714    if ( !the_info )
715      continue;
716
717    maximum = the_info->maximum;
718    object_table = the_info->local_table;
719
720    assert( object_table );
721
722    object_table++;                         /* skip entry 0 */
723
724    for ( index = 1 ; index <= maximum ; index++ ) {
725      the_thread = (Thread_Control *) object_table++;
726
727      /*
728       *  If this thread is of lower priority than the interested thread,
729       *  go on to the next thread.
730       */
731
732      if ( the_thread->current_priority > interested_priority )
733        continue;
734
735      /*
736       *  If this thread is not interested, then go on to the next thread.
737       */
738
739      api = the_thread->API_Extensions[ THREAD_API_POSIX ];
740
741      if ( !_POSIX_signals_Is_interested( api, mask ) )
742        continue;
743
744      /*
745       *  If this thread is of higher priority logically and interested, then
746       *  it becomes the interested thread.
747       */
748
749      if ( the_thread->current_priority < interested_priority ) {
750        interested_thread   = the_thread;
751        interested_priority = the_thread->current_priority;
752        continue;
753      }
754
755      /*
756       *  Now the thread and the interested thread have the same priority.
757       *  If the interested thread is ready, then we don't need to send it
758       *  to a blocked thread.
759       */
760
761      if ( _States_Is_ready( interested_thread->current_state ) )
762        continue;
763
764      /*
765       *  The interested thread is blocked and the thread we are considering
766       *  is not, so it becomes the interested thread.
767       */
768
769      if ( _States_Is_ready( the_thread->current_state ) ) {
770        interested_thread   = the_thread;
771        interested_priority = the_thread->current_priority;
772        continue;
773      }
774
775      /*
776       *  If the interested thread is interruptible, then just use it.
777       */
778
779      /* XXX need a new states macro */
780      if ( interested_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL )
781        continue;
782
783      /*
784       *  Both the thread under consideration and the interested thread are
785       *  blocked and the interested thread is not interruptible by a signal.
786       *  If the thread under consideration is interruptible by a signal,
787       *  then it becomes the interested thread.
788       */
789
790      /* XXX need a new states macro */
791      if ( the_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL ) {
792        interested_thread   = the_thread;
793        interested_priority = the_thread->current_priority;
794      }
795    }
796  }
797
798  if ( interested_thread ) {
799    the_thread = interested_thread;
800    goto process_it;
801  }
802
803  /*
804   *  OK so no threads were interested right now.  It will be left on the
805   *  global pending until a thread receives it.  The global set of threads
806   *  can change interest in this signal in one of the following ways:
807   *
808   *    + a thread is created with the signal unblocked,
809   *    + pthread_sigmask() unblocks the signal,
810   *    + sigprocmask() unblocks the signal, OR
811   *    + sigaction() which changes the handler to SIG_IGN.
812   */
813
814  _Thread_Enable_dispatch();
815  return 0;
816
817  /*
818   *  We found a thread which was interested, so now we mark that this
819   *  thread needs to do the post context switch extension so it can
820   *  evaluate the signals pending.
821   */
822
823process_it:
824  api = the_thread->API_Extensions[ THREAD_API_POSIX ];
825
826  the_thread->do_post_task_switch_extension = TRUE;
827
828  _Thread_Enable_dispatch();
829
830   /* XXX take this out when a little more confident */
831  /* SIGABRT comes from abort via assert and must work no matter what */
832  if ( sig == SIGABRT ) {
833    exit( 1 );
834  }
835  return 0;
836}
837
838/*
839 *  3.3.10 Send a Signal to a Thread, P1003.1c/D10, p. 43
840 */
841
842int pthread_kill(
843  pthread_t   thread,
844  int         sig
845)
846{
847  POSIX_API_Control  *api;
848  Thread_Control     *the_thread;
849  Objects_Locations  location;
850
851  if ( sig && !is_valid_signo(sig) )
852    set_errno_and_return_minus_one( EINVAL );
853
854  if ( _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN )
855    return 0;
856
857  the_thread = _POSIX_Threads_Get( thread, &location );
858  switch ( location ) {
859    case OBJECTS_ERROR:
860    case OBJECTS_REMOTE:
861      return ESRCH;
862    case OBJECTS_LOCAL:
863      /*
864       *  If sig == 0 then just validate arguments
865       */
866
867      api = the_thread->API_Extensions[ THREAD_API_POSIX ];
868
869      if ( sig ) {
870
871        /* XXX critical section */
872
873        api->signals_pending |= signo_to_mask( sig );
874
875        if ( api->signals_pending & ~api->signals_blocked ) {
876          the_thread->do_post_task_switch_extension = TRUE;
877 
878          /* XXX unblock the task -- this is a kludge -- fix it */
879
880          if ( the_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL ) {
881            the_thread->Wait.return_code = EINTR;
882            if ( _States_Is_waiting_on_thread_queue(the_thread->current_state) )
883              _Thread_queue_Extract_with_proxy( the_thread );
884            else if ( _States_Is_delaying(the_thread->current_state)){
885              if ( _Watchdog_Is_active( &the_thread->Timer ) )
886                (void) _Watchdog_Remove( &the_thread->Timer );
887              _Thread_Unblock( the_thread );
888            }
889        }
890      }
891    }
892    _Thread_Enable_dispatch();
893    return 0;
894  }
895
896  return POSIX_BOTTOM_REACHED();
897}
898
899/*
900 *  3.4.1 Schedule Alarm, P1003.1b-1993, p. 79
901 */
902
903Watchdog_Control _POSIX_signals_Alarm_timer;
904
905unsigned int alarm(
906  unsigned int seconds
907)
908{
909  unsigned int      remaining = 0;
910  Watchdog_Control *the_timer;
911
912  the_timer = &_POSIX_signals_Alarm_timer;
913
914  switch ( _Watchdog_Remove( the_timer ) ) {
915    case WATCHDOG_INACTIVE:
916    case WATCHDOG_BEING_INSERTED:
917      break;
918 
919    case WATCHDOG_ACTIVE:
920    case WATCHDOG_REMOVE_IT:
921      remaining = the_timer->initial -
922                  (the_timer->stop_time - the_timer->start_time);
923      break;
924  }
925
926  _Watchdog_Insert_seconds( the_timer, seconds );
927
928  return remaining;
929}
930
931/*
932 *  3.4.2 Suspend Process Execution, P1003.1b-1993, p. 81
933 */
934
935int pause( void )
936{
937  return POSIX_NOT_IMPLEMENTED();
938}
Note: See TracBrowser for help on using the repository browser.