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
13 // Copyright (C) 2004 eCosCentric Ltd.
15 // eCos is free software; you can redistribute it and/or modify it under
16 // the terms of the GNU General Public License as published by the Free
17 // Software Foundation; either version 2 or (at your option) any later version.
19 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
20 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 // You should have received a copy of the GNU General Public License along
25 // with eCos; if not, write to the Free Software Foundation, Inc.,
26 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
28 // As a special exception, if other files instantiate templates or use macros
29 // or inline functions from this file, or you compile this file and link it
30 // with other works to produce a work based on this file, this file does not
31 // by itself cause the resulting work to be covered by the GNU General Public
32 // License. However the source code for this file must still be made available
33 // in accordance with section (3) of the GNU General Public License.
35 // This exception does not invalidate any other reasons why a work based on
36 // this file might be covered by the GNU General Public License.
38 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
39 // at http://sources.redhat.com/ecos/ecos-license/
40 // -------------------------------------------
41 //####ECOSGPLCOPYRIGHTEND####
42 //==========================================================================
43 //#####DESCRIPTIONBEGIN####
46 // Contributors: nickg
48 // Purpose: POSIX signal functions implementation
49 // Description: This file contains the implementation of the POSIX signal
54 //####DESCRIPTIONEND####
56 //==========================================================================
58 #include <pkgconf/posix.h>
60 #ifdef CYGPKG_POSIX_SIGNALS
62 #include <pkgconf/hal.h>
63 #include <pkgconf/kernel.h>
64 #include <pkgconf/isoinfra.h>
66 #include <cyg/kernel/ktypes.h> // base kernel types
67 #include <cyg/infra/cyg_trac.h> // tracing macros
68 #include <cyg/infra/cyg_ass.h> // assertion macros
70 #include "pprivate.h" // POSIX private header
72 #include <signal.h> // our header
74 #include <unistd.h> // _exit
76 #include <cyg/kernel/clock.hxx>
77 #include <cyg/kernel/thread.hxx>
78 #include <cyg/kernel/clock.inl>
79 #include <cyg/kernel/thread.inl>
81 // -------------------------------------------------------------------------
82 // Internal definitions
84 // Handle entry to a signal package function.
85 #define SIGNAL_ENTRY() CYG_REPORT_FUNCTYPE( "returning %d" );
87 // Do a signal package defined return. This requires the error code
88 // to be placed in errno, and if it is non-zero, -1 returned as the
89 // result of the function. This also gives us a place to put any
90 // generic tidyup handling needed for things like signal delivery and
92 #define SIGNAL_RETURN(err) \
95 if( err != 0 ) __retval = -1, errno = err; \
96 CYG_REPORT_RETVAL( __retval ); \
100 // Similarly for functions that have valid non-zero returns
101 #define SIGNAL_RETURN_VALUE(val) \
103 CYG_REPORT_RETVAL( val ); \
107 // Range check on a signal value.
108 #define SIGNAL_VALID(_sig_) (((_sig_) > 0) && ((_sig_) < ((int)sizeof(sigset_t)*8)))
110 //==========================================================================
111 // Signal management structures
113 typedef struct signal_info
115 struct signal_info *next; // link in list of pending signals
116 siginfo_t si; // siginfo to pass to handler
121 struct sigaction sa; // Sigaction defining what to do
122 signal_info *pending; // List of pending signals - this is
123 // a circular list with pending pointing
124 // to the tail element (or NULL if empty).
127 //==========================================================================
128 // Signal management variables
130 // Lock used to protect signal management structures
131 Cyg_Mutex signal_mutex CYGBLD_POSIX_INIT;
133 // Condition variable for all threads in sigsuspend() and sigwait()
135 Cyg_Condition_Variable CYGBLD_POSIX_INIT signal_sigwait( signal_mutex ) ;
137 // Global pending signal set
138 sigset_t sig_pending;
140 // Array controlling signal states
141 static signal_state sigstate[sizeof(sigset_t)*8];
143 // Array of available signal_info objects for queueing signals
144 static signal_info siginfo[SIGQUEUE_MAX];
146 // List of free signal_info objects
147 static signal_info *siginfo_next = NULL;
149 //==========================================================================
150 // Variables used to support alarm()
152 // Forward def of action function
153 static void sigalrm_action( Cyg_Alarm *alarm, CYG_ADDRWORD data );
155 // Kernel alarm object
156 static Cyg_Alarm CYGBLD_POSIX_INIT sigalrm_alarm( Cyg_Clock::real_time_clock, sigalrm_action, 0 ) ;
158 // Set true when alarm is armed
159 volatile cyg_bool sigalrm_armed = false;
161 // Set true when alarm has fired and is waiting to be delivered
162 volatile cyg_bool sigalrm_pending = false;
164 //==========================================================================
165 // Implementation functions.
166 // These are where the real work of the signal mechanism gets done.
168 externC void cyg_posix_signal_start()
170 // Chain all free signal_info objects together
171 for( int i = 0; i < SIGQUEUE_MAX; i++ )
173 siginfo[i].next = siginfo_next;
174 siginfo_next = &siginfo[i];
177 // initialize all signal actions to SIG_DFL
178 for ( unsigned int i=0; i<(sizeof(sigstate)/sizeof(signal_state)); i++ )
180 sigstate[i].sa.sa_handler = SIG_DFL;
183 // Clear the pending signal set
184 sigemptyset( &sig_pending );
187 // -------------------------------------------------------------------------
190 cyg_bool cyg_sigqueue( const struct sigevent *sev, int code,
191 pthread_info *thread )
193 if( sev->sigev_notify == SIGEV_NONE )
199 if( sev->sigev_notify == SIGEV_THREAD )
201 // create a thread to run the notification
203 // FIXME: implement SIGEV_THREAD
207 // Otherwise we must have a SIGEV_SIGNAL notification
209 // Find out whether the current thread already has the mutex
210 // locked. This is a distinct possibility if this function is
211 // called from the ASR while exiting the signal_sigwait condvar in
212 // pause() and sigtimedwait().
214 pthread_info *self = pthread_self_info();
215 cyg_bool locked = (self != NULL) && (signal_mutex.get_owner() == self->thread);
217 // Lock the mutex only if we do not already own it
218 if( !locked ) signal_mutex.lock();
220 int signo = sev->sigev_signo;
221 signal_state *ss = &sigstate[signo];
223 if( ss->sa.sa_flags & SA_SIGINFO )
225 // We have a queuable signal, allocate a signal_info
226 // object and add it to the queue.
228 if( siginfo_next == NULL )
230 if( !locked ) signal_mutex.unlock();
234 signal_info *si = siginfo_next;
235 siginfo_next = si->next;
237 si->si.si_signo = signo;
238 si->si.si_code = code;
239 si->si.si_value = sev->sigev_value;
241 if( ss->pending == NULL )
247 si->next = ss->pending->next;
248 ss->pending->next = si;
253 // else A non-queuable signal, just set it pending
257 sigaddset( &thread->sigpending, signo );
258 // just wake the thread up now if it's blocked somewhere
259 if ((thread->sigpending & ~thread->sigmask) != 0)
261 thread->thread->set_asr_pending();
262 thread->thread->release();
267 sigaddset( &sig_pending, signo );
268 // Wake up any threads in sigsuspend() and sigwait().
269 if (!signal_sigwait.get_queue()->empty())
271 signal_sigwait.broadcast();
275 cyg_posix_pthread_release_thread( &sig_pending );
279 if( !locked ) signal_mutex.unlock();
284 // -------------------------------------------------------------------------
285 // Deliver any pending unblocked signals to the current thread
286 // Returns true if a signal handler was called.
288 cyg_bool cyg_deliver_signals()
290 cyg_bool res = false;
292 pthread_info *self = pthread_self_info();
294 // If there is no pthread_info pointer for this thread then
295 // it is not a POSIX thread and cannot have signals delivered
298 if( self == NULL ) return false;
300 // If there are no pending signals our work is done
301 if( sig_pending == 0 && self->sigpending == 0 )
304 // If there are no unmasked pending signals our
306 if( ((sig_pending | self->sigpending) & ~self->sigmask) == 0 )
309 // As with cyg_sigqueue(), this function can get called from an
310 // ASR where the signal_mutex is already locked. Check here to
311 // avoid relocking...
313 cyg_bool locked = signal_mutex.get_owner() == self->thread;
315 if( !locked ) signal_mutex.lock();
319 // Since a signal handler may raise another signal, or unmask an existing
320 // signal, we loop here while there are no more unblocked signals pending.
321 while( (todo = ((sig_pending | self->sigpending) & ~self->sigmask)) != 0 )
323 // Here todo is a mask of the signals available for delivery
327 // This prioritizes low numbered signals
328 HAL_LSBIT_INDEX( signo, todo );
330 signal_state *ss = &sigstate[signo];
331 sigset_t sigbit = 1L<<signo;
333 if( ss->sa.sa_handler != SIG_IGN )
335 sigset_t oldmask = self->sigmask;
338 if(ss->pending != NULL)
340 // There is a queued signal. Dequeue it and copy the
341 // siginfo object to a local copy.
343 signal_info *si = ss->pending->next;
345 // Make a local copy of the siginfo object
348 // Remove the head signal_info object from the
350 if( ss->pending == si )
353 ss->pending->next = si->next;
355 // Return it to the free list
356 si->next = siginfo_next;
361 // There are no signals queued. Set up the local siginfo_t
362 // object with default values.
364 lsi.si_signo = signo;
365 lsi.si_code = SI_USER;
366 lsi.si_value.sival_int = 0;
369 // Clear the bit from the pending masks. If the pending
370 // queue is not empty, leave the bits set, otherwise clear
371 // them. Do this now so that if the signal handler longjumps
372 // out, the signal subsystem is clean.
374 if( ss->pending == NULL )
376 // Clear the bit in both masks regardless of which
377 // one it actually came from. This is cheaper than
378 // trying to find out.
379 sig_pending &= ~sigbit;
380 self->sigpending &= ~sigbit;
383 // Add the mask set and the signal itself to the
384 // mask while we call the signal handler
385 self->sigmask = oldmask | ss->sa.sa_mask | sigbit;
387 // Unlock now so that a longjmp out of the handler
388 // does the right thing. We do this even if we did not
389 // lock the mutex since it will only recently have been
390 // relocked and thus all data is still consistent.
392 signal_mutex.unlock();
394 if( ss->sa.sa_flags & SA_SIGINFO )
396 // A sigaction delivery
397 CYG_CHECK_FUNC_PTR( ss->sa.sa_sigaction,
398 "Bad sa_sigaction signal handler" );
399 ss->sa.sa_sigaction( signo, &lsi, NULL );
401 else if ( ss->sa.sa_handler == SIG_DFL )
404 "Unhandled POSIX signal: sig=%d, mask=%08x",
407 // FIXME: should do something better here
411 CYG_FAIL("Unhandled POSIX signal");
415 // This is a standard signal delivery.
416 CYG_CHECK_FUNC_PTR( ss->sa.sa_handler,
417 "Bad sa_handler signal handler" );
419 ss->sa.sa_handler( signo );
425 // Restore original signal mask
426 self->sigmask = oldmask;
428 // return that we have handled a signal
433 if( !locked ) signal_mutex.unlock();
438 // -------------------------------------------------------------------------
439 // Utility routine to signal any threads waiting in sigwait*().
441 void cyg_posix_signal_sigwait()
443 signal_sigwait.broadcast();
446 // -------------------------------------------------------------------------
447 // Action routine called from kernel alarm to deliver the SIGALRM signal.
448 // We cannot call any signal delivery functions directly here, so we simply
449 // set a flag and schedule an ASR to be called.
451 static void sigalrm_action( Cyg_Alarm *alarm, CYG_ADDRWORD data )
454 sigalrm_armed = false;
455 sigalrm_pending = true;
456 sigemptyset( &mask );
457 sigaddset( &mask, SIGALRM );
458 // Wake up any threads in sigsuspend() and sigwait() in case they
459 // are waiting for an alarm, and would have SIGALRM masked
460 signal_sigwait.broadcast();
462 cyg_posix_pthread_release_thread( &mask );
465 // -------------------------------------------------------------------------
466 // Check for SIGALRMs. This is called from the ASR and sigtimedwait()
467 // as alarms need to be handled as a special case.
469 static __inline__ void check_sigalarm(void)
471 // If there is a pending SIGALRM, generate it
472 if( sigalrm_pending )
474 sigalrm_pending = false;
478 sev.sigev_notify = SIGEV_SIGNAL;
479 sev.sigev_signo = SIGALRM;
480 sev.sigev_value.sival_int = 0;
482 // generate the signal
483 cyg_sigqueue( &sev, SI_USER );
487 // -------------------------------------------------------------------------
488 // signal ASR function. This is called from the general POSIX ASR to
489 // deal with any signal related issues.
491 externC void cyg_posix_signal_asr(pthread_info *self)
495 // Now call cyg_deliver_signals() to see if we can
496 // handle any signals now.
498 cyg_deliver_signals();
501 //==========================================================================
502 // Per-thread initialization and destruction
504 externC void cyg_posix_thread_siginit( pthread_info *thread,
505 pthread_info *parentthread )
507 // Clear out signal masks
508 sigemptyset( &thread->sigpending );
509 // but threads inherit signal masks
510 if ( NULL == parentthread )
511 sigemptyset( &thread->sigmask );
513 thread->sigmask = parentthread->sigmask;
515 cyg_pthread_exception_init( thread );
518 externC void cyg_posix_thread_sigdestroy( pthread_info *thread )
520 cyg_pthread_exception_destroy( thread );
523 //==========================================================================
524 // Functions to generate signals
526 // -------------------------------------------------------------------------
527 // Deliver sig to a process.
528 // eCos only supports the value 0 for pid.
530 externC int kill (pid_t pid, int sig)
534 if( !SIGNAL_VALID(sig) )
535 SIGNAL_RETURN(EINVAL);
538 SIGNAL_RETURN(ESRCH);
542 sev.sigev_notify = SIGEV_SIGNAL;
543 sev.sigev_signo = sig;
544 sev.sigev_value.sival_int = 0;
546 cyg_sigqueue( &sev, SI_USER );
548 cyg_deliver_signals();
553 // -------------------------------------------------------------------------
555 externC int pthread_kill (pthread_t threadid, int sig)
559 if( !SIGNAL_VALID(sig) )
560 SIGNAL_RETURN(EINVAL);
564 pthread_info *thread = pthread_info_id(threadid);
567 SIGNAL_RETURN(ESRCH);
569 sev.sigev_notify = SIGEV_SIGNAL;
570 sev.sigev_signo = sig;
571 sev.sigev_value.sival_int = 0;
573 cyg_sigqueue( &sev, SI_USER, thread );
575 cyg_deliver_signals();
580 //==========================================================================
581 // Functions to catch signals
583 // -------------------------------------------------------------------------
584 // Install signal handler for sig.
586 externC int sigaction (int sig, const struct sigaction *act,
587 struct sigaction *oact)
591 if( !SIGNAL_VALID(sig) )
592 SIGNAL_RETURN(EINVAL);
594 signal_state *ss = &sigstate[sig];
603 if( ss->sa.sa_handler == SIG_IGN )
605 // Setting the handler to SIG_IGN causes any pending
606 // signals to be discarded and any queued values to also
609 pthread_info *self = pthread_self_info();
610 sigset_t sigbit = 1<<sig;
612 if( (sig_pending | self->sigpending) & sigbit )
614 // This signal is pending, clear it
616 sig_pending &= ~sigbit;
617 self->sigpending &= ~sigbit;
619 // Clean out any queued signal_info objects
620 while( ss->pending != NULL )
622 signal_info *si = ss->pending->next;
624 // Remove the head signal_info object from the
626 if( ss->pending == si )
629 ss->pending->next = si->next;
631 // Return it to the free list
632 si->next = siginfo_next;
638 cyg_deliver_signals();
640 signal_mutex.unlock();
646 // -------------------------------------------------------------------------
647 // Queue signal to process with value.
649 externC int sigqueue (pid_t pid, int sig, const union sigval value)
653 if( !SIGNAL_VALID(sig) )
654 SIGNAL_RETURN(EINVAL);
658 sev.sigev_notify = SIGEV_SIGNAL;
659 sev.sigev_signo = sig;
660 sev.sigev_value = value;
662 cyg_sigqueue( &sev, SI_QUEUE );
664 cyg_deliver_signals();
669 //==========================================================================
670 // Functions to deal with current blocked and pending masks
672 // -------------------------------------------------------------------------
673 // Set process blocked signal mask
674 // Map this onto pthread_sigmask().
676 externC int sigprocmask (int how, const sigset_t *set, sigset_t *oset)
678 return pthread_sigmask( how, set, oset);
682 // -------------------------------------------------------------------------
683 // Set calling thread's blocked signal mask
685 externC int pthread_sigmask (int how, const sigset_t *set, sigset_t *oset)
691 pthread_info *self = pthread_self_info();
694 *oset = self->sigmask;
701 self->sigmask |= *set;
705 self->sigmask &= ~*set;
709 self->sigmask = *set;
718 // Deliver any newly unblocked signals
719 cyg_deliver_signals();
724 // -------------------------------------------------------------------------
725 // Exported routine to set calling thread's blocked signal mask
727 // Optionally set and return the current thread's signal mask. This is
728 // exported to other packages so that they can manipulate the signal
729 // mask without necessarily having them delivered (as calling
730 // pthread_sigmask() would). Signals can be delivered by calling
731 // cyg_posix_deliver_signals().
733 externC void cyg_pthread_sigmask_set (const sigset_t *set, sigset_t *oset)
735 pthread_info *self = pthread_self_info();
740 *oset = self->sigmask;
743 self->sigmask = *set;
747 // -------------------------------------------------------------------------
748 // Exported routine to test for any pending signals.
750 // This routine tests for any pending undelivered, unmasked
751 // signals. If there are any it returns true. This is exported to
752 // other packages, such as FILEIO, so that they can detect whether to
753 // abort a current API call with an EINTR result.
755 externC cyg_bool cyg_posix_sigpending(void)
757 pthread_info *self = pthread_self_info();
762 return ( ((sig_pending | self->sigpending) & ~self->sigmask) != 0 );
765 // -------------------------------------------------------------------------
766 // Exported routine to deliver selected signals
768 // This routine optionally sets the given mask and then tries to
769 // deliver any pending signals that have been unmasked. This is
770 // exported to other packages so that they can cause signals to be
771 // delivered at controlled points during execution.
773 externC void cyg_posix_deliver_signals( const sigset_t *mask )
776 pthread_info *self = pthread_self_info();
782 oldmask = self->sigmask;
783 self->sigmask = *mask;
786 oldmask = 0; // silence warning
788 cyg_deliver_signals();
791 self->sigmask = oldmask;
795 // -------------------------------------------------------------------------
796 // Get set of pending signals for this process
798 externC int sigpending (sigset_t *set)
803 SIGNAL_RETURN(EINVAL);
805 pthread_info *self = pthread_self_info();
807 *set = self->sigpending | sig_pending;
813 //==========================================================================
814 // Wait for or accept signals
816 // -------------------------------------------------------------------------
817 // Block signals in set and wait for a signal
819 externC int sigsuspend (const sigset_t *set)
823 pthread_info *self = pthread_self_info();
827 // Save the old mask and set the current mask to
829 sigset_t old = self->sigmask;
830 self->sigmask = *set;
832 // Loop until a signal gets delivered
833 while( !cyg_deliver_signals() )
834 signal_sigwait.wait();
838 signal_mutex.unlock();
840 SIGNAL_RETURN(EINTR);
844 // -------------------------------------------------------------------------
845 // Wait for a signal in set to arrive
846 // Implement this as a variant on sigtimedwait().
848 externC int sigwait (const sigset_t *set, int *sig)
854 int ret = sigtimedwait( set, &info, NULL );
857 SIGNAL_RETURN(errno);
864 // -------------------------------------------------------------------------
865 // Do the same as sigwait() except return a siginfo_t object too.
866 // Implement this as a variant on sigtimedwait().
868 externC int sigwaitinfo (const sigset_t *set, siginfo_t *info)
872 int ret = sigtimedwait( set, info, NULL );
874 SIGNAL_RETURN_VALUE(ret);
877 // -------------------------------------------------------------------------
878 // Wait either for a signal in the given set to become pending, or
879 // for the timeout to expire. If timeout is NULL, wait for ever.
881 externC int sigtimedwait (const sigset_t *set, siginfo_t *info,
882 const struct timespec *timeout)
886 // check for cancellation first.
887 pthread_testcancel();
890 cyg_tick_count ticks;
892 if( timeout == NULL ) ticks = 0;
893 else ticks = cyg_timespec_to_ticks( timeout ) +
894 Cyg_Clock::real_time_clock->current_value();
896 pthread_info *self = pthread_self_info();
902 // Wait for a signal in the set to become pending
903 while( (todo = (*set & (sig_pending | self->sigpending))) == 0 )
905 // If timeout is not NULL, do a timed wait on the
906 // sigwait condition variable. If it is NULL - wait
907 // until we are woken.
910 if( ticks == 0 || !signal_sigwait.wait(ticks) )
912 // If the timeout is actually zero, or we have waited and
913 // timed out, then we must quit with an error.
919 if ( !signal_sigwait.wait() ) {
920 // check we weren't woken up forcibly (e.g. to be cancelled)
921 // if so, pretend it's an error
927 // Special case check for SIGALRM since the fact SIGALRM is masked
928 // would have prevented it being set pending in the alarm handler.
931 cyg_posix_timer_asr(self);
936 // There is a signal in the set that is pending: deliver
937 // it. todo contains a mask of all the signals that could be
938 // delivered now, but we only want to deliver one of them.
942 // Select the lowest numbered signal from the todo mask
943 HAL_LSBIT_INDEX( signo, todo );
945 signal_state *ss = &sigstate[signo];
946 sigset_t sigbit = 1L<<signo;
948 if( (ss->sa.sa_flags & SA_SIGINFO) && (ss->pending != NULL) )
950 // If the SA_SIGINFO bit is set, then there
951 // will be a signal_info object queued on the
954 signal_info *si = ss->pending->next;
957 // Remove the head signal_info object from the
959 if( ss->pending == si )
962 ss->pending->next = si->next;
964 si->next = siginfo_next;
970 // Not a queued signal, or there is no signal_info object
971 // on the pending queue: fill in info structure with
973 info->si_signo = signo;
974 info->si_code = SI_USER;
975 info->si_value.sival_int = 0;
978 // Clear the bit from the pending masks. If the pending
979 // queue is not empty, leave the bits set, otherwise clear
982 if( ss->pending == NULL )
984 // Clear the bit in both masks regardless of which
985 // one it actually came from. This is cheaper than
986 // trying to find out.
987 sig_pending &= ~sigbit;
988 self->sigpending &= ~sigbit;
994 signal_mutex.unlock();
996 pthread_testcancel();
1001 SIGNAL_RETURN_VALUE( info->si_signo );
1004 //==========================================================================
1005 // alarm, pause and sleep
1007 // -------------------------------------------------------------------------
1008 // Generate SIGALRM after some number of seconds
1010 externC unsigned int alarm( unsigned int seconds )
1014 cyg_tick_count trigger, interval;
1018 signal_mutex.lock();
1022 sigalrm_alarm.disable();
1024 sigalrm_alarm.get_times( &trigger, &interval );
1026 // Convert trigger time back to interval
1027 trigger -= Cyg_Clock::real_time_clock->current_value();
1029 cyg_ticks_to_timespec( trigger, &tv );
1033 sigalrm_armed = false;
1038 // Here we know that the sigalrm_alarm is unarmed, set it up
1039 // to trigger in the required number of seconds.
1041 tv.tv_sec = seconds;
1044 trigger = cyg_timespec_to_ticks( &tv );
1046 // Convert trigger interval to absolute time
1047 trigger += Cyg_Clock::real_time_clock->current_value();
1049 sigalrm_alarm.initialize( trigger, 0 );
1051 sigalrm_armed = true;
1054 signal_mutex.unlock();
1056 CYG_REPORT_RETVAL(res);
1061 // -------------------------------------------------------------------------
1062 // Wait for a signal to be delivered.
1064 externC int pause( void )
1068 signal_mutex.lock();
1070 // Check for any pending signals that can be delivered and
1071 // if there are none, wait for a signal to be generated
1072 while( !cyg_deliver_signals() )
1073 signal_sigwait.wait();
1075 signal_mutex.unlock();
1077 SIGNAL_RETURN(EINTR);
1080 //==========================================================================
1083 // -------------------------------------------------------------------------
1084 // Clear all signals from set.
1086 externC int sigemptyset (sigset_t *set)
1096 // -------------------------------------------------------------------------
1097 // Set all signals in set.
1099 externC int sigfillset (sigset_t *set)
1109 // -------------------------------------------------------------------------
1110 // Add signo to set.
1112 externC int sigaddset (sigset_t *set, int signo)
1118 if( !SIGNAL_VALID(signo) )
1120 else *set |= 1<<signo;
1126 // -------------------------------------------------------------------------
1127 // Remove signo from set.
1129 externC int sigdelset (sigset_t *set, int signo)
1135 if( !SIGNAL_VALID(signo) )
1137 else *set &= ~(1<<signo);
1143 // -------------------------------------------------------------------------
1144 // Test whether signo is in set
1146 externC int sigismember (const sigset_t *set, int signo)
1152 if( !SIGNAL_VALID(signo) )
1153 SIGNAL_RETURN(EINVAL);
1155 if( *set & (1<<signo) ) ret = 1;
1157 CYG_REPORT_RETVAL( ret );
1161 //==========================================================================
1162 // ISO C compatibility functions
1164 // -------------------------------------------------------------------------
1165 // Installs a new signal handler for the specified signal, and returns
1168 externC sa_sighandler_t signal(int sig, sa_sighandler_t handler)
1173 sa_sighandler_t ret;
1174 struct sigaction new_action;
1175 struct sigaction old_action;
1177 sigemptyset( &new_action.sa_mask );
1178 new_action.sa_flags = 0;
1179 new_action.sa_handler = handler;
1181 err = sigaction( sig, &new_action, &old_action );
1185 else ret = old_action.sa_handler;
1187 CYG_REPORT_RETVAL( ret );
1191 // -------------------------------------------------------------------------
1192 // raise() - ISO C 7.7.2 //
1194 // Raises the signal, which will cause the current signal handler for
1195 // that signal to be called
1197 externC int raise(int sig)
1199 return kill( 0, sig );
1202 // -------------------------------------------------------------------------
1204 // Restores signal mask and longjumps.
1206 __externC void siglongjmp( sigjmp_buf env, int val )
1208 CYG_REPORT_FUNCNAME( "siglongjmp" );
1209 CYG_REPORT_FUNCARG2( "&env=%08x, val=%d", &env, val );
1211 // ISO C says that if we are passed val == 0, then we change it to 1
1215 if( env[0].__savemask )
1216 pthread_sigmask( SIG_SETMASK, &env[0].__sigsavemask, NULL );
1218 HAL_REORDER_BARRIER(); // prevent any chance of optimisation re-ordering
1219 hal_longjmp( env[0].__jmp_buf, val );
1220 HAL_REORDER_BARRIER(); // prevent any chance of optimisation re-ordering
1222 #ifdef CYGDBG_USE_ASSERTS
1223 CYG_ASSERT( 0, "siglongjmp should not have reached this point!" );
1226 CYG_EMPTY_STATEMENT;
1231 #endif // ifdef CYGPKG_POSIX_SIGNALS
1233 // -------------------------------------------------------------------------