ecos kernel 分析

來源:互聯網
上載者:User

ecos kernel 是個典型的搶佔式多任務的rtos,我這裡想從代碼上,把它的實現搭個架構出來。
    分時的多任務系統是靠定時時間中斷實現的,所以我從這裡做切入點
有kernel 的ecos重寫了interrupt 處理代碼,原來的在drv_api.c裡實現的,現在的在kernel/intr/intr.cxx裡,時間中斷的註冊在kernel/common/clock.cxx裡

Cyg_RealTimeClock Cyg_RealTimeClock::rtc CYG_INIT_PRIORITY( CLOCK );

// -------------------------------------------------------------------------

Cyg_RealTimeClock::Cyg_RealTimeClock()
    : Cyg_Clock(rtc_resolution),
      interrupt(CYGNUM_HAL_INTERRUPT_RTC,
                CYGNUM_KERNEL_COUNTERS_CLOCK_ISR_PRIORITY,
                (CYG_ADDRWORD)this, isr, dsr)
{
    CYG_REPORT_FUNCTION();

    HAL_CLOCK_INITIALIZE( CYGNUM_KERNEL_COUNTERS_RTC_PERIOD );
    
    interrupt.attach();
    interrupt.unmask_interrupt(CYGNUM_HAL_INTERRUPT_RTC);

    Cyg_Clock::real_time_clock = this;
}
中斷的註冊很好理解,但這裡有個有趣的是這個函數是怎樣被調用到的,直接搜尋ecos所有的代碼是找不到的。一般我們有個概念c++的類在聲明後就會被自動調用裡面和自己名字一樣的那個函數,(很久沒有接觸c++,忘記叫什麼名字了)
這裡也是這樣,這裡第一句就是聲明這個執行個體,然後編譯器會把這個函數放到一個特殊的段__CTOR_LIST__裡面(target.ld),
然後cyg_hal_invoke_constructors()會遍曆__CTOR_LIST__並執行所有的函數,cyg_hal_invoke_constructors() 是在vector.S裡面被調用到的。這個“自動調用”就是這樣實現的。
    再看時間中斷服務程式,ecos 把中斷服務分為兩塊ISR和DSR,ISR裡只做些最簡單的事情,發生中斷後會被直接調到,以保證kernel快速響應的效果。把其他的事情都放到DSR裡面,DSR會被稍後調用,先看DSR裡面代碼
// -------------------------------------------------------------------------
void Cyg_RealTimeClock::dsr(cyg_vector vector, cyg_ucount32 count, CYG_ADDRWORD data)
{
//    CYG_REPORT_FUNCTION();

    Cyg_RealTimeClock *rtc = (Cyg_RealTimeClock *)data;

    CYG_INSTRUMENT_CLOCK( TICK_START,
                          rtc->current_value_lo(),
                          rtc->current_value_hi());
>>這裡是提供系統時鐘
    rtc->tick( count );
#ifdef CYGSEM_KERNEL_SCHED_TIMESLICE
#if    0 == CYGINT_KERNEL_SCHEDULER_UNIQUE_PRIORITIES

    // If timeslicing is enabled, call the scheduler to
    // handle it. But not if we have unique priorities.
>>分時多任務的處理,它的實現在演算法裡,我以mlqueue為例
    Cyg_Scheduler::scheduler.timeslice();

#endif
#endif

    CYG_INSTRUMENT_CLOCK( TICK_END,
                          rtc->current_value_lo(),
                          rtc->current_value_hi());
   
}

timeslice()調用timeslice_cpu(),timeslice_cpu裡只做了一件事情,
找出是否有比當前任務的優先順序更高的任務存在,如果有,則設定reschedule的標誌:需要做任務切換。
到這裡這條路就斷了。但是前面我沒有講到DSR是怎樣被調到的,這裡要看interrupt_end()
在vector.S裡被調到,interrupt_end代碼在kernel/intr/intr.cxx裡

//-------------------------------------
externC void
interrupt_end(
    cyg_uint32          isr_ret,
    Cyg_Interrupt       *intr,
    HAL_SavedRegisters  *regs
    )
{
//    CYG_REPORT_FUNCTION();

#ifdef CYGPKG_KERNEL_SMP_SUPPORT
    Cyg_Scheduler::lock();
#endif
   
    // Sometimes we have a NULL intr object pointer.
    cyg_vector vector = (intr!=NULL)?intr->vector:0;

    CYG_INSTRUMENT_INTR(END, vector, isr_ret);
   
    CYG_UNUSED_PARAM( cyg_vector, vector ); // prevent compiler warning
   
#ifndef CYGIMP_KERNEL_INTERRUPTS_CHAIN

    // Only do this if we are in a non-chained configuration.
    // If we are chained, then chain_isr below will do the DSR
    // posting.
>>這裡把當前的DSR post出去,其實就是加入一個DSR 任務鏈表裡去,之後再拿出來處理
    if( isr_ret & Cyg_Interrupt::CALL_DSR && intr != NULL ) intr->post_dsr();

#endif   

  
    // Now unlock the scheduler, which may also call DSRs
    // and cause a thread switch to happen.
>>這裡就是多任務處理的入口了,下面再去看裡面的實現
    Cyg_Scheduler::unlock();

    CYG_INSTRUMENT_INTR(RESTORE, vector, 0);   
}

unlock()會調用unlock_inner,unlock_inner是kernel最重要的一個函數了,它是多任務切換的
執行者,來看它的實現,代碼很長,只挑其中一段

//-------------------------------------
void Cyg_Scheduler::unlock_inner( cyg_ucount32 new_lock )
{

    do {

#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS
       
        // Call any pending DSRs. Do this here to ensure that any
        // threads that get awakened are properly scheduled.
>>調用前面post的所有的DSR,注意裡面會有reschedule flag的設定
>>下面就要用到
        if( new_lock == 0 && Cyg_Interrupt::DSRs_pending() )
            Cyg_Interrupt::call_pending_DSRs();
#endif

        Cyg_Thread *current = get_current_thread();

        // If the current thread is going to sleep, or someone
        // wants a reschedule, choose another thread to run
>>這裡有兩種情況需要處理,一個是當前的任務已經不在運行了,當然就要切換給別的任務;
>>另外一個就是在DSR的timeslice中找到優先順序更高的任務需要運行
        if( current->state != Cyg_Thread::RUNNING || get_need_reschedule() ) {

            CYG_INSTRUMENT_SCHED(RESCHEDULE,0,0);
           
            // Get the next thread to run from scheduler
            Cyg_Thread *next = scheduler.schedule();

            if( current != next )
            {

                CYG_INSTRUMENT_THREAD(SWITCH,current,next);

                // Count this thread switch
                thread_switches[CYG_KERNEL_CPU_THIS()]++;
>>環境切換,在contexts.S裡
                // Switch contexts
                HAL_THREAD_SWITCH_CONTEXT( &current->stack_ptr,
                                           &next->stack_ptr );

                // Worry here about possible compiler
                // optimizations across the above call that may try to
                // propogate common subexpresions.  We would end up
                // with the expression from one thread in its
                // successor. This is only a worry if we do not save
                // and restore the complete register set. We need a
                // way of marking functions that return into a
                // different context. A temporary fix would be to
                // disable CSE (-fdisable-cse) in the compiler.
               
                // We return here only when the current thread is
                // rescheduled.  There is a bit of housekeeping to do
                // here before we are allowed to go on our way.
>>一般就不會跑到這裡了,cpu pc指標已經切換到別的任務上去了,只有等這個任務再次
>>被reschedule時,才會從這裡開始執行
                current_thread[CYG_KERNEL_CPU_THIS()] = current;   // restore current thread pointer
            }

#ifdef CYGSEM_KERNEL_SCHED_TIMESLICE
            // Reset the timeslice counter so that this thread gets a full
            // quantum.
            reset_timeslice_count();
#endif

            clear_need_reschedule();    // finished rescheduling
        }

        return;

    } while( 1 );
}

至此,整個架構已經出來了,對於schedule,thread,semphone,mutex,flag,mailbox等等其他概念,在ecos 發布的文檔上
有比較詳細的介紹(ecos reference manual),我就不再贅述了。 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.