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

📄 thread.cxx

📁 ecos为实时嵌入式操作系统
💻 CXX
📖 第 1 页 / 共 3 页
字号:
//==========================================================================////      common/thread.cxx////      Thread class implementations////==========================================================================//####COPYRIGHTBEGIN####//// -------------------------------------------// The contents of this file are subject to the Cygnus eCos Public License// Version 1.0 (the "License"); you may not use this file except in// compliance with the License.  You may obtain a copy of the License at// http://sourceware.cygnus.com/ecos// // Software distributed under the License is distributed on an "AS IS"// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the// License for the specific language governing rights and limitations under// the License.// // The Original Code is eCos - Embedded Cygnus Operating System, released// September 30, 1998.// // The Initial Developer of the Original Code is Cygnus.  Portions created// by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions.  All Rights Reserved.// -------------------------------------------////####COPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s):   nickg// Contributors:        nickg// Date:        1997-09-15// Purpose:     Thread class implementation// Description: This file contains the definitions of the thread class//              member functions that are common to all thread implementations.////####DESCRIPTIONEND####////==========================================================================#include <pkgconf/kernel.h>             // kernel configuration file#include <cyg/hal/hal_arch.h>           // HAL_REORDER_BARRIER &                                        // CYGNUM_HAL_STACK_SIZE_TYPICAL#include <cyg/kernel/ktypes.h>          // base kernel types#include <cyg/infra/cyg_trac.h>         // tracing macros#include <cyg/infra/cyg_ass.h>          // assertion macros#include <cyg/kernel/instrmnt.h>        // instrumentation#include <cyg/kernel/thread.hxx>        // our header#include <cyg/kernel/intr.hxx>          // Interrupt support#include <cyg/kernel/thread.inl>        // thread inlines#include <cyg/kernel/sched.inl>         // scheduler inlines#include <cyg/kernel/clock.inl>         // clock inlines// =========================================================================// Cyg_HardwareThread members// -------------------------------------------------------------------------// Thread entry point.// This is inserted as the PC value in all initial thread contexts.// It does some housekeeping and then calls the real entry point.voidCyg_HardwareThread::thread_entry( Cyg_Thread *thread ){    CYG_REPORT_FUNCTION();    Cyg_Scheduler::scheduler.need_reschedule = false; // finished rescheduling    Cyg_Scheduler::scheduler.current_thread = thread; // restore current thread pointer#ifdef CYGSEM_KERNEL_SCHED_TIMESLICE    // Reset the timeslice counter so that this thread gets a full    // quantum.     Cyg_Scheduler::reset_timeslice_count();#endif        // Zero the lock    HAL_REORDER_BARRIER ();            // Prevent the compiler from moving    Cyg_Scheduler::sched_lock = 0;     // the assignment into the code above.    HAL_REORDER_BARRIER();    // Call entry point in a loop.        for(;;)    {        thread->entry_point(thread->entry_data);        thread->exit();    }}// =========================================================================// Cyg_Thread members// -------------------------------------------------------------------------// Statics and thread list functions#ifdef CYGVAR_KERNEL_THREADS_LIST// List of all extant threadsCyg_Thread *Cyg_Thread::thread_list = 0;inline voidCyg_Thread::add_to_list( void ){    // Add thread to housekeeping list    Cyg_Scheduler::lock();    if( thread_list == 0 )        list_next = this;    else {        Cyg_Thread *prev = thread_list;        do {            if ( this == prev )                break; // found it already!            prev = prev->list_next;        } while ( prev != thread_list );        if ( this != prev ) {            // insert it in the list:            list_next = thread_list->list_next;            thread_list->list_next = this;        }    }    thread_list = this;    Cyg_Scheduler::unlock();}inline voidCyg_Thread::remove_from_list( void ){    // remove thread from housekeeping list    Cyg_Scheduler::lock();    Cyg_Thread *prev = thread_list;    do {        if( prev->list_next == this ) {            prev->list_next = list_next;            if( thread_list == this )                thread_list = list_next;            break;        }        prev = prev->list_next;    } while ( prev != thread_list );        Cyg_Scheduler::unlock();}#endifstatic cyg_uint16 next_unique_id = 1;// -------------------------------------------------------------------------// Magic new operator to allow the thread constructor to be// recalled.inline void *operator new(size_t size, Cyg_Thread *ptr){ return (void *)ptr; };// ConstructorCyg_Thread::Cyg_Thread(        CYG_ADDRWORD            sched_info,     // Scheduling parameter(s)        cyg_thread_entry        *entry,         // entry point function        CYG_ADDRWORD            entry_data,     // entry data        char                    *name_arg,      // thread name cookie        CYG_ADDRESS             stack_base,     // stack base, NULL = allocate        cyg_ucount32            stack_size      // stack size, 0 = use default        ):   Cyg_HardwareThread(entry, entry_data, stack_size, stack_base),    Cyg_SchedThread(this, sched_info)#ifdef CYGFUN_KERNEL_THREADS_TIMER    ,timer(this)#endif{    CYG_REPORT_FUNCTION();    // Start the thread in suspended state.    state               = SUSPENDED;    suspend_count       = 1;    // Initialize sleep_reason which is used by kill, release    sleep_reason        = NONE;    wake_reason         = NONE;    // Assign a 16 bit id to the thread.    unique_id           = next_unique_id++;#ifdef CYGVAR_KERNEL_THREADS_DATA    // Zero all per-thread data entries.    for( int i = 0; i < CYGNUM_KERNEL_THREADS_DATA_MAX; i++ )        thread_data[i] = 0;#endif#ifdef CYGVAR_KERNEL_THREADS_NAME    name = name_arg;#endif#ifdef CYGVAR_KERNEL_THREADS_LIST    // Add thread to housekeeping list    add_to_list();#endif            Cyg_Scheduler::scheduler.register_thread(this);        init_context(this);    CYG_REPORT_RETURN();}// -------------------------------------------------------------------------// Re-initialize this thread.// We do this by re-invoking the constructor with the original// arguments, which are still available in the object.voidCyg_Thread::reinitialize(){    CYG_REPORT_FUNCTION();    CYG_ASSERTCLASS( this, "Bad thread");    CYG_ASSERT( this != Cyg_Scheduler::get_current_thread(),                "Attempt to reinitialize current thread");    CYG_ASSERT( get_current_queue() == NULL , "Thread is still on a queue");#ifdef CYGFUN_KERNEL_THREADS_TIMER    // Clear the timeout. It is irrelevant whether there was    // actually a timeout pending.    timer.disable();#endif    // Ensure the scheduler has let go of us.    Cyg_Scheduler::scheduler.deregister_thread(this);    cyg_priority pri = get_priority();#ifdef CYGVAR_KERNEL_THREADS_NAME    char * name_arg = name;#else    char * name_arg = NULL;#endif        new(this) Cyg_Thread( pri,                          entry_point, entry_data,                          name_arg,                          stack_base, stack_size );    // the constructor re-registers the thread with the scheduler.    CYG_ASSERTCLASS( this, "Thread corrupted by reinitialize");        CYG_REPORT_RETURN();}// -------------------------------------------------------------------------// Destructor.Cyg_Thread::~Cyg_Thread(){    CYG_REPORT_FUNCTION();    Cyg_Scheduler::scheduler.deregister_thread(this);#ifdef CYGVAR_KERNEL_THREADS_LIST    // Remove thread from housekeeping list.    remove_from_list();#endif         CYG_REPORT_RETURN();}// -------------------------------------------------------------------------// Thread consistency checker.#ifdef CYGDBG_USE_ASSERTSboolCyg_Thread::check_this( cyg_assert_class_zeal zeal) const{//    CYG_REPORT_FUNCTION();    // check that we have a non-NULL pointer first    if( this == NULL ) return false;        switch( zeal )    {    case cyg_system_test:    case cyg_extreme:    case cyg_thorough:        if( (state & SUSPENDED) && (suspend_count == 0) ) return false;    case cyg_quick:        // Check that the stackpointer is within its limits.        // Note: This does not check the current stackpointer value        // of the executing thread.        if( (stack_ptr > (stack_base + stack_size)) ||            (stack_ptr < stack_base) ) return false;    case cyg_trivial:    case cyg_none:    default:        break;    };    return true;}#endif// -------------------------------------------------------------------------// Put the thread to sleep.// This can only be called by the current thread on itself, hence// it is a static function.voidCyg_Thread::sleep(){    CYG_REPORT_FUNCTION();    Cyg_Thread *current = Cyg_Scheduler::get_current_thread();    CYG_ASSERTCLASS( current, "Bad current thread" );        CYG_INSTRUMENT_THREAD(SLEEP,current,0);        // Prevent preemption    Cyg_Scheduler::lock();    // If running, remove from run qs    if ( current->state == RUNNING )        Cyg_Scheduler::scheduler.rem_thread(current);    // Set the state    current->state |= SLEEPING;    // Unlock the scheduler and switch threads    Cyg_Scheduler::unlock();    CYG_REPORT_RETURN();}// -------------------------------------------------------------------------// Awaken the thread from sleep.voidCyg_Thread::wake(){    CYG_REPORT_FUNCTION();    CYG_INSTRUMENT_THREAD(WAKE,this,Cyg_Scheduler::current_thread);        // Prevent preemption    Cyg_Scheduler::lock();    if( 0 != (state & SLEEPSET) )    {        // Set the state        state &= ~SLEEPSET;        // remove from any queue we were on        remove();        // If the thread is now runnable, return it to run queue        if( state == RUNNING )            Cyg_Scheduler::scheduler.add_thread(this);    }        // Unlock the scheduler and maybe switch threads    Cyg_Scheduler::unlock();    CYG_REPORT_RETURN();}// -------------------------------------------------------------------------// Put the thread to sleep, with wakeup count.// This can only be called by the current thread on itself, hence// it is a static function.voidCyg_Thread::counted_sleep(){    CYG_REPORT_FUNCTION();    Cyg_Thread *current = Cyg_Scheduler::get_current_thread();    CYG_ASSERTCLASS( current, "Bad current thread" );        CYG_INSTRUMENT_THREAD(SLEEP,current,0);        // Prevent preemption    Cyg_Scheduler::lock();    if ( 0 == current->wakeup_count ) {        set_sleep_reason( Cyg_Thread::WAIT );        current->sleep();               // prepare to sleep        current->state |= COUNTSLEEP;   // Set the state    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -