# HG changeset patch # User nickg # Date 1044013994 0 # Node ID 489b846deeff5f56287eb31413b31a6177241711 # Parent fddb77989fbbf5ec71d6706087fb4c501902f165 * src/time.cxx (alarm_action): Added call to cyg_posix_signal_sigwait() to wake up any sigwait()ing threads. * src/signal.cxx (cyg_posix_signal_sigwait): Added this function to export access to signal_sigwait conditional variable. (sigtimedwait): Added call to cyg_posix_timer_asr() to allow timer signals to be delivered here. * src/pprivate.h: Added prototype for cyg_posix_signal_sigwait(). * cdl/posix.cdl: * tests/signal3.c: Added this program to test interaction of timers and signals, particularly sigwait(). Based on a test program from N.Suresh . diff --git a/packages/compat/posix/current/ChangeLog b/packages/compat/posix/current/ChangeLog --- a/packages/compat/posix/current/ChangeLog +++ b/packages/compat/posix/current/ChangeLog @@ -1,3 +1,20 @@ +2003-01-31 Nick Garnett + + * src/time.cxx (alarm_action): Added call to + cyg_posix_signal_sigwait() to wake up any sigwait()ing threads. + + * src/signal.cxx (cyg_posix_signal_sigwait): Added this function + to export access to signal_sigwait conditional variable. + (sigtimedwait): Added call to cyg_posix_timer_asr() to allow timer + signals to be delivered here. + + * src/pprivate.h: Added prototype for cyg_posix_signal_sigwait(). + + * cdl/posix.cdl: + * tests/signal3.c: Added this program to test interaction of + timers and signals, particularly sigwait(). Based on a test + program from N.Suresh . + 2003-01-20 Jonathan Larmour * src/signal.cxx (cyg_posix_deliver_signals): silence warning. diff --git a/packages/compat/posix/current/cdl/posix.cdl b/packages/compat/posix/current/cdl/posix.cdl --- a/packages/compat/posix/current/cdl/posix.cdl +++ b/packages/compat/posix/current/cdl/posix.cdl @@ -302,7 +302,7 @@ cdl_package CYGPKG_POSIX { no_define calculated { "tests/pthread1 tests/pthread2 tests/pthread3 tests/mutex3 tests/mqueue2" - . ((CYGPKG_POSIX_SIGNALS) ? " tests/mqueue1 tests/signal1 tests/signal2 tests/sigsetjmp tests/timer1 tests/tm_basic" : "") + . ((CYGPKG_POSIX_SIGNALS) ? " tests/mqueue1 tests/signal1 tests/signal2 tests/signal3 tests/sigsetjmp tests/timer1 tests/tm_basic" : "") } description " This option specifies the set of tests for the POSIX package." diff --git a/packages/compat/posix/current/src/pprivate.h b/packages/compat/posix/current/src/pprivate.h --- a/packages/compat/posix/current/src/pprivate.h +++ b/packages/compat/posix/current/src/pprivate.h @@ -227,7 +227,9 @@ externC cyg_bool cyg_sigqueue( const str pthread_info *thread = NULL ); externC cyg_bool cyg_deliver_signals(); - + +externC void cyg_posix_signal_sigwait(); + externC void cyg_posix_thread_siginit( pthread_info *thread, pthread_info *parentthread ); diff --git a/packages/compat/posix/current/src/signal.cxx b/packages/compat/posix/current/src/signal.cxx --- a/packages/compat/posix/current/src/signal.cxx +++ b/packages/compat/posix/current/src/signal.cxx @@ -435,6 +435,14 @@ cyg_bool cyg_deliver_signals() } // ------------------------------------------------------------------------- +// Utility routine to signal any threads waiting in sigwait*(). + +void cyg_posix_signal_sigwait() +{ + signal_sigwait.broadcast(); +} + +// ------------------------------------------------------------------------- // Action routine called from kernel alarm to deliver the SIGALRM signal. // We cannot call any signal delivery functions directly here, so we simply // set a flag and schedule an ASR to be called. @@ -918,6 +926,8 @@ externC int sigtimedwait (const sigset_ // Special case check for SIGALRM since the fact SIGALRM is masked // would have prevented it being set pending in the alarm handler. check_sigalarm(); + + cyg_posix_timer_asr(self); } if( err == 0 ) diff --git a/packages/compat/posix/current/src/time.cxx b/packages/compat/posix/current/src/time.cxx --- a/packages/compat/posix/current/src/time.cxx +++ b/packages/compat/posix/current/src/time.cxx @@ -272,6 +272,7 @@ static void alarm_action( Cyg_Alarm *ala sigset_t mask; sigemptyset( &mask ); sigaddset( &mask, timer->sigev.sigev_signo ); + cyg_posix_signal_sigwait(); cyg_posix_pthread_release_thread( &mask ); } else if( timer->sigev.sigev_notify == SIGEV_THREAD ) diff --git a/packages/compat/posix/current/tests/signal1.c b/packages/compat/posix/current/tests/signal1.c --- a/packages/compat/posix/current/tests/signal1.c +++ b/packages/compat/posix/current/tests/signal1.c @@ -183,7 +183,7 @@ void *pthread_entry1( void *arg) pthread_sigmask( SIG_SETMASK, &mask, NULL ); alarm(1); - CYG_TEST_INFO( "Thread1: calling alarm()"); + CYG_TEST_INFO( "Thread1: calling sigwait()"); err = sigwait( &mask, &sig); CYG_TEST_CHECK( 0==err, "sigwait returned -1"); CYG_TEST_CHECK( sig==SIGALRM, "sigwait caught alarm"); diff --git a/packages/compat/posix/current/tests/signal3.c b/packages/compat/posix/current/tests/signal3.c new file mode 100644 --- /dev/null +++ b/packages/compat/posix/current/tests/signal3.c @@ -0,0 +1,174 @@ +//========================================================================== +// +// signal3.cxx +// +// POSIX signal test 3 +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 2003-01-30 +// Description: Tests POSIX signal functionality. +// +//####DESCRIPTIONEND#### +//========================================================================== + +#include +#include + +#if !defined(CYGPKG_POSIX_SIGNALS) +#define NA_MSG "POSIX signals not enabled" +#elif !defined(CYGPKG_POSIX_PTHREAD) +#define NA_MSG "POSIX threads not enabled" +#endif + +#ifdef NA_MSG +void +cyg_start(void) +{ + CYG_TEST_INIT(); + CYG_TEST_NA(NA_MSG); +} +#else + +#include +#include +#include +#include +#include + +volatile int sigusr1_called = 0; + +//-------------------------------------------------------------------------- +// Signal handler functions + +static void sigusr1( int signo ) +{ + CYG_TEST_INFO( "sigusr1() handler called" ); + CYG_TEST_CHECK( signo == SIGUSR1, "Signal not SIGUSR1"); + + sigusr1_called++; +} + +//-------------------------------------------------------------------------- + +int main (int argc, char **argv) +{ + int ret_val; + sigset_t set; + int sig; + + CYG_TEST_INIT(); + + { + struct sigaction sa; + + sa.sa_handler = sigusr1; + sigfillset( &sa.sa_mask ); + sa.sa_flags = 0; + + ret_val = sigaction( SIGUSR1, &sa, NULL ); + + CYG_TEST_CHECK( ret_val == 0 , "sigaction returned error"); + } + + // unblock all the signals + sigfillset (&set); + pthread_sigmask (SIG_UNBLOCK, &set, (sigset_t*)NULL); + + //-------------------------------------------------------------------- + // + //-------------------------------------------------------------------- + struct itimerspec timerValue; // Timeout value on eCos + timer_t timer1; // Timer + struct sigevent sev; + + // Notification type --- Deliver the signal + sev.sigev_notify = SIGEV_SIGNAL; + sev.sigev_signo = SIGUSR1; + sev.sigev_value.sival_int = 0xABCDEF01; + + // Timer values --- 1 Second + timerValue.it_value.tv_sec = 1; + timerValue.it_value.tv_nsec = 0; + timerValue.it_interval.tv_sec = 1; + timerValue.it_interval.tv_nsec = 0; + + ret_val = timer_create (CLOCK_REALTIME, &sev, &timer1); + + CYG_TEST_CHECK( ret_val==0, "Error in creating the timer"); + + ret_val = timer_settime (timer1, 0, &timerValue, NULL ); + CYG_TEST_CHECK( ret_val==0,"Error in setting the time"); + + //-------------------------------------------------------------------- + // + //-------------------------------------------------------------------- + + CYG_TEST_INFO ("Timer initialisation is completed.."); + + CYG_TEST_INFO ("Calling pause()"); + ret_val = pause(); + CYG_TEST_CHECK( ret_val==-1, "pause() did not return -1"); + CYG_TEST_CHECK( EINTR==errno, "errno set to EINTR"); + CYG_TEST_CHECK( sigusr1_called==1, "Siguser1 handler not called"); + + // Block all the signals + sigfillset (&set); + pthread_sigmask (SIG_BLOCK, &set, (sigset_t*)NULL); + + CYG_TEST_INFO ("Calling sigwait()"); + // Wait for any signal to arrive + sigfillset (&set); + ret_val = sigwait (&set, &sig); + + CYG_TEST_CHECK( ret_val==0, "sigwait returned error"); + CYG_TEST_CHECK( sig==SIGUSR1, "sigwait returned wrong signo!"); + CYG_TEST_CHECK( sigusr1_called==1, "Siguser1 handler called!"); + + CYG_TEST_INFO ("Program terminating"); + + CYG_TEST_PASS_FINISH( "signal3" ); + return 0; +} + + +#endif + +//-------------------------------------------------------------------------- +// end of signal3.c