Changeset 07d880f4 in rtems
- Timestamp:
- 01/31/99 20:45:31 (25 years ago)
- Branches:
- 4.10, 4.11, 4.8, 4.9, 5, master
- Children:
- 7dbab720
- Parents:
- 379d2ed
- Files:
-
- 38 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
c/src/exec/posix/include/rtems/posix/psignal.h
r379d2ed r07d880f4 6 6 #define __RTEMS_POSIX_SIGNALS_h 7 7 8 #include <rtems/posix/pthread.h> 9 10 /* 11 * Currently 32 signals numbered 1-32 are defined 12 */ 13 14 #define SIGNAL_EMPTY_MASK 0x00000000 15 #define SIGNAL_ALL_MASK 0xffffffff 16 17 #define signo_to_mask( _sig ) (1 << ((_sig) - 1)) 18 19 #define is_valid_signo( _sig ) \ 20 ((_sig) >= 1 && (_sig) <= 32 ) 21 22 #define _States_Is_interruptible_signal( _states ) \ 23 ( ((_states) & \ 24 (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL)) == \ 25 (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL)) 26 27 #define SIGACTION_TERMINATE \ 28 { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Abormal_termination_handler} } 29 #define SIGACTION_IGNORE \ 30 { 0, SIGNAL_ALL_MASK, {SIG_IGN} } 31 #define SIGACTION_STOP \ 32 { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Stop_handler} } 33 #define SIGACTION_CONTINUE \ 34 { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Continue_handler} } 35 36 #define SIG_ARRAY_MAX (SIGRTMAX + 1) 37 38 /* 39 * Variables 40 */ 41 42 extern sigset_t _POSIX_signals_Pending; 43 44 extern struct sigaction _POSIX_signals_Default_vectors[ SIG_ARRAY_MAX ]; 45 46 extern struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ]; 47 48 extern Watchdog_Control _POSIX_signals_Alarm_timer; 49 50 extern Thread_queue_Control _POSIX_signals_Wait_queue; 51 52 extern Chain_Control _POSIX_signals_Inactive_siginfo; 53 54 extern Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ]; 55 56 /* 57 * POSIX internal siginfo structure 58 */ 59 8 60 typedef struct { 9 61 Chain_Node Node; 10 62 siginfo_t Info; 11 63 } POSIX_signals_Siginfo_node; 64 65 /* 66 * Internal routines 67 */ 12 68 13 69 void _POSIX_signals_Manager_Initialization( … … 19 75 ); 20 76 77 boolean _POSIX_signals_Unblock_thread( 78 Thread_Control *the_thread, 79 int signo, 80 siginfo_t *info 81 ); 82 83 boolean _POSIX_signals_Clear_signals( 84 POSIX_API_Control *api, 85 int signo, 86 siginfo_t *info, 87 boolean is_global, 88 boolean check_blocked 89 ); 90 91 int killinfo( 92 pid_t pid, 93 int sig, 94 const union sigval *value 95 ); 96 97 void _POSIX_signals_Set_process_signals( 98 sigset_t mask 99 ); 100 101 void _POSIX_signals_Set_process_signals( 102 sigset_t mask 103 ); 104 105 /* 106 * Default signal handlers 107 */ 108 109 #define _POSIX_signals_Stop_handler NULL 110 #define _POSIX_signals_Continue_handler NULL 111 112 void _POSIX_signals_Abormal_termination_handler( int signo ); 113 21 114 #endif 22 115 /* end of file */ -
c/src/exec/posix/src/Makefile.in
r379d2ed r07d880f4 30 30 pthreadattrgetscope pthreadattrsetscope 31 31 32 C_PIECES= adasupp cond getpid key mutex $(PTHREAD_PIECES) psignal sched time \ 32 PSIGNAL_PIECES=\ 33 psignal alarm kill killinfo pause pthreadkill pthreadsigmask \ 34 sigaction sigaddset sigdelset sigemptyset sigfillset sigismember \ 35 sigpending sigprocmask sigqueue sigsuspend sigtimedwait sigwait \ 36 sigwaitinfo 37 38 C_PIECES= adasupp cond getpid key mutex $(PTHREAD_PIECES) \ 39 $(PSIGNAL_PIECES) sched time \ 33 40 types unistd $(ENOSYS_C_PIECES) 41 34 42 C_FILES=$(C_PIECES:%=%.c) 35 43 C_O_FILES=$(C_PIECES:%=${ARCH}/%.o) -
c/src/exec/posix/src/psignal.c
r379d2ed r07d880f4 19 19 #include <rtems/posix/time.h> 20 20 21 /*22 * Currently 32 signals numbered 1-32 are defined23 */24 25 #define SIGNAL_EMPTY_MASK 0x0000000026 #define SIGNAL_ALL_MASK 0xffffffff27 28 #define signo_to_mask( _sig ) (1 << ((_sig) - 1))29 30 #define is_valid_signo( _sig ) \31 ((_sig) >= 1 && (_sig) <= 32 )32 33 21 /*** PROCESS WIDE STUFF ****/ 34 22 35 23 sigset_t _POSIX_signals_Pending; 36 24 37 void _POSIX_signals_Abormal_termination_handler( int signo ) 38 { 39 exit( 1 ); 40 } 41 42 #define _POSIX_signals_Stop_handler NULL 43 #define _POSIX_signals_Continue_handler NULL 44 45 #define SIGACTION_TERMINATE \ 46 { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Abormal_termination_handler} } 47 #define SIGACTION_IGNORE \ 48 { 0, SIGNAL_ALL_MASK, {SIG_IGN} } 49 #define SIGACTION_STOP \ 50 { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Stop_handler} } 51 #define SIGACTION_CONTINUE \ 52 { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Continue_handler} } 53 54 #define SIG_ARRAY_MAX (SIGRTMAX + 1) 25 struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ]; 26 27 Watchdog_Control _POSIX_signals_Alarm_timer; 28 29 Thread_queue_Control _POSIX_signals_Wait_queue; 30 31 Chain_Control _POSIX_signals_Inactive_siginfo; 32 Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ]; 33 55 34 struct sigaction _POSIX_signals_Default_vectors[ SIG_ARRAY_MAX ] = { 56 35 /* NO SIGNAL 0 */ SIGACTION_IGNORE, … … 90 69 }; 91 70 92 struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ]; 93 94 Watchdog_Control _POSIX_signals_Alarm_timer; 95 96 Thread_queue_Control _POSIX_signals_Wait_queue; 97 98 Chain_Control _POSIX_signals_Inactive_siginfo; 99 Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ]; 100 101 /*PAGE 102 * 103 * XXX - move these 104 */ 105 106 #define _States_Is_interruptible_signal( _states ) \ 107 ( ((_states) & \ 108 (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL)) == \ 109 (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL)) 71 /*PAGE 72 * 73 * _POSIX_signals_Abormal_termination_handler 74 * 75 */ 76 77 void _POSIX_signals_Abormal_termination_handler( int signo ) 78 { 79 exit( 1 ); 80 } 110 81 111 82 /*PAGE … … 485 456 ); 486 457 } 487 488 /*489 * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69490 */491 492 int sigemptyset(493 sigset_t *set494 )495 {496 if ( !set )497 set_errno_and_return_minus_one( EINVAL );498 499 *set = 0;500 return 0;501 }502 503 /*504 * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69505 */506 507 int sigfillset(508 sigset_t *set509 )510 {511 if ( !set )512 set_errno_and_return_minus_one( EINVAL );513 514 *set = SIGNAL_ALL_MASK;515 return 0;516 }517 518 /*519 * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69520 */521 522 int sigaddset(523 sigset_t *set,524 int signo525 )526 {527 if ( !set )528 set_errno_and_return_minus_one( EINVAL );529 530 if ( !signo )531 return 0;532 533 if ( !is_valid_signo(signo) )534 set_errno_and_return_minus_one( EINVAL );535 536 *set |= signo_to_mask(signo);537 return 0;538 }539 540 /*541 * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69542 */543 544 int sigdelset(545 sigset_t *set,546 int signo547 )548 {549 if ( !set )550 set_errno_and_return_minus_one( EINVAL );551 552 if ( !signo )553 return 0;554 555 if ( !is_valid_signo(signo) )556 set_errno_and_return_minus_one( EINVAL );557 558 *set &= ~signo_to_mask(signo);559 return 0;560 }561 562 /*563 * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69564 */565 566 int sigismember(567 const sigset_t *set,568 int signo569 )570 {571 if ( !set )572 set_errno_and_return_minus_one( EINVAL );573 574 if ( !signo )575 return 0;576 577 if ( !is_valid_signo(signo) )578 set_errno_and_return_minus_one( EINVAL );579 580 if ( *set & signo_to_mask(signo) )581 return 1;582 583 return 0;584 }585 586 /*587 * 3.3.4 Examine and Change Signal Action, P1003.1b-1993, p. 70588 */589 590 int sigaction(591 int sig,592 const struct sigaction *act,593 struct sigaction *oact594 )595 {596 ISR_Level level;597 598 if ( oact )599 *oact = _POSIX_signals_Vectors[ sig ];600 601 if ( !sig )602 return 0;603 604 if ( !is_valid_signo(sig) )605 set_errno_and_return_minus_one( EINVAL );606 607 /*608 * Some signals cannot be ignored (P1003.1b-1993, pp. 70-72 and references.609 *610 * NOTE: Solaris documentation claims to "silently enforce" this which611 * contradicts the POSIX specification.612 */613 614 if ( sig == SIGKILL )615 set_errno_and_return_minus_one( EINVAL );616 617 /*618 * Evaluate the new action structure and set the global signal vector619 * appropriately.620 */621 622 if ( act ) {623 624 /*625 * Unless the user is installing the default signal actions, then626 * we can just copy the provided sigaction structure into the vectors.627 */628 629 _ISR_Disable( level );630 if ( act->sa_handler == SIG_DFL ) {631 _POSIX_signals_Vectors[ sig ] = _POSIX_signals_Default_vectors[ sig ];632 } else {633 _POSIX_signals_Clear_process_signals( signo_to_mask(sig) );634 _POSIX_signals_Vectors[ sig ] = *act;635 }636 _ISR_Enable( level );637 }638 639 /*640 * No need to evaluate or dispatch because:641 *642 * + If we were ignoring the signal before, none could be pending643 * now (signals not posted when SIG_IGN).644 * + If we are now ignoring a signal that was previously pending,645 * we clear the pending signal indicator.646 */647 648 return 0;649 }650 651 /*652 * 3.3.5 Examine and Change Blocked Signals, P1003.1b-1993, p. 73653 *654 * NOTE: P1003.1c/D10, p. 37 adds pthread_sigmask().655 *656 */657 658 int sigprocmask(659 int how,660 const sigset_t *set,661 sigset_t *oset662 )663 {664 /*665 * P1003.1c/Draft 10, p. 38 maps sigprocmask to pthread_sigmask.666 */667 668 return pthread_sigmask( how, set, oset );669 }670 671 /*672 * 3.3.5 Examine and Change Blocked Signals, P1003.1b-1993, p. 73673 *674 * NOTE: P1003.1c/D10, p. 37 adds pthread_sigmask().675 */676 677 int pthread_sigmask(678 int how,679 const sigset_t *set,680 sigset_t *oset681 )682 {683 POSIX_API_Control *api;684 685 if ( !set && !oset )686 set_errno_and_return_minus_one( EINVAL );687 688 api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];689 690 if ( oset )691 *oset = api->signals_blocked;692 693 if ( !set )694 return 0;695 696 switch ( how ) {697 case SIG_BLOCK:698 api->signals_blocked |= *set;699 break;700 case SIG_UNBLOCK:701 api->signals_blocked &= ~*set;702 break;703 case SIG_SETMASK:704 api->signals_blocked = *set;705 break;706 default:707 set_errno_and_return_minus_one( EINVAL );708 }709 710 /* XXX are there critical section problems here? */711 712 /* XXX evaluate the new set */713 714 if ( ~api->signals_blocked &715 (api->signals_pending | _POSIX_signals_Pending) ) {716 _Thread_Executing->do_post_task_switch_extension = TRUE;717 _Thread_Dispatch();718 }719 720 return 0;721 }722 723 /*724 * 3.3.6 Examine Pending Signals, P1003.1b-1993, p. 75725 */726 727 int sigpending(728 sigset_t *set729 )730 {731 POSIX_API_Control *api;732 733 if ( !set )734 set_errno_and_return_minus_one( EINVAL );735 736 api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];737 738 *set = api->signals_pending | _POSIX_signals_Pending;739 740 return 0;741 }742 743 /*744 * 3.3.7 Wait for a Signal, P1003.1b-1993, p. 75745 */746 747 int sigsuspend(748 const sigset_t *sigmask749 )750 {751 sigset_t saved_signals_blocked;752 sigset_t all_signals;753 int status;754 POSIX_API_Control *api;755 756 api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];757 758 status = sigprocmask( SIG_BLOCK, sigmask, &saved_signals_blocked );759 760 (void) sigfillset( &all_signals );761 762 status = sigtimedwait( &all_signals, NULL, NULL );763 764 (void) sigprocmask( SIG_SETMASK, &saved_signals_blocked, NULL );765 766 return status;767 }768 769 /*770 * 3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76771 *772 * NOTE: P1003.1c/D10, p. 39 adds sigwait().773 */774 775 int sigwaitinfo(776 const sigset_t *set,777 siginfo_t *info778 )779 {780 return sigtimedwait( set, info, NULL );781 }782 783 /*784 * 3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76785 *786 * NOTE: P1003.1c/D10, p. 39 adds sigwait().787 */788 789 int _POSIX_signals_Get_highest(790 sigset_t set791 )792 {793 int signo;794 795 for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) {796 if ( set & signo_to_mask( signo ) )797 return signo;798 }799 800 /* XXX - add __SIGFIRSTNOTRT or something like that to newlib siginfo.h */801 802 for ( signo = SIGHUP ; signo <= __SIGLASTNOTRT ; signo++ ) {803 if ( set & signo_to_mask( signo ) )804 return signo;805 }806 807 return 0;808 }809 810 int sigtimedwait(811 const sigset_t *set,812 siginfo_t *info,813 const struct timespec *timeout814 )815 {816 Thread_Control *the_thread;817 POSIX_API_Control *api;818 Watchdog_Interval interval;819 siginfo_t signal_information;820 siginfo_t *the_info;821 int signo;822 823 the_info = ( info ) ? info : &signal_information;824 825 the_thread = _Thread_Executing;826 827 api = the_thread->API_Extensions[ THREAD_API_POSIX ];828 829 /*830 * What if they are already pending?831 */832 833 /* API signals pending? */834 835 if ( *set & api->signals_pending ) {836 /* XXX real info later */837 the_info->si_signo = _POSIX_signals_Get_highest( api->signals_pending );838 _POSIX_signals_Clear_signals( api, the_info->si_signo, the_info,839 FALSE, FALSE );840 the_info->si_code = SI_USER;841 the_info->si_value.sival_int = 0;842 return the_info->si_signo;843 }844 845 /* Process pending signals? */846 847 if ( *set & _POSIX_signals_Pending) {848 signo = _POSIX_signals_Get_highest( _POSIX_signals_Pending );849 _POSIX_signals_Clear_signals( api, signo, the_info, TRUE, FALSE );850 851 if ( !info ) {852 the_info->si_signo = signo;853 the_info->si_code = SI_USER;854 the_info->si_value.sival_int = 0;855 }856 }857 858 interval = 0;859 if ( timeout ) {860 861 if (timeout->tv_nsec < 0 || timeout->tv_nsec >= TOD_NANOSECONDS_PER_SECOND)862 set_errno_and_return_minus_one( EINVAL );863 864 interval = _POSIX_Timespec_to_interval( timeout );865 }866 867 the_info->si_signo = -1;868 869 _Thread_Disable_dispatch();870 the_thread->Wait.queue = &_POSIX_signals_Wait_queue;871 the_thread->Wait.return_code = EINTR;872 the_thread->Wait.option = *set;873 the_thread->Wait.return_argument = (void *) the_info;874 _Thread_queue_Enter_critical_section( &_POSIX_signals_Wait_queue );875 _Thread_queue_Enqueue( &_POSIX_signals_Wait_queue, interval );876 _Thread_Enable_dispatch();877 878 errno = _Thread_Executing->Wait.return_code;879 return the_info->si_signo;880 }881 882 /*883 * 3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76884 *885 * NOTE: P1003.1c/D10, p. 39 adds sigwait().886 */887 888 int sigwait(889 const sigset_t *set,890 int *sig891 )892 {893 int status;894 895 status = sigtimedwait( set, NULL, NULL );896 897 if ( status != -1 ) {898 if ( sig )899 *sig = status;900 return 0;901 }902 903 return errno;904 }905 906 /*PAGE907 *908 * 3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68909 *910 * NOTE: Behavior of kill() depends on _POSIX_SAVED_IDS.911 */912 913 #define _POSIX_signals_Is_interested( _api, _mask ) \914 ( ~(_api)->signals_blocked & (_mask) )915 916 int killinfo(917 pid_t pid,918 int sig,919 const union sigval *value920 )921 {922 sigset_t mask;923 POSIX_API_Control *api;924 unsigned32 the_class;925 unsigned32 index;926 unsigned32 maximum;927 Objects_Information *the_info;928 Objects_Control **object_table;929 Thread_Control *the_thread;930 Thread_Control *interested_thread;931 Priority_Control interested_priority;932 Chain_Control *the_chain;933 Chain_Node *the_node;934 siginfo_t siginfo_struct;935 siginfo_t *siginfo;936 POSIX_signals_Siginfo_node *psiginfo;937 938 /*939 * Only supported for the "calling process" (i.e. this node).940 */941 942 if( pid != getpid() )943 set_errno_and_return_minus_one( ESRCH );944 945 /*946 * Validate the signal passed if not 0.947 */948 949 if ( sig && !is_valid_signo(sig) )950 set_errno_and_return_minus_one( EINVAL );951 952 /*953 * If the signal is being ignored, then we are out of here.954 */955 956 if ( !sig || _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN )957 return 0;958 959 /*960 * P1003.1c/Draft 10, p. 33 says that certain signals should always961 * be directed to the executing thread such as those caused by hardware962 * faults.963 */964 965 switch ( sig ) {966 case SIGFPE:967 case SIGILL:968 case SIGSEGV:969 return pthread_kill( pthread_self(), sig );970 default:971 break;972 }973 974 mask = signo_to_mask( sig );975 976 /*977 * Build up a siginfo structure978 */979 980 siginfo = &siginfo_struct;981 siginfo->si_signo = sig;982 siginfo->si_code = SI_USER;983 if ( !value ) {984 siginfo->si_value.sival_int = 0;985 } else {986 siginfo->si_value = *value;987 }988 989 _Thread_Disable_dispatch();990 991 /*992 * Is the currently executing thread interested? If so then it will993 * get it an execute it as soon as the dispatcher executes.994 */995 996 the_thread = _Thread_Executing;997 998 api = the_thread->API_Extensions[ THREAD_API_POSIX ];999 if ( _POSIX_signals_Is_interested( api, mask ) ) {1000 goto process_it;1001 }1002 1003 /*1004 * Is an interested thread waiting for this signal (sigwait())?1005 */1006 1007 /* XXX violation of visibility -- need to define thread queue support */1008 1009 for( index=0 ;1010 index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;1011 index++ ) {1012 1013 the_chain = &_POSIX_signals_Wait_queue.Queues.Priority[ index ];1014 1015 for ( the_node = the_chain->first ;1016 !_Chain_Is_tail( the_chain, the_node ) ;1017 the_node = the_node->next ) {1018 1019 the_thread = (Thread_Control *)the_node;1020 api = the_thread->API_Extensions[ THREAD_API_POSIX ];1021 1022 if ((the_thread->Wait.option & mask) || (~api->signals_blocked & mask)) {1023 goto process_it;1024 }1025 1026 }1027 }1028 1029 /*1030 * Is any other thread interested? The highest priority interested1031 * thread is selected. In the event of a tie, then the following1032 * additional criteria is used:1033 *1034 * + ready thread over blocked1035 * + blocked on call interruptible by signal (can return EINTR)1036 * + blocked on call not interruptible by signal1037 *1038 * This looks at every thread in the system regardless of the creating API.1039 *1040 * NOTES:1041 *1042 * + rtems internal threads do not receive signals.1043 */1044 1045 interested_thread = NULL;1046 interested_priority = PRIORITY_MAXIMUM + 1;1047 1048 for ( the_class = OBJECTS_CLASSES_FIRST_THREAD_CLASS;1049 the_class <= OBJECTS_CLASSES_LAST_THREAD_CLASS;1050 the_class++ ) {1051 1052 if ( the_class == OBJECTS_INTERNAL_THREADS )1053 continue;1054 1055 the_info = _Objects_Information_table[ the_class ];1056 1057 if ( !the_info ) /* manager not installed */1058 continue;1059 1060 maximum = the_info->maximum;1061 object_table = the_info->local_table;1062 1063 assert( object_table ); /* always at least 1 entry */1064 1065 for ( index = 1 ; index <= maximum ; index++ ) {1066 the_thread = (Thread_Control *) object_table[ index ];1067 1068 if ( !the_thread )1069 continue;1070 1071 /*1072 * If this thread is of lower priority than the interested thread,1073 * go on to the next thread.1074 */1075 1076 if ( the_thread->current_priority > interested_priority )1077 continue;1078 1079 /*1080 * If this thread is not interested, then go on to the next thread.1081 */1082 1083 api = the_thread->API_Extensions[ THREAD_API_POSIX ];1084 1085 if ( !api || !_POSIX_signals_Is_interested( api, mask ) )1086 continue;1087 1088 /*1089 * Now we know the thread under connsideration is interested.1090 * If the thread under consideration is of higher priority, then1091 * it becomes the interested thread.1092 */1093 1094 if ( the_thread->current_priority < interested_priority ) {1095 interested_thread = the_thread;1096 interested_priority = the_thread->current_priority;1097 continue;1098 }1099 1100 /*1101 * Now the thread and the interested thread have the same priority.1102 * If the interested thread is ready, then we don't need to send it1103 * to a blocked thread.1104 */1105 1106 if ( _States_Is_ready( interested_thread->current_state ) )1107 continue;1108 1109 /*1110 * Now the interested thread is blocked.1111 * If the thread we are considering is not, the it becomes the1112 * interested thread.1113 */1114 1115 if ( _States_Is_ready( the_thread->current_state ) ) {1116 interested_thread = the_thread;1117 interested_priority = the_thread->current_priority;1118 continue;1119 }1120 1121 /*1122 * Now we know both threads are blocked.1123 * If the interested thread is interruptible, then just use it.1124 */1125 1126 /* XXX need a new states macro */1127 if ( interested_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL )1128 continue;1129 1130 /*1131 * Now both threads are blocked and the interested thread is not1132 * interruptible.1133 * If the thread under consideration is interruptible by a signal,1134 * then it becomes the interested thread.1135 */1136 1137 /* XXX need a new states macro */1138 if ( the_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL ) {1139 interested_thread = the_thread;1140 interested_priority = the_thread->current_priority;1141 }1142 }1143 }1144 1145 if ( interested_thread ) {1146 the_thread = interested_thread;1147 goto process_it;1148 }1149 1150 /*1151 * OK so no threads were interested right now. It will be left on the1152 * global pending until a thread receives it. The global set of threads1153 * can change interest in this signal in one of the following ways:1154 *1155 * + a thread is created with the signal unblocked,1156 * + pthread_sigmask() unblocks the signal,1157 * + sigprocmask() unblocks the signal, OR1158 * + sigaction() which changes the handler to SIG_IGN.1159 */1160 1161 the_thread = NULL;1162 goto post_process_signal;1163 1164 /*1165 * We found a thread which was interested, so now we mark that this1166 * thread needs to do the post context switch extension so it can1167 * evaluate the signals pending.1168 */1169 1170 process_it:1171 1172 the_thread->do_post_task_switch_extension = TRUE;1173 1174 /*1175 * Returns TRUE if the signal was synchronously given to a thread1176 * blocked waiting for the signal.1177 */1178 1179 if ( _POSIX_signals_Unblock_thread( the_thread, sig, siginfo ) ) {1180 _Thread_Enable_dispatch();1181 return 0;1182 }1183 1184 post_process_signal:1185 1186 /*1187 * We may have woken up a thread but we definitely need to post the1188 * signal to the process wide information set.1189 */1190 1191 _POSIX_signals_Set_process_signals( mask );1192 1193 if ( _POSIX_signals_Vectors[ sig ].sa_flags == SA_SIGINFO ) {1194 1195 psiginfo = (POSIX_signals_Siginfo_node *)1196 _Chain_Get( &_POSIX_signals_Inactive_siginfo );1197 if ( !psiginfo )1198 set_errno_and_return_minus_one( EAGAIN );1199 1200 psiginfo->Info = *siginfo;1201 1202 _Chain_Append( &_POSIX_signals_Siginfo[ sig ], &psiginfo->Node );1203 }1204 1205 _Thread_Enable_dispatch();1206 return 0;1207 }1208 1209 /*PAGE1210 *1211 * 3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 681212 *1213 * NOTE: Behavior of kill() depends on _POSIX_SAVED_IDS.1214 */1215 1216 int kill(1217 pid_t pid,1218 int sig1219 )1220 {1221 return killinfo( pid, sig, NULL );1222 }1223 1224 /*1225 * _kill_r1226 *1227 * This is the Newlib dependent reentrant version of kill().1228 */1229 1230 #if defined(RTEMS_NEWLIB)1231 1232 #include <reent.h>1233 1234 int _kill_r(1235 struct _reent *ptr,1236 pid_t pid,1237 int sig1238 )1239 {1240 return kill( pid, sig );1241 }1242 #endif1243 1244 /*1245 * 3.3.9 Queue a Signal to a Process, P1003.1b-1993, p. 781246 */1247 1248 int sigqueue(1249 pid_t pid,1250 int signo,1251 const union sigval value1252 )1253 {1254 return killinfo( pid, signo, &value );1255 }1256 1257 /*1258 * 3.3.10 Send a Signal to a Thread, P1003.1c/D10, p. 431259 */1260 1261 int pthread_kill(1262 pthread_t thread,1263 int sig1264 )1265 {1266 POSIX_API_Control *api;1267 Thread_Control *the_thread;1268 Objects_Locations location;1269 1270 if ( sig && !is_valid_signo(sig) )1271 set_errno_and_return_minus_one( EINVAL );1272 1273 if ( _POSIX_signals_Vectors[ sig ].sa_flags == SA_SIGINFO )1274 set_errno_and_return_minus_one( ENOSYS );1275 1276 /*1277 * RTEMS does not support sending a siginfo signal to a specific thread.1278 */1279 1280 the_thread = _POSIX_Threads_Get( thread, &location );1281 switch ( location ) {1282 case OBJECTS_ERROR:1283 case OBJECTS_REMOTE:1284 set_errno_and_return_minus_one( ESRCH );1285 case OBJECTS_LOCAL:1286 /*1287 * If sig == 0 then just validate arguments1288 */1289 1290 api = the_thread->API_Extensions[ THREAD_API_POSIX ];1291 1292 if ( sig ) {1293 1294 if ( _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN ) {1295 _Thread_Enable_dispatch();1296 return 0;1297 }1298 1299 /* XXX critical section */1300 1301 api->signals_pending |= signo_to_mask( sig );1302 1303 (void) _POSIX_signals_Unblock_thread( the_thread, sig, NULL );1304 1305 the_thread->do_post_task_switch_extension = TRUE;1306 1307 if ( _ISR_Is_in_progress() && _Thread_Is_executing( the_thread ) )1308 _ISR_Signals_to_thread_executing = TRUE;1309 }1310 _Thread_Enable_dispatch();1311 return 0;1312 }1313 1314 return POSIX_BOTTOM_REACHED();1315 }1316 1317 /*1318 * 3.4.1 Schedule Alarm, P1003.1b-1993, p. 791319 */1320 1321 Watchdog_Control _POSIX_signals_Alarm_timer;1322 1323 unsigned int alarm(1324 unsigned int seconds1325 )1326 {1327 unsigned int remaining = 0;1328 Watchdog_Control *the_timer;1329 1330 the_timer = &_POSIX_signals_Alarm_timer;1331 1332 switch ( _Watchdog_Remove( the_timer ) ) {1333 case WATCHDOG_INACTIVE:1334 case WATCHDOG_BEING_INSERTED:1335 break;1336 1337 case WATCHDOG_ACTIVE:1338 case WATCHDOG_REMOVE_IT:1339 remaining = the_timer->initial -1340 (the_timer->stop_time - the_timer->start_time);1341 break;1342 }1343 1344 _Watchdog_Insert_seconds( the_timer, seconds );1345 1346 return remaining;1347 }1348 1349 /*1350 * 3.4.2 Suspend Process Execution, P1003.1b-1993, p. 811351 */1352 1353 int pause( void )1354 {1355 sigset_t all_signals;1356 int status;1357 1358 (void) sigfillset( &all_signals );1359 1360 status = sigtimedwait( &all_signals, NULL, NULL );1361 1362 return status;1363 } -
cpukit/posix/include/rtems/posix/psignal.h
r379d2ed r07d880f4 6 6 #define __RTEMS_POSIX_SIGNALS_h 7 7 8 #include <rtems/posix/pthread.h> 9 10 /* 11 * Currently 32 signals numbered 1-32 are defined 12 */ 13 14 #define SIGNAL_EMPTY_MASK 0x00000000 15 #define SIGNAL_ALL_MASK 0xffffffff 16 17 #define signo_to_mask( _sig ) (1 << ((_sig) - 1)) 18 19 #define is_valid_signo( _sig ) \ 20 ((_sig) >= 1 && (_sig) <= 32 ) 21 22 #define _States_Is_interruptible_signal( _states ) \ 23 ( ((_states) & \ 24 (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL)) == \ 25 (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL)) 26 27 #define SIGACTION_TERMINATE \ 28 { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Abormal_termination_handler} } 29 #define SIGACTION_IGNORE \ 30 { 0, SIGNAL_ALL_MASK, {SIG_IGN} } 31 #define SIGACTION_STOP \ 32 { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Stop_handler} } 33 #define SIGACTION_CONTINUE \ 34 { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Continue_handler} } 35 36 #define SIG_ARRAY_MAX (SIGRTMAX + 1) 37 38 /* 39 * Variables 40 */ 41 42 extern sigset_t _POSIX_signals_Pending; 43 44 extern struct sigaction _POSIX_signals_Default_vectors[ SIG_ARRAY_MAX ]; 45 46 extern struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ]; 47 48 extern Watchdog_Control _POSIX_signals_Alarm_timer; 49 50 extern Thread_queue_Control _POSIX_signals_Wait_queue; 51 52 extern Chain_Control _POSIX_signals_Inactive_siginfo; 53 54 extern Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ]; 55 56 /* 57 * POSIX internal siginfo structure 58 */ 59 8 60 typedef struct { 9 61 Chain_Node Node; 10 62 siginfo_t Info; 11 63 } POSIX_signals_Siginfo_node; 64 65 /* 66 * Internal routines 67 */ 12 68 13 69 void _POSIX_signals_Manager_Initialization( … … 19 75 ); 20 76 77 boolean _POSIX_signals_Unblock_thread( 78 Thread_Control *the_thread, 79 int signo, 80 siginfo_t *info 81 ); 82 83 boolean _POSIX_signals_Clear_signals( 84 POSIX_API_Control *api, 85 int signo, 86 siginfo_t *info, 87 boolean is_global, 88 boolean check_blocked 89 ); 90 91 int killinfo( 92 pid_t pid, 93 int sig, 94 const union sigval *value 95 ); 96 97 void _POSIX_signals_Set_process_signals( 98 sigset_t mask 99 ); 100 101 void _POSIX_signals_Set_process_signals( 102 sigset_t mask 103 ); 104 105 /* 106 * Default signal handlers 107 */ 108 109 #define _POSIX_signals_Stop_handler NULL 110 #define _POSIX_signals_Continue_handler NULL 111 112 void _POSIX_signals_Abormal_termination_handler( int signo ); 113 21 114 #endif 22 115 /* end of file */ -
cpukit/posix/src/psignal.c
r379d2ed r07d880f4 19 19 #include <rtems/posix/time.h> 20 20 21 /*22 * Currently 32 signals numbered 1-32 are defined23 */24 25 #define SIGNAL_EMPTY_MASK 0x0000000026 #define SIGNAL_ALL_MASK 0xffffffff27 28 #define signo_to_mask( _sig ) (1 << ((_sig) - 1))29 30 #define is_valid_signo( _sig ) \31 ((_sig) >= 1 && (_sig) <= 32 )32 33 21 /*** PROCESS WIDE STUFF ****/ 34 22 35 23 sigset_t _POSIX_signals_Pending; 36 24 37 void _POSIX_signals_Abormal_termination_handler( int signo ) 38 { 39 exit( 1 ); 40 } 41 42 #define _POSIX_signals_Stop_handler NULL 43 #define _POSIX_signals_Continue_handler NULL 44 45 #define SIGACTION_TERMINATE \ 46 { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Abormal_termination_handler} } 47 #define SIGACTION_IGNORE \ 48 { 0, SIGNAL_ALL_MASK, {SIG_IGN} } 49 #define SIGACTION_STOP \ 50 { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Stop_handler} } 51 #define SIGACTION_CONTINUE \ 52 { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Continue_handler} } 53 54 #define SIG_ARRAY_MAX (SIGRTMAX + 1) 25 struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ]; 26 27 Watchdog_Control _POSIX_signals_Alarm_timer; 28 29 Thread_queue_Control _POSIX_signals_Wait_queue; 30 31 Chain_Control _POSIX_signals_Inactive_siginfo; 32 Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ]; 33 55 34 struct sigaction _POSIX_signals_Default_vectors[ SIG_ARRAY_MAX ] = { 56 35 /* NO SIGNAL 0 */ SIGACTION_IGNORE, … … 90 69 }; 91 70 92 struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ]; 93 94 Watchdog_Control _POSIX_signals_Alarm_timer; 95 96 Thread_queue_Control _POSIX_signals_Wait_queue; 97 98 Chain_Control _POSIX_signals_Inactive_siginfo; 99 Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ]; 100 101 /*PAGE 102 * 103 * XXX - move these 104 */ 105 106 #define _States_Is_interruptible_signal( _states ) \ 107 ( ((_states) & \ 108 (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL)) == \ 109 (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL)) 71 /*PAGE 72 * 73 * _POSIX_signals_Abormal_termination_handler 74 * 75 */ 76 77 void _POSIX_signals_Abormal_termination_handler( int signo ) 78 { 79 exit( 1 ); 80 } 110 81 111 82 /*PAGE … … 485 456 ); 486 457 } 487 488 /*489 * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69490 */491 492 int sigemptyset(493 sigset_t *set494 )495 {496 if ( !set )497 set_errno_and_return_minus_one( EINVAL );498 499 *set = 0;500 return 0;501 }502 503 /*504 * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69505 */506 507 int sigfillset(508 sigset_t *set509 )510 {511 if ( !set )512 set_errno_and_return_minus_one( EINVAL );513 514 *set = SIGNAL_ALL_MASK;515 return 0;516 }517 518 /*519 * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69520 */521 522 int sigaddset(523 sigset_t *set,524 int signo525 )526 {527 if ( !set )528 set_errno_and_return_minus_one( EINVAL );529 530 if ( !signo )531 return 0;532 533 if ( !is_valid_signo(signo) )534 set_errno_and_return_minus_one( EINVAL );535 536 *set |= signo_to_mask(signo);537 return 0;538 }539 540 /*541 * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69542 */543 544 int sigdelset(545 sigset_t *set,546 int signo547 )548 {549 if ( !set )550 set_errno_and_return_minus_one( EINVAL );551 552 if ( !signo )553 return 0;554 555 if ( !is_valid_signo(signo) )556 set_errno_and_return_minus_one( EINVAL );557 558 *set &= ~signo_to_mask(signo);559 return 0;560 }561 562 /*563 * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69564 */565 566 int sigismember(567 const sigset_t *set,568 int signo569 )570 {571 if ( !set )572 set_errno_and_return_minus_one( EINVAL );573 574 if ( !signo )575 return 0;576 577 if ( !is_valid_signo(signo) )578 set_errno_and_return_minus_one( EINVAL );579 580 if ( *set & signo_to_mask(signo) )581 return 1;582 583 return 0;584 }585 586 /*587 * 3.3.4 Examine and Change Signal Action, P1003.1b-1993, p. 70588 */589 590 int sigaction(591 int sig,592 const struct sigaction *act,593 struct sigaction *oact594 )595 {596 ISR_Level level;597 598 if ( oact )599 *oact = _POSIX_signals_Vectors[ sig ];600 601 if ( !sig )602 return 0;603 604 if ( !is_valid_signo(sig) )605 set_errno_and_return_minus_one( EINVAL );606 607 /*608 * Some signals cannot be ignored (P1003.1b-1993, pp. 70-72 and references.609 *610 * NOTE: Solaris documentation claims to "silently enforce" this which611 * contradicts the POSIX specification.612 */613 614 if ( sig == SIGKILL )615 set_errno_and_return_minus_one( EINVAL );616 617 /*618 * Evaluate the new action structure and set the global signal vector619 * appropriately.620 */621 622 if ( act ) {623 624 /*625 * Unless the user is installing the default signal actions, then626 * we can just copy the provided sigaction structure into the vectors.627 */628 629 _ISR_Disable( level );630 if ( act->sa_handler == SIG_DFL ) {631 _POSIX_signals_Vectors[ sig ] = _POSIX_signals_Default_vectors[ sig ];632 } else {633 _POSIX_signals_Clear_process_signals( signo_to_mask(sig) );634 _POSIX_signals_Vectors[ sig ] = *act;635 }636 _ISR_Enable( level );637 }638 639 /*640 * No need to evaluate or dispatch because:641 *642 * + If we were ignoring the signal before, none could be pending643 * now (signals not posted when SIG_IGN).644 * + If we are now ignoring a signal that was previously pending,645 * we clear the pending signal indicator.646 */647 648 return 0;649 }650 651 /*652 * 3.3.5 Examine and Change Blocked Signals, P1003.1b-1993, p. 73653 *654 * NOTE: P1003.1c/D10, p. 37 adds pthread_sigmask().655 *656 */657 658 int sigprocmask(659 int how,660 const sigset_t *set,661 sigset_t *oset662 )663 {664 /*665 * P1003.1c/Draft 10, p. 38 maps sigprocmask to pthread_sigmask.666 */667 668 return pthread_sigmask( how, set, oset );669 }670 671 /*672 * 3.3.5 Examine and Change Blocked Signals, P1003.1b-1993, p. 73673 *674 * NOTE: P1003.1c/D10, p. 37 adds pthread_sigmask().675 */676 677 int pthread_sigmask(678 int how,679 const sigset_t *set,680 sigset_t *oset681 )682 {683 POSIX_API_Control *api;684 685 if ( !set && !oset )686 set_errno_and_return_minus_one( EINVAL );687 688 api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];689 690 if ( oset )691 *oset = api->signals_blocked;692 693 if ( !set )694 return 0;695 696 switch ( how ) {697 case SIG_BLOCK:698 api->signals_blocked |= *set;699 break;700 case SIG_UNBLOCK:701 api->signals_blocked &= ~*set;702 break;703 case SIG_SETMASK:704 api->signals_blocked = *set;705 break;706 default:707 set_errno_and_return_minus_one( EINVAL );708 }709 710 /* XXX are there critical section problems here? */711 712 /* XXX evaluate the new set */713 714 if ( ~api->signals_blocked &715 (api->signals_pending | _POSIX_signals_Pending) ) {716 _Thread_Executing->do_post_task_switch_extension = TRUE;717 _Thread_Dispatch();718 }719 720 return 0;721 }722 723 /*724 * 3.3.6 Examine Pending Signals, P1003.1b-1993, p. 75725 */726 727 int sigpending(728 sigset_t *set729 )730 {731 POSIX_API_Control *api;732 733 if ( !set )734 set_errno_and_return_minus_one( EINVAL );735 736 api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];737 738 *set = api->signals_pending | _POSIX_signals_Pending;739 740 return 0;741 }742 743 /*744 * 3.3.7 Wait for a Signal, P1003.1b-1993, p. 75745 */746 747 int sigsuspend(748 const sigset_t *sigmask749 )750 {751 sigset_t saved_signals_blocked;752 sigset_t all_signals;753 int status;754 POSIX_API_Control *api;755 756 api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];757 758 status = sigprocmask( SIG_BLOCK, sigmask, &saved_signals_blocked );759 760 (void) sigfillset( &all_signals );761 762 status = sigtimedwait( &all_signals, NULL, NULL );763 764 (void) sigprocmask( SIG_SETMASK, &saved_signals_blocked, NULL );765 766 return status;767 }768 769 /*770 * 3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76771 *772 * NOTE: P1003.1c/D10, p. 39 adds sigwait().773 */774 775 int sigwaitinfo(776 const sigset_t *set,777 siginfo_t *info778 )779 {780 return sigtimedwait( set, info, NULL );781 }782 783 /*784 * 3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76785 *786 * NOTE: P1003.1c/D10, p. 39 adds sigwait().787 */788 789 int _POSIX_signals_Get_highest(790 sigset_t set791 )792 {793 int signo;794 795 for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) {796 if ( set & signo_to_mask( signo ) )797 return signo;798 }799 800 /* XXX - add __SIGFIRSTNOTRT or something like that to newlib siginfo.h */801 802 for ( signo = SIGHUP ; signo <= __SIGLASTNOTRT ; signo++ ) {803 if ( set & signo_to_mask( signo ) )804 return signo;805 }806 807 return 0;808 }809 810 int sigtimedwait(811 const sigset_t *set,812 siginfo_t *info,813 const struct timespec *timeout814 )815 {816 Thread_Control *the_thread;817 POSIX_API_Control *api;818 Watchdog_Interval interval;819 siginfo_t signal_information;820 siginfo_t *the_info;821 int signo;822 823 the_info = ( info ) ? info : &signal_information;824 825 the_thread = _Thread_Executing;826 827 api = the_thread->API_Extensions[ THREAD_API_POSIX ];828 829 /*830 * What if they are already pending?831 */832 833 /* API signals pending? */834 835 if ( *set & api->signals_pending ) {836 /* XXX real info later */837 the_info->si_signo = _POSIX_signals_Get_highest( api->signals_pending );838 _POSIX_signals_Clear_signals( api, the_info->si_signo, the_info,839 FALSE, FALSE );840 the_info->si_code = SI_USER;841 the_info->si_value.sival_int = 0;842 return the_info->si_signo;843 }844 845 /* Process pending signals? */846 847 if ( *set & _POSIX_signals_Pending) {848 signo = _POSIX_signals_Get_highest( _POSIX_signals_Pending );849 _POSIX_signals_Clear_signals( api, signo, the_info, TRUE, FALSE );850 851 if ( !info ) {852 the_info->si_signo = signo;853 the_info->si_code = SI_USER;854 the_info->si_value.sival_int = 0;855 }856 }857 858 interval = 0;859 if ( timeout ) {860 861 if (timeout->tv_nsec < 0 || timeout->tv_nsec >= TOD_NANOSECONDS_PER_SECOND)862 set_errno_and_return_minus_one( EINVAL );863 864 interval = _POSIX_Timespec_to_interval( timeout );865 }866 867 the_info->si_signo = -1;868 869 _Thread_Disable_dispatch();870 the_thread->Wait.queue = &_POSIX_signals_Wait_queue;871 the_thread->Wait.return_code = EINTR;872 the_thread->Wait.option = *set;873 the_thread->Wait.return_argument = (void *) the_info;874 _Thread_queue_Enter_critical_section( &_POSIX_signals_Wait_queue );875 _Thread_queue_Enqueue( &_POSIX_signals_Wait_queue, interval );876 _Thread_Enable_dispatch();877 878 errno = _Thread_Executing->Wait.return_code;879 return the_info->si_signo;880 }881 882 /*883 * 3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76884 *885 * NOTE: P1003.1c/D10, p. 39 adds sigwait().886 */887 888 int sigwait(889 const sigset_t *set,890 int *sig891 )892 {893 int status;894 895 status = sigtimedwait( set, NULL, NULL );896 897 if ( status != -1 ) {898 if ( sig )899 *sig = status;900 return 0;901 }902 903 return errno;904 }905 906 /*PAGE907 *908 * 3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68909 *910 * NOTE: Behavior of kill() depends on _POSIX_SAVED_IDS.911 */912 913 #define _POSIX_signals_Is_interested( _api, _mask ) \914 ( ~(_api)->signals_blocked & (_mask) )915 916 int killinfo(917 pid_t pid,918 int sig,919 const union sigval *value920 )921 {922 sigset_t mask;923 POSIX_API_Control *api;924 unsigned32 the_class;925 unsigned32 index;926 unsigned32 maximum;927 Objects_Information *the_info;928 Objects_Control **object_table;929 Thread_Control *the_thread;930 Thread_Control *interested_thread;931 Priority_Control interested_priority;932 Chain_Control *the_chain;933 Chain_Node *the_node;934 siginfo_t siginfo_struct;935 siginfo_t *siginfo;936 POSIX_signals_Siginfo_node *psiginfo;937 938 /*939 * Only supported for the "calling process" (i.e. this node).940 */941 942 if( pid != getpid() )943 set_errno_and_return_minus_one( ESRCH );944 945 /*946 * Validate the signal passed if not 0.947 */948 949 if ( sig && !is_valid_signo(sig) )950 set_errno_and_return_minus_one( EINVAL );951 952 /*953 * If the signal is being ignored, then we are out of here.954 */955 956 if ( !sig || _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN )957 return 0;958 959 /*960 * P1003.1c/Draft 10, p. 33 says that certain signals should always961 * be directed to the executing thread such as those caused by hardware962 * faults.963 */964 965 switch ( sig ) {966 case SIGFPE:967 case SIGILL:968 case SIGSEGV:969 return pthread_kill( pthread_self(), sig );970 default:971 break;972 }973 974 mask = signo_to_mask( sig );975 976 /*977 * Build up a siginfo structure978 */979 980 siginfo = &siginfo_struct;981 siginfo->si_signo = sig;982 siginfo->si_code = SI_USER;983 if ( !value ) {984 siginfo->si_value.sival_int = 0;985 } else {986 siginfo->si_value = *value;987 }988 989 _Thread_Disable_dispatch();990 991 /*992 * Is the currently executing thread interested? If so then it will993 * get it an execute it as soon as the dispatcher executes.994 */995 996 the_thread = _Thread_Executing;997 998 api = the_thread->API_Extensions[ THREAD_API_POSIX ];999 if ( _POSIX_signals_Is_interested( api, mask ) ) {1000 goto process_it;1001 }1002 1003 /*1004 * Is an interested thread waiting for this signal (sigwait())?1005 */1006 1007 /* XXX violation of visibility -- need to define thread queue support */1008 1009 for( index=0 ;1010 index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;1011 index++ ) {1012 1013 the_chain = &_POSIX_signals_Wait_queue.Queues.Priority[ index ];1014 1015 for ( the_node = the_chain->first ;1016 !_Chain_Is_tail( the_chain, the_node ) ;1017 the_node = the_node->next ) {1018 1019 the_thread = (Thread_Control *)the_node;1020 api = the_thread->API_Extensions[ THREAD_API_POSIX ];1021 1022 if ((the_thread->Wait.option & mask) || (~api->signals_blocked & mask)) {1023 goto process_it;1024 }1025 1026 }1027 }1028 1029 /*1030 * Is any other thread interested? The highest priority interested1031 * thread is selected. In the event of a tie, then the following1032 * additional criteria is used:1033 *1034 * + ready thread over blocked1035 * + blocked on call interruptible by signal (can return EINTR)1036 * + blocked on call not interruptible by signal1037 *1038 * This looks at every thread in the system regardless of the creating API.1039 *1040 * NOTES:1041 *1042 * + rtems internal threads do not receive signals.1043 */1044 1045 interested_thread = NULL;1046 interested_priority = PRIORITY_MAXIMUM + 1;1047 1048 for ( the_class = OBJECTS_CLASSES_FIRST_THREAD_CLASS;1049 the_class <= OBJECTS_CLASSES_LAST_THREAD_CLASS;1050 the_class++ ) {1051 1052 if ( the_class == OBJECTS_INTERNAL_THREADS )1053 continue;1054 1055 the_info = _Objects_Information_table[ the_class ];1056 1057 if ( !the_info ) /* manager not installed */1058 continue;1059 1060 maximum = the_info->maximum;1061 object_table = the_info->local_table;1062 1063 assert( object_table ); /* always at least 1 entry */1064 1065 for ( index = 1 ; index <= maximum ; index++ ) {1066 the_thread = (Thread_Control *) object_table[ index ];1067 1068 if ( !the_thread )1069 continue;1070 1071 /*1072 * If this thread is of lower priority than the interested thread,1073 * go on to the next thread.1074 */1075 1076 if ( the_thread->current_priority > interested_priority )1077 continue;1078 1079 /*1080 * If this thread is not interested, then go on to the next thread.1081 */1082 1083 api = the_thread->API_Extensions[ THREAD_API_POSIX ];1084 1085 if ( !api || !_POSIX_signals_Is_interested( api, mask ) )1086 continue;1087 1088 /*1089 * Now we know the thread under connsideration is interested.1090 * If the thread under consideration is of higher priority, then1091 * it becomes the interested thread.1092 */1093 1094 if ( the_thread->current_priority < interested_priority ) {1095 interested_thread = the_thread;1096 interested_priority = the_thread->current_priority;1097 continue;1098 }1099 1100 /*1101 * Now the thread and the interested thread have the same priority.1102 * If the interested thread is ready, then we don't need to send it1103 * to a blocked thread.1104 */1105 1106 if ( _States_Is_ready( interested_thread->current_state ) )1107 continue;1108 1109 /*1110 * Now the interested thread is blocked.1111 * If the thread we are considering is not, the it becomes the1112 * interested thread.1113 */1114 1115 if ( _States_Is_ready( the_thread->current_state ) ) {1116 interested_thread = the_thread;1117 interested_priority = the_thread->current_priority;1118 continue;1119 }1120 1121 /*1122 * Now we know both threads are blocked.1123 * If the interested thread is interruptible, then just use it.1124 */1125 1126 /* XXX need a new states macro */1127 if ( interested_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL )1128 continue;1129 1130 /*1131 * Now both threads are blocked and the interested thread is not1132 * interruptible.1133 * If the thread under consideration is interruptible by a signal,1134 * then it becomes the interested thread.1135 */1136 1137 /* XXX need a new states macro */1138 if ( the_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL ) {1139 interested_thread = the_thread;1140 interested_priority = the_thread->current_priority;1141 }1142 }1143 }1144 1145 if ( interested_thread ) {1146 the_thread = interested_thread;1147 goto process_it;1148 }1149 1150 /*1151 * OK so no threads were interested right now. It will be left on the1152 * global pending until a thread receives it. The global set of threads1153 * can change interest in this signal in one of the following ways:1154 *1155 * + a thread is created with the signal unblocked,1156 * + pthread_sigmask() unblocks the signal,1157 * + sigprocmask() unblocks the signal, OR1158 * + sigaction() which changes the handler to SIG_IGN.1159 */1160 1161 the_thread = NULL;1162 goto post_process_signal;1163 1164 /*1165 * We found a thread which was interested, so now we mark that this1166 * thread needs to do the post context switch extension so it can1167 * evaluate the signals pending.1168 */1169 1170 process_it:1171 1172 the_thread->do_post_task_switch_extension = TRUE;1173 1174 /*1175 * Returns TRUE if the signal was synchronously given to a thread1176 * blocked waiting for the signal.1177 */1178 1179 if ( _POSIX_signals_Unblock_thread( the_thread, sig, siginfo ) ) {1180 _Thread_Enable_dispatch();1181 return 0;1182 }1183 1184 post_process_signal:1185 1186 /*1187 * We may have woken up a thread but we definitely need to post the1188 * signal to the process wide information set.1189 */1190 1191 _POSIX_signals_Set_process_signals( mask );1192 1193 if ( _POSIX_signals_Vectors[ sig ].sa_flags == SA_SIGINFO ) {1194 1195 psiginfo = (POSIX_signals_Siginfo_node *)1196 _Chain_Get( &_POSIX_signals_Inactive_siginfo );1197 if ( !psiginfo )1198 set_errno_and_return_minus_one( EAGAIN );1199 1200 psiginfo->Info = *siginfo;1201 1202 _Chain_Append( &_POSIX_signals_Siginfo[ sig ], &psiginfo->Node );1203 }1204 1205 _Thread_Enable_dispatch();1206 return 0;1207 }1208 1209 /*PAGE1210 *1211 * 3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 681212 *1213 * NOTE: Behavior of kill() depends on _POSIX_SAVED_IDS.1214 */1215 1216 int kill(1217 pid_t pid,1218 int sig1219 )1220 {1221 return killinfo( pid, sig, NULL );1222 }1223 1224 /*1225 * _kill_r1226 *1227 * This is the Newlib dependent reentrant version of kill().1228 */1229 1230 #if defined(RTEMS_NEWLIB)1231 1232 #include <reent.h>1233 1234 int _kill_r(1235 struct _reent *ptr,1236 pid_t pid,1237 int sig1238 )1239 {1240 return kill( pid, sig );1241 }1242 #endif1243 1244 /*1245 * 3.3.9 Queue a Signal to a Process, P1003.1b-1993, p. 781246 */1247 1248 int sigqueue(1249 pid_t pid,1250 int signo,1251 const union sigval value1252 )1253 {1254 return killinfo( pid, signo, &value );1255 }1256 1257 /*1258 * 3.3.10 Send a Signal to a Thread, P1003.1c/D10, p. 431259 */1260 1261 int pthread_kill(1262 pthread_t thread,1263 int sig1264 )1265 {1266 POSIX_API_Control *api;1267 Thread_Control *the_thread;1268 Objects_Locations location;1269 1270 if ( sig && !is_valid_signo(sig) )1271 set_errno_and_return_minus_one( EINVAL );1272 1273 if ( _POSIX_signals_Vectors[ sig ].sa_flags == SA_SIGINFO )1274 set_errno_and_return_minus_one( ENOSYS );1275 1276 /*1277 * RTEMS does not support sending a siginfo signal to a specific thread.1278 */1279 1280 the_thread = _POSIX_Threads_Get( thread, &location );1281 switch ( location ) {1282 case OBJECTS_ERROR:1283 case OBJECTS_REMOTE:1284 set_errno_and_return_minus_one( ESRCH );1285 case OBJECTS_LOCAL:1286 /*1287 * If sig == 0 then just validate arguments1288 */1289 1290 api = the_thread->API_Extensions[ THREAD_API_POSIX ];1291 1292 if ( sig ) {1293 1294 if ( _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN ) {1295 _Thread_Enable_dispatch();1296 return 0;1297 }1298 1299 /* XXX critical section */1300 1301 api->signals_pending |= signo_to_mask( sig );1302 1303 (void) _POSIX_signals_Unblock_thread( the_thread, sig, NULL );1304 1305 the_thread->do_post_task_switch_extension = TRUE;1306 1307 if ( _ISR_Is_in_progress() && _Thread_Is_executing( the_thread ) )1308 _ISR_Signals_to_thread_executing = TRUE;1309 }1310 _Thread_Enable_dispatch();1311 return 0;1312 }1313 1314 return POSIX_BOTTOM_REACHED();1315 }1316 1317 /*1318 * 3.4.1 Schedule Alarm, P1003.1b-1993, p. 791319 */1320 1321 Watchdog_Control _POSIX_signals_Alarm_timer;1322 1323 unsigned int alarm(1324 unsigned int seconds1325 )1326 {1327 unsigned int remaining = 0;1328 Watchdog_Control *the_timer;1329 1330 the_timer = &_POSIX_signals_Alarm_timer;1331 1332 switch ( _Watchdog_Remove( the_timer ) ) {1333 case WATCHDOG_INACTIVE:1334 case WATCHDOG_BEING_INSERTED:1335 break;1336 1337 case WATCHDOG_ACTIVE:1338 case WATCHDOG_REMOVE_IT:1339 remaining = the_timer->initial -1340 (the_timer->stop_time - the_timer->start_time);1341 break;1342 }1343 1344 _Watchdog_Insert_seconds( the_timer, seconds );1345 1346 return remaining;1347 }1348 1349 /*1350 * 3.4.2 Suspend Process Execution, P1003.1b-1993, p. 811351 */1352 1353 int pause( void )1354 {1355 sigset_t all_signals;1356 int status;1357 1358 (void) sigfillset( &all_signals );1359 1360 status = sigtimedwait( &all_signals, NULL, NULL );1361 1362 return status;1363 }
Note: See TracChangeset
for help on using the changeset viewer.