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

📄 thread.inl

📁 实现快速傅立叶变换算法,provides test framwork for FFT testing
💻 INL
📖 第 1 页 / 共 2 页
字号:
#ifndef CYGONCE_KERNEL_THREAD_INL
#define CYGONCE_KERNEL_THREAD_INL

//==========================================================================
//
//      thread.inl
//
//      Thread class inlines
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
// Copyright (C) 2003 Gary Thomas
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s):   nickg
// Contributors:        nickg
// Date:        1997-09-09
// Purpose:     Define inlines for thread classes
// Description: Inline implementations of various member functions defined
//              in various Thread classes. 
// Usage:
//              #include <cyg/kernel/thread.hxx>
//              ...
//              #include <cyg/kernel/thread.inl>
//              ...

//
//####DESCRIPTIONEND####
//
//==========================================================================

#include <cyg/kernel/thread.hxx>
#include <cyg/hal/hal_arch.h>

#include <cyg/kernel/clock.inl>
#include <cyg/infra/diag.h>

#ifndef CYGNUM_KERNEL_THREADS_STACK_CHECK_DATA_SIZE
#define CYGNUM_KERNEL_THREADS_STACK_CHECK_DATA_SIZE (0)
#endif

//==========================================================================
// Inlines for Cyg_HardwareThread

// -------------------------------------------------------------------------
// get the size/base of this thread's stack

inline CYG_ADDRESS
Cyg_HardwareThread::get_stack_base()
{
    return stack_base - CYGNUM_KERNEL_THREADS_STACK_CHECK_DATA_SIZE;
}

inline cyg_uint32
Cyg_HardwareThread::get_stack_size()
{
    return stack_size + 2 * CYGNUM_KERNEL_THREADS_STACK_CHECK_DATA_SIZE;
}

// -------------------------------------------------------------------------
// Check the stack bounds of this thread:
#ifdef CYGFUN_KERNEL_THREADS_STACK_CHECKING
inline void Cyg_HardwareThread::check_stack(void)
{
    cyg_uint32 sig = (cyg_uint32)this;
    cyg_uint32 *base = (cyg_uint32 *)get_stack_base();
    cyg_uint32 *top =  (cyg_uint32 *)(stack_base + stack_size);
    cyg_ucount32 i;

    CYG_INSTRUMENT_THREAD(CHECK_STACK, base, top );
    
    CYG_ASSERT( 0 == ((sizeof(CYG_WORD)-1) & (cyg_uint32)base), "stack base not word aligned" );
    CYG_ASSERT( 0 == ((sizeof(CYG_WORD)-1) & (cyg_uint32)top),  "stack  top not word aligned" );

    CYG_ASSERT( (cyg_uint32)stack_ptr > (cyg_uint32)stack_base,
                "Stack_ptr below base" );
    CYG_ASSERT( (cyg_uint32)stack_ptr <= ((cyg_uint32)stack_base + stack_size),
                "Stack_ptr above top" );

    for ( i = 0;
          i < CYGNUM_KERNEL_THREADS_STACK_CHECK_DATA_SIZE/sizeof(cyg_uint32);
          i++ ) {
        if ((sig ^ (i * 0x01010101)) != base[i]) {
            char *reason = "Stack base corrupt";
            diag_printf("%s - i: %d\n", reason, i);
            diag_dump_buf(base, CYGNUM_KERNEL_THREADS_STACK_CHECK_DATA_SIZE);
            CYG_FAIL(reason);
        }
        if ((sig ^ (i * 0x10101010)) != top[i]) {
            char *reason = "Stack top corrupt";
            diag_printf("%s - i: %d\n", reason, i);
            diag_dump_buf(top, CYGNUM_KERNEL_THREADS_STACK_CHECK_DATA_SIZE);
            CYG_FAIL(reason);
        }
    }            

#ifdef CYGFUN_KERNEL_THREADS_STACK_LIMIT
    // we won't have added check data above the stack limit if it hasn't
    // been incremented
    if (stack_limit != stack_base) {
        CYG_ADDRESS limit = stack_limit;
        // the limit will be off by the check data size, so lets correct it
        limit -= CYGNUM_KERNEL_THREADS_STACK_CHECK_DATA_SIZE;
        
        // determine base of check data by rounding up to nearest word aligned
        // address if not already aligned
        cyg_uint32 *p = (cyg_uint32 *)((limit + 3) & ~3);
        // i.e. + sizeof(cyg_uint32)-1) & ~(sizeof(cyg_uint32)-1);
        
        for ( i = 0;
              i < CYGNUM_KERNEL_THREADS_STACK_CHECK_DATA_SIZE/sizeof(cyg_uint32);
              i++ ) {
            if ((sig ^ (i * 0x01010101)) != p[i]) {
                char *reason = "Gap between stack limit and base corrupt";
                diag_printf("%s - i: %d\n", reason, i);
                diag_dump_buf(p, CYGNUM_KERNEL_THREADS_STACK_CHECK_DATA_SIZE);
                CYG_FAIL(reason);
            }
        }
    }
#endif
}
#endif

// -------------------------------------------------------------------------
// Measure the stack usage of the thread
#ifdef CYGFUN_KERNEL_THREADS_STACK_MEASUREMENT
inline cyg_uint32 Cyg_HardwareThread::measure_stack_usage(void)
{
#ifdef CYGFUN_KERNEL_THREADS_STACK_LIMIT
    CYG_WORD *base = (CYG_WORD *)stack_limit;
    cyg_uint32 size = (stack_size - (stack_limit-stack_base))/sizeof(CYG_WORD);
#else
    CYG_WORD *base = (CYG_WORD *)stack_base;
    cyg_uint32 size = stack_size/sizeof(CYG_WORD);
#endif
    cyg_ucount32 i;

    // Work up the stack comparing with the preset value
    // We assume the stack grows downwards, hmm...
    for (i=0; i<size; i++) {
	if (base[i] != 0xDEADBEEF)
	  break;
    }
    return (size - i)*sizeof(CYG_WORD);
}
#endif

// -------------------------------------------------------------------------
// Attach a stack to this thread. If there is a HAL defined macro to
// do this, then we use that, otherwise assume a falling stack.
inline void Cyg_HardwareThread::attach_stack(CYG_ADDRESS s_base, cyg_uint32 s_size)
{
#ifdef CYGNUM_HAL_STACK_SIZE_MINIMUM
    CYG_ASSERT( s_size >= CYGNUM_HAL_STACK_SIZE_MINIMUM,
                "Stack size too small");
#endif

#ifdef CYGFUN_KERNEL_THREADS_STACK_CHECKING
    {
        cyg_uint32 sig = (cyg_uint32)this;
        cyg_uint32 *base = (cyg_uint32 *)s_base;
        cyg_uint32 *top =  (cyg_uint32 *)(s_base + s_size -
            CYGNUM_KERNEL_THREADS_STACK_CHECK_DATA_SIZE);

        unsigned int i;

        CYG_INSTRUMENT_THREAD(ATTACH_STACK, base, top );
        
        CYG_ASSERT( NULL != base, "stack base non-NULL" );
        CYG_ASSERT( 0 == ((sizeof(CYG_WORD)-1) & (cyg_uint32)base), "stack base alignment" );
        CYG_ASSERT( 0 == ((sizeof(CYG_WORD)-1) & (cyg_uint32)top),  "stack  top alignment" );

        for ( i = 0;
              i < CYGNUM_KERNEL_THREADS_STACK_CHECK_DATA_SIZE/sizeof(cyg_uint32);
              i++ ) {
            base[i] = (sig ^ (i * 0x01010101));
             top[i] = (sig ^ (i * 0x10101010));
        }            
        // This check for overlap of the two signature areas also detects
        // wrap round zero of the size in the unsigned subtraction below.
        CYG_ASSERT( &base[i] < &top[0], "Stack is so small size wrapped" );
        // Use this 'i' expression to round correctly to whole words.
        s_base += i * sizeof(cyg_uint32);
        s_size -= i * sizeof(cyg_uint32) * 2;
        // This is a complete guess, the 256; the point is to assert early that
        // this might go badly wrong.  It would not detect wrap of unsigned size.
        CYG_ASSERT( s_size >= 256,
                    "Stack size too small after allocating checking buffer");
    }
#endif
#ifdef CYGFUN_KERNEL_THREADS_STACK_MEASUREMENT
    {
	CYG_WORD *base = (CYG_WORD *)s_base;
	cyg_uint32 size = s_size/sizeof(CYG_WORD);
	cyg_ucount32 i;

	// initialize all of stack with known value - don't choose 0
	// could do with pseudo value as above, but this way, checking
	// is faster
	for (i=0; i<size; i++) {
		base[i] = 0xDEADBEEF;
	}
	// Don't bother about the case when the stack isn't a multiple of
	// CYG_WORD in size. Since it's at the top of the stack, it will
	// almost certainly be overwritten the instant the thread starts
	// anyway.
    }
#endif
    stack_base = s_base;
    stack_size = s_size;
#ifdef CYGFUN_KERNEL_THREADS_STACK_LIMIT
    stack_limit = s_base;
#endif
    
#ifdef HAL_THREAD_ATTACH_STACK

    HAL_THREAD_ATTACH_STACK(stack_ptr, stack_base, stack_size);
    
#else

    stack_ptr = stack_base + stack_size;

#endif

#ifdef CYGFUN_KERNEL_THREADS_STACK_CHECKING
    check_stack();
#endif
}

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

inline Cyg_HardwareThread::Cyg_HardwareThread(
    cyg_thread_entry        *e_point,   // entry point function
    CYG_ADDRWORD            e_data,     // entry data
    cyg_ucount32            s_size,     // stack size, 0 = use default
    CYG_ADDRESS             s_base      // stack base, NULL = allocate
)
{
    entry_point = e_point;
    entry_data  = e_data;
#ifdef CYGDBG_KERNEL_DEBUG_GDB_THREAD_SUPPORT
    saved_context = 0;
#endif
    
    attach_stack( s_base, s_size );
};

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

#ifdef CYGDBG_KERNEL_DEBUG_GDB_THREAD_SUPPORT

// Return the current saved state for this thread.
inline HAL_SavedRegisters *Cyg_HardwareThread::get_saved_context()
{
    HAL_SavedRegisters *regs;
    if( saved_context != 0 ) regs = saved_context;
    else HAL_THREAD_GET_SAVED_REGISTERS( stack_ptr, regs );
    return regs;
}

inline void Cyg_HardwareThread::set_saved_context(HAL_SavedRegisters *ctx)
{
    saved_context = ctx;
}

#endif

// -------------------------------------------------------------------------
// (declare this inline before its first use)

inline cyg_uint16 Cyg_Thread::get_unique_id()
{
    return unique_id;
}

// -------------------------------------------------------------------------
// Initialize the context of this thread.

inline void Cyg_HardwareThread::init_context(Cyg_Thread *thread)
{
#ifdef CYGPKG_INFRA_DEBUG
    cyg_uint32 threadid = thread->get_unique_id()*0x01010000;
#else
    cyg_uint32 threadid = 0x11110000;
#endif
    HAL_THREAD_INIT_CONTEXT( stack_ptr, thread, thread_entry, threadid );
}



// -------------------------------------------------------------------------
// Save current thread's context and load that of the given next thread.
// This function is only really here for completeness, the
// kernel generally calls the HAL macros directly.

inline void Cyg_HardwareThread::switch_context(Cyg_HardwareThread *next)
{
    HAL_THREAD_SWITCH_CONTEXT( &stack_ptr, &next->stack_ptr );
}

// -------------------------------------------------------------------------
// Get and set entry_data.

inline void Cyg_HardwareThread::set_entry_data( CYG_ADDRWORD data )
{
    entry_data = data;
}

inline CYG_ADDRWORD Cyg_HardwareThread::get_entry_data()
{
    return entry_data;
}

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

⌨️ 快捷键说明

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