1 //==========================================================================
5 // POSIX signal functions implementation
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 // Copyright (C) 2002 Nick Garnett
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38 // at http://sources.redhat.com/ecos/ecos-license/
39 // -------------------------------------------
40 //####ECOSGPLCOPYRIGHTEND####
41 //==========================================================================
42 //#####DESCRIPTIONBEGIN####
45 // Contributors: nickg
47 // Purpose: POSIX signal functions implementation
48 // Description: This file contains the implementation of the POSIX signal
53 //####DESCRIPTIONEND####
55 //==========================================================================
57 #include <pkgconf/posix.h>
59 #ifdef CYGPKG_POSIX_SIGNALS
61 #include <pkgconf/hal.h>
62 #include <pkgconf/kernel.h>
63 #include <pkgconf/isoinfra.h>
65 #include <cyg/kernel/ktypes.h> // base kernel types
66 #include <cyg/infra/cyg_trac.h> // tracing macros
67 #include <cyg/infra/cyg_ass.h> // assertion macros
69 #include "pprivate.h" // POSIX private header
71 #include <signal.h> // our header
73 #include <unistd.h> // _exit
75 #include <cyg/kernel/clock.hxx>
76 #include <cyg/kernel/thread.hxx>
77 #include <cyg/kernel/clock.inl>
78 #include <cyg/kernel/thread.inl>
80 // -------------------------------------------------------------------------
81 // Internal definitions
83 // Handle entry to a signal package function.
84 #define SIGNAL_ENTRY() CYG_REPORT_FUNCTYPE( "returning %d" );
86 // Do a signal package defined return. This requires the error code
87 // to be placed in errno, and if it is non-zero, -1 returned as the
88 // result of the function. This also gives us a place to put any
89 // generic tidyup handling needed for things like signal delivery and
91 #define SIGNAL_RETURN(err) \
94 if( err != 0 ) __retval = -1, errno = err; \
95 CYG_REPORT_RETVAL( __retval ); \
99 // Similarly for functions that have valid non-zero returns
100 #define SIGNAL_RETURN_VALUE(val) \
102 CYG_REPORT_RETVAL( val ); \
106 // Range check on a signal value.
107 #define SIGNAL_VALID(_sig_) (((_sig_) > 0) && ((_sig_) < ((int)sizeof(sigset_t)*8)))
109 //==========================================================================
110 // Signal management structures
112 typedef struct signal_info
114 struct signal_info *next; // link in list of pending signals
115 siginfo_t si; // siginfo to pass to handler
120 struct sigaction sa; // Sigaction defining what to do
121 signal_info *pending; // List of pending signals - this is
122 // a circular list with pending pointing
123 // to the tail element (or NULL if empty).
126 //==========================================================================
127 // Signal management variables
129 // Lock used to protect signal management structures
130 Cyg_Mutex signal_mutex CYGBLD_POSIX_INIT;
132 // Condition variable for all threads in sigsuspend() and sigwait()
134 Cyg_Condition_Variable CYGBLD_POSIX_INIT signal_sigwait( signal_mutex ) ;
136 // Global pending signal set
137 sigset_t sig_pending;
139 // Array controlling signal states
140 static signal_state sigstate[sizeof(sigset_t)*8];
142 // Array of available signal_info objects for queueing signals
143 static signal_info siginfo[SIGQUEUE_MAX];
145 // List of free signal_info objects
146 static signal_info *siginfo_next = NULL;
148 //==========================================================================
149 // Variables used to support alarm()
151 // Forward def of action function
152 static void sigalrm_action( Cyg_Alarm *alarm, CYG_ADDRWORD data );
154 // Kernel alarm object
155 static Cyg_Alarm CYGBLD_POSIX_INIT sigalrm_alarm( Cyg_Clock::real_time_clock, sigalrm_action, 0 ) ;
157 // Set true when alarm is armed
158 volatile cyg_bool sigalrm_armed = false;
160 // Set true when alarm has fired and is waiting to be delivered
161 volatile cyg_bool sigalrm_pending = false;
163 //==========================================================================
164 // Implementation functions.
165 // These are where the real work of the signal mechanism gets done.
167 externC void cyg_posix_signal_start()
169 // Chain all free signal_info objects together
170 for( int i = 0; i < SIGQUEUE_MAX; i++ )
172 siginfo[i].next = siginfo_next;
173 siginfo_next = &siginfo[i];
176 // initialize all signal actions to SIG_DFL
177 for ( unsigned int i=0; i<(sizeof(sigstate)/sizeof(signal_state)); i++ )
179 sigstate[i].sa.sa_handler = SIG_DFL;
182 // Clear the pending signal set
183 sigemptyset( &sig_pending );
186 // -------------------------------------------------------------------------
189 cyg_bool cyg_sigqueue( const struct sigevent *sev, int code,
190 pthread_info *thread )
192 if( sev->sigev_notify == SIGEV_NONE )
198 if( sev->sigev_notify == SIGEV_THREAD )
200 // create a thread to run the notification
202 // FIXME: implement SIGEV_THREAD
206 // Otherwise we must have a SIGEV_SIGNAL notification
208 // Find out whether the current thread already has the mutex
209 // locked. This is a distinct possibility if this function is
210 // called from the ASR while exiting the signal_sigwait condvar in
211 // pause() and sigtimedwait().
213 pthread_info *self = pthread_self_info();
214 cyg_bool locked = (self != NULL) && (signal_mutex.get_owner() == self->thread);
216 // Lock the mutex only if we do not already own it
217 if( !locked ) signal_mutex.lock();
219 int signo = sev->sigev_signo;
220 signal_state *ss = &sigstate[signo];
222 if( ss->sa.sa_flags & SA_SIGINFO )
224 // We have a queuable signal, allocate a signal_info
225 // object and add it to the queue.
227 if( siginfo_next == NULL )
229 if( !locked ) signal_mutex.unlock();
233 signal_info *si = siginfo_next;
234 siginfo_next = si->next;
236 si->si.si_signo = signo;
237 si->si.si_code = code;
238 si->si.si_value = sev->sigev_value;
240 if( ss->pending == NULL )
246 si->next = ss->pending->next;
247 ss->pending->next = si;
252 // else A non-queuable signal, just set it pending
256 sigaddset( &thread->sigpending, signo );
257 // just wake the thread up now if it's blocked somewhere
258 if ((thread->sigpending & ~thread->sigmask) != 0)
260 thread->thread->set_asr_pending();
261 thread->thread->release();
266 sigaddset( &sig_pending, signo );
267 // Wake up any threads in sigsuspend() and sigwait().
268 if (!signal_sigwait.get_queue()->empty())
270 signal_sigwait.broadcast();
274 cyg_posix_pthread_release_thread( &sig_pending );
278 if( !locked ) signal_mutex.unlock();
283 // -------------------------------------------------------------------------
284 // Deliver any pending unblocked signals to the current thread
285 // Returns true if a signal handler was called.
287 cyg_bool cyg_deliver_signals()
289 cyg_bool res = false;
291 pthread_info *self = pthread_self_info();
293 // If there is no pthread_info pointer for this thread then
294 // it is not a POSIX thread and cannot have signals delivered
297 if( self == NULL ) return false;
299 // If there are no pending signals our work is done
300 if( sig_pending == 0 && self->sigpending == 0 )
303 // If there are no unmasked pending signals our
305 if( ((sig_pending | self->sigpending) & ~self->sigmask) == 0 )
308 // As with cyg_sigqueue(), this function can get called from an
309 // ASR where the signal_mutex is already locked. Check here to
310 // avoid relocking...
312 cyg_bool locked = signal_mutex.get_owner() == self->thread;
314 if( !locked ) signal_mutex.lock();
318 // Since a signal handler may raise another signal, or unmask an existing
319 // signal, we loop here while there are no more unblocked signals pending.
320 while( (todo = ((sig_pending | self->sigpending) & ~self->sigmask)) != 0 )
322 // Here todo is a mask of the signals available for delivery
326 // This prioritizes low numbered signals
327 HAL_LSBIT_INDEX( signo, todo );
329 signal_state *ss = &sigstate[signo];
330 sigset_t sigbit = 1L<<signo;
332 if( ss->sa.sa_handler != SIG_IGN )
334 sigset_t oldmask = self->sigmask;
337 if(ss->pending != NULL)
339 // There is a queued signal. Dequeue it and copy the
340 // siginfo object to a local copy.
342 signal_info *si = ss->pending->next;
344 // Make a local copy of the siginfo object
347 // Remove the head signal_info object from the
349 if( ss->pending == si )
352 ss->pending->next = si->next;
354 // Return it to the free list
355 si->next = siginfo_next;
360 // There are no signals queued. Set up the local siginfo_t
361 // object with default values.
363 lsi.si_signo = signo;
364 lsi.si_code = SI_USER;
365 lsi.si_value.sival_int = 0;
368 // Clear the bit from the pending masks. If the pending
369 // queue is not empty, leave the bits set, otherwise clear
370 // them. Do this now so that if the signal handler longjumps
371 // out, the signal subsystem is clean.
373 if( ss->pending == NULL )
375 // Clear the bit in both masks regardless of which
376 // one it actually came from. This is cheaper than
377 // trying to find out.
378 sig_pending &= ~sigbit;
379 self->sigpending &= ~sigbit;
382 // Add the mask set and the signal itself to the
383 // mask while we call the signal handler
384 self->sigmask = oldmask | ss->sa.sa_mask | sigbit;
386 // Unlock now so that a longjmp out of the handler
387 // does the right thing. We do this even if we did not
388 // lock the mutex since it will only recently have been
389 // relocked and thus all data is still consistent.
391 signal_mutex.unlock();
393 if( ss->sa.sa_flags & SA_SIGINFO )
395 // A sigaction delivery
396 CYG_CHECK_FUNC_PTR( ss->sa.sa_sigaction,
397 "Bad sa_sigaction signal handler" );
398 ss->sa.sa_sigaction( signo, &lsi, NULL );
400 else if ( ss->sa.sa_handler == SIG_DFL )
403 "Unhandled POSIX signal: sig=%d, mask=%08x",
406 // FIXME: should do something better here
410 CYG_FAIL("Unhandled POSIX signal");
414 // This is a standard signal delivery.
415 CYG_CHECK_FUNC_PTR( ss->sa.sa_handler,
416 "Bad sa_handler signal handler" );
418 ss->sa.sa_handler( signo );
424 // Restore original signal mask
425 self->sigmask = oldmask;
427 // return that we have handled a signal
432 if( !locked ) signal_mutex.unlock();
437 // -------------------------------------------------------------------------
438 // Utility routine to signal any threads waiting in sigwait*().
440 void cyg_posix_signal_sigwait()
442 signal_sigwait.broadcast();
445 // -------------------------------------------------------------------------
446 // Action routine called from kernel alarm to deliver the SIGALRM signal.
447 // We cannot call any signal delivery functions directly here, so we simply
448 // set a flag and schedule an ASR to be called.
450 static void sigalrm_action( Cyg_Alarm *alarm, CYG_ADDRWORD data )
453 sigalrm_armed = false;
454 sigalrm_pending = true;
455 sigemptyset( &mask );
456 sigaddset( &mask, SIGALRM );
457 // Wake up any threads in sigsuspend() and sigwait() in case they
458 // are waiting for an alarm, and would have SIGALRM masked
459 signal_sigwait.broadcast();
461 cyg_posix_pthread_release_thread( &mask );
464 // -------------------------------------------------------------------------
465 // Check for SIGALRMs. This is called from the ASR and sigtimedwait()
466 // as alarms need to be handled as a special case.
468 static __inline__ void check_sigalarm(void)
470 // If there is a pending SIGALRM, generate it
471 if( sigalrm_pending )
473 sigalrm_pending = false;
477 sev.sigev_notify = SIGEV_SIGNAL;
478 sev.sigev_signo = SIGALRM;
479 sev.sigev_value.sival_int = 0;
481 // generate the signal
482 cyg_sigqueue( &sev, SI_USER );
486 // -------------------------------------------------------------------------
487 // signal ASR function. This is called from the general POSIX ASR to
488 // deal with any signal related issues.
490 externC void cyg_posix_signal_asr(pthread_info *self)
494 // Now call cyg_deliver_signals() to see if we can
495 // handle any signals now.
497 cyg_deliver_signals();
500 //==========================================================================
501 // Per-thread initialization and destruction
503 externC void cyg_posix_thread_siginit( pthread_info *thread,
504 pthread_info *parentthread )
506 // Clear out signal masks
507 sigemptyset( &thread->sigpending );
508 // but threads inherit signal masks
509 if ( NULL == parentthread )
510 sigemptyset( &thread->sigmask );
512 thread->sigmask = parentthread->sigmask;
514 cyg_pthread_exception_init( thread );
517 externC void cyg_posix_thread_sigdestroy( pthread_info *thread )
519 cyg_pthread_exception_destroy( thread );
522 //==========================================================================
523 // Functions to generate signals
525 // -------------------------------------------------------------------------
526 // Deliver sig to a process.
527 // eCos only supports the value 0 for pid.
529 externC int kill (pid_t pid, int sig)
533 if( !SIGNAL_VALID(sig) )
534 SIGNAL_RETURN(EINVAL);
537 SIGNAL_RETURN(ESRCH);
541 sev.sigev_notify = SIGEV_SIGNAL;
542 sev.sigev_signo = sig;
543 sev.sigev_value.sival_int = 0;
545 cyg_sigqueue( &sev, SI_USER );
547 cyg_deliver_signals();
552 // -------------------------------------------------------------------------
554 externC int pthread_kill (pthread_t threadid, int sig)
558 if( !SIGNAL_VALID(sig) )
559 SIGNAL_RETURN(EINVAL);
563 pthread_info *thread = pthread_info_id(threadid);
566 SIGNAL_RETURN(ESRCH);
568 sev.sigev_notify = SIGEV_SIGNAL;
569 sev.sigev_signo = sig;
570 sev.sigev_value.sival_int = 0;
572 cyg_sigqueue( &sev, SI_USER, thread );
574 cyg_deliver_signals();
579 //==========================================================================
580 // Functions to catch signals
582 // -------------------------------------------------------------------------
583 // Install signal handler for sig.
585 externC int sigaction (int sig, const struct sigaction *act,
586 struct sigaction *oact)
590 if( !SIGNAL_VALID(sig) )
591 SIGNAL_RETURN(EINVAL);
593 signal_state *ss = &sigstate[sig];
602 if( ss->sa.sa_handler == SIG_IGN )
604 // Setting the handler to SIG_IGN causes any pending
605 // signals to be discarded and any queued values to also
608 pthread_info *self = pthread_self_info();
609 sigset_t sigbit = 1<<sig;
611 if( (sig_pending | self->sigpending) & sigbit )
613 // This signal is pending, clear it
615 sig_pending &= ~sigbit;
616 self->sigpending &= ~sigbit;
618 // Clean out any queued signal_info objects
619 while( ss->pending != NULL )
621 signal_info *si = ss->pending->next;
623 // Remove the head signal_info object from the
625 if( ss->pending == si )
628 ss->pending->next = si->next;
630 // Return it to the free list
631 si->next = siginfo_next;
637 cyg_deliver_signals();
639 signal_mutex.unlock();
645 // -------------------------------------------------------------------------
646 // Queue signal to process with value.
648 externC int sigqueue (pid_t pid, int sig, const union sigval value)
652 if( !SIGNAL_VALID(sig) )
653 SIGNAL_RETURN(EINVAL);
657 sev.sigev_notify = SIGEV_SIGNAL;
658 sev.sigev_signo = sig;
659 sev.sigev_value = value;
661 cyg_sigqueue( &sev, SI_QUEUE );
663 cyg_deliver_signals();
668 //==========================================================================
669 // Functions to deal with current blocked and pending masks
671 // -------------------------------------------------------------------------
672 // Set process blocked signal mask
673 // Map this onto pthread_sigmask().
675 externC int sigprocmask (int how, const sigset_t *set, sigset_t *oset)
677 return pthread_sigmask( how, set, oset);
681 // -------------------------------------------------------------------------
682 // Set calling thread's blocked signal mask
684 externC int pthread_sigmask (int how, const sigset_t *set, sigset_t *oset)
690 pthread_info *self = pthread_self_info();
693 *oset = self->sigmask;
700 self->sigmask |= *set;
704 self->sigmask &= ~*set;
708 self->sigmask = *set;
717 // Deliver any newly unblocked signals
718 cyg_deliver_signals();
723 // -------------------------------------------------------------------------
724 // Exported routine to set calling thread's blocked signal mask
726 // Optionally set and return the current thread's signal mask. This is
727 // exported to other packages so that they can manipulate the signal
728 // mask without necessarily having them delivered (as calling
729 // pthread_sigmask() would). Signals can be delivered by calling
730 // cyg_posix_deliver_signals().
732 externC void cyg_pthread_sigmask_set (const sigset_t *set, sigset_t *oset)
734 pthread_info *self = pthread_self_info();
739 *oset = self->sigmask;
742 self->sigmask = *set;
746 // -------------------------------------------------------------------------
747 // Exported routine to test for any pending signals.
749 // This routine tests for any pending undelivered, unmasked
750 // signals. If there are any it returns true. This is exported to
751 // other packages, such as FILEIO, so that they can detect whether to
752 // abort a current API call with an EINTR result.
754 externC cyg_bool cyg_posix_sigpending(void)
756 pthread_info *self = pthread_self_info();
761 return ( ((sig_pending | self->sigpending) & ~self->sigmask) != 0 );
764 // -------------------------------------------------------------------------
765 // Exported routine to deliver selected signals
767 // This routine optionally sets the given mask and then tries to
768 // deliver any pending signals that have been unmasked. This is
769 // exported to other packages so that they can cause signals to be
770 // delivered at controlled points during execution.
772 externC void cyg_posix_deliver_signals( const sigset_t *mask )
775 pthread_info *self = pthread_self_info();
781 oldmask = self->sigmask;
782 self->sigmask = *mask;
785 oldmask = 0; // silence warning
787 cyg_deliver_signals();
790 self->sigmask = oldmask;
794 // -------------------------------------------------------------------------
795 // Get set of pending signals for this process
797 externC int sigpending (sigset_t *set)
802 SIGNAL_RETURN(EINVAL);
804 pthread_info *self = pthread_self_info();
806 *set = self->sigpending | sig_pending;
812 //==========================================================================
813 // Wait for or accept signals
815 // -------------------------------------------------------------------------
816 // Block signals in set and wait for a signal
818 externC int sigsuspend (const sigset_t *set)
822 pthread_info *self = pthread_self_info();
826 // Save the old mask and set the current mask to
828 sigset_t old = self->sigmask;
829 self->sigmask = *set;
831 // Loop until a signal gets delivered
832 while( !cyg_deliver_signals() )
833 signal_sigwait.wait();
837 signal_mutex.unlock();
839 SIGNAL_RETURN(EINTR);
843 // -------------------------------------------------------------------------
844 // Wait for a signal in set to arrive
845 // Implement this as a variant on sigtimedwait().
847 externC int sigwait (const sigset_t *set, int *sig)
853 int ret = sigtimedwait( set, &info, NULL );
856 SIGNAL_RETURN(errno);
863 // -------------------------------------------------------------------------
864 // Do the same as sigwait() except return a siginfo_t object too.
865 // Implement this as a variant on sigtimedwait().
867 externC int sigwaitinfo (const sigset_t *set, siginfo_t *info)
871 int ret = sigtimedwait( set, info, NULL );
873 SIGNAL_RETURN_VALUE(ret);
876 // -------------------------------------------------------------------------
877 // Wait either for a signal in the given set to become pending, or
878 // for the timeout to expire. If timeout is NULL, wait for ever.
880 externC int sigtimedwait (const sigset_t *set, siginfo_t *info,
881 const struct timespec *timeout)
885 // check for cancellation first.
886 pthread_testcancel();
889 cyg_tick_count ticks;
891 if( timeout == NULL ) ticks = 0;
892 else ticks = cyg_timespec_to_ticks( timeout ) +
893 Cyg_Clock::real_time_clock->current_value();
895 pthread_info *self = pthread_self_info();
901 // Wait for a signal in the set to become pending
902 while( (todo = (*set & (sig_pending | self->sigpending))) == 0 )
904 // If timeout is not NULL, do a timed wait on the
905 // sigwait condition variable. If it is NULL - wait
906 // until we are woken.
909 if( ticks == 0 || !signal_sigwait.wait(ticks) )
911 // If the timeout is actually zero, or we have waited and
912 // timed out, then we must quit with an error.
918 if ( !signal_sigwait.wait() ) {
919 // check we weren't woken up forcibly (e.g. to be cancelled)
920 // if so, pretend it's an error
926 // Special case check for SIGALRM since the fact SIGALRM is masked
927 // would have prevented it being set pending in the alarm handler.
930 cyg_posix_timer_asr(self);
935 // There is a signal in the set that is pending: deliver
936 // it. todo contains a mask of all the signals that could be
937 // delivered now, but we only want to deliver one of them.
941 // Select the lowest numbered signal from the todo mask
942 HAL_LSBIT_INDEX( signo, todo );
944 signal_state *ss = &sigstate[signo];
945 sigset_t sigbit = 1L<<signo;
947 if( (ss->sa.sa_flags & SA_SIGINFO) && (ss->pending != NULL) )
949 // If the SA_SIGINFO bit is set, then there
950 // will be a signal_info object queued on the
953 signal_info *si = ss->pending->next;
956 // Remove the head signal_info object from the
958 if( ss->pending == si )
961 ss->pending->next = si->next;
963 si->next = siginfo_next;
969 // Not a queued signal, or there is no signal_info object
970 // on the pending queue: fill in info structure with
972 info->si_signo = signo;
973 info->si_code = SI_USER;
974 info->si_value.sival_int = 0;
977 // Clear the bit from the pending masks. If the pending
978 // queue is not empty, leave the bits set, otherwise clear
981 if( ss->pending == NULL )
983 // Clear the bit in both masks regardless of which
984 // one it actually came from. This is cheaper than
985 // trying to find out.
986 sig_pending &= ~sigbit;
987 self->sigpending &= ~sigbit;
993 signal_mutex.unlock();
995 pthread_testcancel();
1000 SIGNAL_RETURN_VALUE( info->si_signo );
1003 //==========================================================================
1004 // alarm, pause and sleep
1006 // -------------------------------------------------------------------------
1007 // Generate SIGALRM after some number of seconds
1009 externC unsigned int alarm( unsigned int seconds )
1013 cyg_tick_count trigger, interval;
1017 signal_mutex.lock();
1021 sigalrm_alarm.disable();
1023 sigalrm_alarm.get_times( &trigger, &interval );
1025 // Convert trigger time back to interval
1026 trigger -= Cyg_Clock::real_time_clock->current_value();
1028 cyg_ticks_to_timespec( trigger, &tv );
1032 sigalrm_armed = false;
1037 // Here we know that the sigalrm_alarm is unarmed, set it up
1038 // to trigger in the required number of seconds.
1040 tv.tv_sec = seconds;
1043 trigger = cyg_timespec_to_ticks( &tv );
1045 // Convert trigger interval to absolute time
1046 trigger += Cyg_Clock::real_time_clock->current_value();
1048 sigalrm_alarm.initialize( trigger, 0 );
1050 sigalrm_armed = true;
1053 signal_mutex.unlock();
1055 CYG_REPORT_RETVAL(res);
1060 // -------------------------------------------------------------------------
1061 // Wait for a signal to be delivered.
1063 externC int pause( void )
1067 signal_mutex.lock();
1069 // Check for any pending signals that can be delivered and
1070 // if there are none, wait for a signal to be generated
1071 if( !cyg_deliver_signals() )
1072 signal_sigwait.wait();
1074 // Now check again for some signals to deliver
1075 cyg_deliver_signals();
1077 signal_mutex.unlock();
1079 SIGNAL_RETURN(EINTR);
1082 //==========================================================================
1085 // -------------------------------------------------------------------------
1086 // Clear all signals from set.
1088 externC int sigemptyset (sigset_t *set)
1098 // -------------------------------------------------------------------------
1099 // Set all signals in set.
1101 externC int sigfillset (sigset_t *set)
1111 // -------------------------------------------------------------------------
1112 // Add signo to set.
1114 externC int sigaddset (sigset_t *set, int signo)
1120 if( !SIGNAL_VALID(signo) )
1122 else *set |= 1<<signo;
1128 // -------------------------------------------------------------------------
1129 // Remove signo from set.
1131 externC int sigdelset (sigset_t *set, int signo)
1137 if( !SIGNAL_VALID(signo) )
1139 else *set &= ~(1<<signo);
1145 // -------------------------------------------------------------------------
1146 // Test whether signo is in set
1148 externC int sigismember (const sigset_t *set, int signo)
1154 if( !SIGNAL_VALID(signo) )
1155 SIGNAL_RETURN(EINVAL);
1157 if( *set & (1<<signo) ) ret = 1;
1159 CYG_REPORT_RETVAL( ret );
1163 //==========================================================================
1164 // ISO C compatibility functions
1166 // -------------------------------------------------------------------------
1167 // Installs a new signal handler for the specified signal, and returns
1170 externC sa_sighandler_t signal(int sig, sa_sighandler_t handler)
1175 sa_sighandler_t ret;
1176 struct sigaction new_action;
1177 struct sigaction old_action;
1179 sigemptyset( &new_action.sa_mask );
1180 new_action.sa_flags = 0;
1181 new_action.sa_handler = handler;
1183 err = sigaction( sig, &new_action, &old_action );
1187 else ret = old_action.sa_handler;
1189 CYG_REPORT_RETVAL( ret );
1193 // -------------------------------------------------------------------------
1194 // raise() - ISO C 7.7.2 //
1196 // Raises the signal, which will cause the current signal handler for
1197 // that signal to be called
1199 externC int raise(int sig)
1201 return kill( 0, sig );
1204 // -------------------------------------------------------------------------
1206 // Restores signal mask and longjumps.
1208 __externC void siglongjmp( sigjmp_buf env, int val )
1210 CYG_REPORT_FUNCNAME( "siglongjmp" );
1211 CYG_REPORT_FUNCARG2( "&env=%08x, val=%d", &env, val );
1213 // ISO C says that if we are passed val == 0, then we change it to 1
1217 if( env[0].__savemask )
1218 pthread_sigmask( SIG_SETMASK, &env[0].__sigsavemask, NULL );
1220 HAL_REORDER_BARRIER(); // prevent any chance of optimisation re-ordering
1221 hal_longjmp( env[0].__jmp_buf, val );
1222 HAL_REORDER_BARRIER(); // prevent any chance of optimisation re-ordering
1224 #ifdef CYGDBG_USE_ASSERTS
1225 CYG_ASSERT( 0, "siglongjmp should not have reached this point!" );
1228 CYG_EMPTY_STATEMENT;
1233 #endif // ifdef CYGPKG_POSIX_SIGNALS
1235 // -------------------------------------------------------------------------