⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pthread.cxx

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 CXX
📖 第 1 页 / 共 4 页
字号:
    // 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 thread

externC 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_MEASUREMENT
externC 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 + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -