Mercurial > ecos
diff packages/compat/posix/current/src/pthread.cxx @ 151:25e238959bae
Merge from eCos master repository on 2001-02-12-23:44:24-GMT
| author | jlarmour |
|---|---|
| date | Tue, 13 Feb 2001 01:23:16 +0000 |
| parents | 8f2f7615e727 |
| children | f935b880e96c |
line wrap: on
line diff
--- a/packages/compat/posix/current/src/pthread.cxx +++ b/packages/compat/posix/current/src/pthread.cxx @@ -164,7 +164,7 @@ static pthread_t main_thread; //============================================================================= // Exported variables -int pthread_canceled; // pointed to by PTHREAD_CANCELED +int pthread_canceled_dummy_var; // pointed to by PTHREAD_CANCELED //============================================================================= // Internal functions @@ -271,6 +271,27 @@ static void *call_main( void * ) } //----------------------------------------------------------------------------- +// Check whether there is a cancel pending and if so, whether +// cancellations are enabled. We do it in this order to reduce the +// number of tests in the common case - when no cancellations are +// pending. +// We make this inline so it can be called directly below for speed + +static __inline__ int +checkforcancel( void ) +{ + pthread_info *self = pthread_self_info(); + + if( self != NULL && + self->cancelpending && + self->cancelstate == PTHREAD_CANCEL_ENABLE ) + return 1; + else + return 0; +} + + +//----------------------------------------------------------------------------- // POSIX ASR // This is installed as the ASR for all POSIX threads. @@ -763,6 +784,9 @@ externC int pthread_join (pthread_t thre { PTHREAD_ENTRY(); + // check for cancellation first. + pthread_testcancel(); + pthread_mutex.lock(); // Dispose of any dead threads @@ -787,8 +811,11 @@ externC int pthread_join (pthread_t thre { case PTHREAD_STATE_RUNNING: // The thread is still running, we must wait for it. - while( joinee->state == PTHREAD_STATE_RUNNING ) + while( joinee->state == PTHREAD_STATE_RUNNING ) { joinee->joiner->wait(); + // check if we were woken because we were being cancelled + pthread_testcancel_unlock( (pthread_mutex_t *)&pthread_mutex); + } // check that the thread is still joinable if( joinee->state == PTHREAD_STATE_JOIN ) @@ -1641,11 +1668,17 @@ externC int pthread_cond_wait (pthread_c { PTHREAD_ENTRY(); + // check for cancellation first. + pthread_testcancel(); + PTHREAD_CHECK( cond ); PTHREAD_CHECK( mutex ); ((Cyg_Condition_Variable *)cond)->wait( *(Cyg_Mutex *)mutex ); + // check if we were woken because we were being cancelled + pthread_testcancel(); + PTHREAD_RETURN(0); } @@ -1658,6 +1691,9 @@ externC int pthread_cond_timedwait (pthr { PTHREAD_ENTRY(); + // check for cancellation first. + pthread_testcancel(); + PTHREAD_CHECK( cond ); PTHREAD_CHECK( mutex ); PTHREAD_CHECK( abstime ); @@ -1673,6 +1709,9 @@ externC int pthread_cond_timedwait (pthr ((Cyg_Condition_Variable *)cond)->wait( *(Cyg_Mutex *)mutex, ticks ); + // check if we were woken because we were being cancelled + pthread_testcancel(); + PTHREAD_RETURN(0); } @@ -1920,20 +1959,31 @@ externC int pthread_cancel (pthread_t th th->cancelpending = true; - if( th->cancelstate == PTHREAD_CANCEL_ENABLE && - th->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS ) + if ( th->cancelstate == PTHREAD_CANCEL_ENABLE ) { - // If the thread has cancellation enabled, and it is in - // asynchronous mode, set the eCos thread's ASR pending to - // deal with it when the thread wakes up. We also release the - // thread out of any current wait to make it wake up. + if ( th->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS ) + { + // If the thread has cancellation enabled, and it is in + // asynchronous mode, set the eCos thread's ASR pending to + // deal with it when the thread wakes up. We also release the + // thread out of any current wait to make it wake up. - th->thread->set_asr_pending(); - th->thread->release(); + th->thread->set_asr_pending(); + th->thread->release(); + } + else if ( th->canceltype == PTHREAD_CANCEL_DEFERRED ) + { + // If the thread has cancellation enabled, and it is in + // deferred mode, wake the thread up so that cancellation + // points can test for cancellation. + th->thread->release(); + } + else + CYG_FAIL("Unknown cancellation type"); } - // Otherwise the thread either has cancellation disabled, or is - // in deferred mode. In either case it is up to the thread to - // get into a state to deal with the pending cancellation. + + // Otherwise the thread has cancellation disabled, in which case + // it is up to the thread to enable cancellation pthread_mutex.unlock(); @@ -1942,6 +1992,42 @@ externC int pthread_cancel (pthread_t th } //----------------------------------------------------------------------------- +// eCos extension: +// Test for a pending cancellation for the current thread and return +// non-zero if this thread has a deferred cancellation pending + +externC int pthread_canceled(void) +{ + PTHREAD_ENTRY(); + PTHREAD_RETURN( checkforcancel() ); +} + +//----------------------------------------------------------------------------- +// eCos extension: +// Test for a pending cancellation for the current thread and terminate +// the thread if there is one, unlocking the supplied mutex first. + +externC void pthread_testcancel_unlock( pthread_mutex_t *__mut ) +{ + PTHREAD_ENTRY_VOID(); + + if( checkforcancel() ) + { + Cyg_Mutex *mut = (Cyg_Mutex *)__mut; + mut->unlock(); + + // If we have cancellation enabled, and there is a cancellation + // pending, then go ahead and do the deed. + + // Exit now with special retval. pthread_exit() calls the + // cancellation handlers implicitly. + pthread_exit(PTHREAD_CANCELED); + } + + PTHREAD_RETURN_VOID; +} + +//----------------------------------------------------------------------------- // Test for a pending cancellation for the current thread and terminate // the thread if there is one. @@ -1949,17 +2035,7 @@ externC void pthread_testcancel (void) { PTHREAD_ENTRY_VOID(); - pthread_info *self = pthread_self_info(); - - // Check whether there is a cancel pending and if so, whether - // cancellations are enabled. We do it in this order to reduce the - // number of tests in the common case - when no cancellations are - // pending. - - if( self != NULL && - self->cancelpending && - self->cancelstate == PTHREAD_CANCEL_ENABLE ) - + if( checkforcancel() ) { // If we have cancellation enabled, and there is a cancellation // pending, then go ahead and do the deed.
