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 + -
显示快捷键?