pthread.cxx
来自「eCos操作系统源码」· CXX 代码 · 共 1,680 行 · 第 1/4 页
CXX
1,680 行
// The parameters seem OK, change the thread... pthread_mutex.lock(); pthread_info *thread = pthread_info_id( thread_id ); if( thread == NULL ) { pthread_mutex.unlock(); PTHREAD_RETURN(ESRCH); } thread->attr.schedpolicy = policy; thread->attr.schedparam = *param; if ( policy == SCHED_FIFO ) thread->thread->timeslice_disable(); else thread->thread->timeslice_enable(); thread->thread->set_priority( PTHREAD_ECOS_PRIORITY( param->sched_priority )); pthread_mutex.unlock(); PTHREAD_RETURN(0);}//-----------------------------------------------------------------------------// Get scheduling policy and parameters for the threadexternC int pthread_getschedparam (pthread_t thread_id, int *policy, struct sched_param *param){ PTHREAD_ENTRY(); pthread_mutex.lock(); pthread_info *thread = pthread_info_id( thread_id ); if( thread == NULL ) { pthread_mutex.unlock(); PTHREAD_RETURN(ESRCH); } if( policy != NULL ) *policy = thread->attr.schedpolicy; if( param != NULL ) *param = thread->attr.schedparam; pthread_mutex.unlock(); PTHREAD_RETURN(0);}//=============================================================================// Dynamic package initialization// Call init_routine just the once per control variable.externC int pthread_once (pthread_once_t *once_control, void (*init_routine) (void)){ PTHREAD_ENTRY(); PTHREAD_CHECK( once_control ); PTHREAD_CHECK( init_routine ); pthread_once_t old; // Do a test and set on the once_control object. pthread_mutex.lock(); old = *once_control; *once_control = 1; pthread_mutex.unlock(); // If the once_control was zero, call the init_routine(). if( !old ) init_routine(); PTHREAD_RETURN(0);}//=============================================================================//Thread specific data//-----------------------------------------------------------------------------// Create a key to identify a location in the thread specific data area.// Each thread has its own distinct thread-specific data area but all are// addressed by the same keys. The destructor function is called whenever a// thread exits and the value associated with the key is non-NULL.externC int pthread_key_create (pthread_key_t *key, void (*destructor) (void *)){ PTHREAD_ENTRY(); pthread_key_t k = -1; pthread_mutex.lock(); // Find a key to allocate for( cyg_ucount32 i = 0; i < (PTHREAD_KEYS_MAX/KEY_MAP_TYPE_SIZE); i++ ) { if( thread_key[i] != 0 ) { // We have a table slot with space available // Get index of ls set bit. HAL_LSBIT_INDEX( k, thread_key[i] ); // clear it thread_key[i] &= ~(1<<k); // Add index of word k += i * KEY_MAP_TYPE_SIZE; // Install destructor key_destructor[k] = destructor; // break out with key found break; } } if( k != -1 ) { // plant a NULL in all the valid thread data slots for this // key in case we are reusing a key we used before. for( cyg_ucount32 i = 0; i < CYGNUM_POSIX_PTHREAD_THREADS_MAX ; i++ ) { pthread_info *thread = thread_table[i]; if( thread != NULL && thread->thread_data != NULL ) thread->thread_data[k] = NULL; } } pthread_mutex.unlock(); if( k == -1 ) PTHREAD_RETURN(EAGAIN); *key = k; PTHREAD_RETURN(0);}//-----------------------------------------------------------------------------// Delete key.externC int pthread_key_delete (pthread_key_t key){ PTHREAD_ENTRY(); pthread_mutex.lock(); // Set the key bit to 1 to indicate it is free. thread_key[key/KEY_MAP_TYPE_SIZE] |= 1<<(key%(KEY_MAP_TYPE_SIZE)); pthread_mutex.unlock(); PTHREAD_RETURN(0);}//-----------------------------------------------------------------------------// Store the pointer value in the thread-specific data slot addressed// by the key.externC int pthread_setspecific (pthread_key_t key, const void *pointer){ PTHREAD_ENTRY(); if( thread_key[key/KEY_MAP_TYPE_SIZE] & 1<<(key%KEY_MAP_TYPE_SIZE) ) PTHREAD_RETURN(EINVAL); pthread_info *self = pthread_self_info(); if( self->thread_data == NULL ) { // Allocate the per-thread data table self->thread_data = (void **)self->thread->increment_stack_limit( PTHREAD_KEYS_MAX * sizeof(void *) ); // Clear out all entries for( int i = 0; i < PTHREAD_KEYS_MAX; i++ ) self->thread_data[i] = NULL; } self->thread_data[key] = (void *)pointer; PTHREAD_RETURN(0);}//-----------------------------------------------------------------------------// Retrieve the pointer value in the thread-specific data slot addressed// by the key.externC void *pthread_getspecific (pthread_key_t key){ void *val; PTHREAD_ENTRY(); if( thread_key[key/KEY_MAP_TYPE_SIZE] & 1<<(key%KEY_MAP_TYPE_SIZE) ) PTHREAD_RETURN(NULL); pthread_info *self = pthread_self_info(); if( self->thread_data == NULL ) val = NULL; else val = self->thread_data[key]; PTHREAD_RETURN(val);}//=============================================================================// Thread Cancellation Functions//-----------------------------------------------------------------------------// Set cancel state of current thread to ENABLE or DISABLE.// Returns old state in *oldstate.externC int pthread_setcancelstate (int state, int *oldstate){ PTHREAD_ENTRY(); if( state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE ) PTHREAD_RETURN(EINVAL); pthread_mutex.lock(); pthread_info *self = pthread_self_info(); if( oldstate != NULL ) *oldstate = self->cancelstate; self->cancelstate = state; pthread_mutex.unlock(); // Note: This function may have made it possible for a pending // cancellation to now be delivered. However the standard does not // list this function as a cancellation point, so for now we do // nothing. In future we might call pthread_testcancel() here. PTHREAD_RETURN(0);}//-----------------------------------------------------------------------------// Set cancel type of current thread to ASYNCHRONOUS or DEFERRED.// Returns old type in *oldtype.externC int pthread_setcanceltype (int type, int *oldtype){ PTHREAD_ENTRY(); if( type != PTHREAD_CANCEL_ASYNCHRONOUS && type != PTHREAD_CANCEL_DEFERRED ) PTHREAD_RETURN(EINVAL); pthread_mutex.lock(); pthread_info *self = pthread_self_info(); if( oldtype != NULL ) *oldtype = self->canceltype; self->canceltype = type; pthread_mutex.unlock(); // Note: This function may have made it possible for a pending // cancellation to now be delivered. However the standard does not // list this function as a cancellation point, so for now we do // nothing. In future we might call pthread_testcancel() here. PTHREAD_RETURN(0);}//-----------------------------------------------------------------------------// Cancel the thread.externC int pthread_cancel (pthread_t thread){ PTHREAD_ENTRY(); pthread_mutex.lock(); pthread_info *th = pthread_info_id(thread); if( th == NULL ) { pthread_mutex.unlock(); PTHREAD_RETURN(ESRCH); } th->cancelpending = true; if ( th->cancelstate == PTHREAD_CANCEL_ENABLE ) { 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(); } 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 has cancellation disabled, in which case // it is up to the thread to enable cancellation pthread_mutex.unlock(); PTHREAD_RETURN(0);}//-----------------------------------------------------------------------------// Test for a pending cancellation for the current thread and terminate// the thread if there is one.externC void pthread_testcancel (void){ PTHREAD_ENTRY_VOID(); if( checkforcancel() ) { // 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;}//-----------------------------------------------------------------------------// These two functions actually implement the cleanup push and pop functionality.externC void pthread_cleanup_push_inner (struct pthread_cleanup_buffer *buffer, void (*routine) (void *), void *arg){ PTHREAD_ENTRY(); pthread_info *self = pthread_self_info(); buffer->routine = routine; buffer->arg = arg; buffer->prev = self->cancelbuffer; self->cancelbuffer = buffer; return;}externC void pthread_cleanup_pop_inner (struct pthread_cleanup_buffer *buffer, int execute){ PTHREAD_ENTRY(); pthread_info *self = pthread_self_info(); CYG_ASSERT( self->cancelbuffer == buffer, "Stacking error in cleanup buffers"); if( self->cancelbuffer == buffer ) { // Remove the buffer from the stack self->cancelbuffer = buffer->prev; } else { // If the top of the stack is not the buffer we expect, do not // execute it. execute = 0; } if( execute ) buffer->routine(buffer->arg); return;}// -------------------------------------------------------------------------// eCos-specific function to measure stack usage of the supplied thread#ifdef CYGFUN_KERNEL_THREADS_STACK_MEASUREMENTexternC size_t pthread_measure_stack_usage (pthread_t thread){ pthread_info *th = pthread_info_id(thread); if ( NULL == th ) return (size_t)-1; return (size_t)th->thread->measure_stack_usage();}#endif// -------------------------------------------------------------------------// EOF pthread.cxx
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?