📄 smp.hxx
字号:
#ifndef CYGONCE_KERNEL_SMP_HXX
#define CYGONCE_KERNEL_SMP_HXX
//==========================================================================
//
// smp.hxx
//
// SMP kernel support
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// 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: 2001-02-10
// Purpose: Kernel SMP support
// Description: If SMP support is configured into the kernel, then this file
// translates HAL defined macros into C and C++ classes and methods
// that can be called from the rest of the kernel. If SMP is not
// configured in, then the same classes and methods are defined here
// to operate correctly in a single CPU configuration.
//
// Usage: #include <cyg/kernel/smp.hxx>
//
//####DESCRIPTIONEND####
//
//==========================================================================
#include <cyg/kernel/ktypes.h>
#include <cyg/infra/cyg_ass.h> // assertion macros
#include <cyg/hal/hal_intr.h> // HAL_DISABLE_INTERRUPTS() etc.
#include <cyg/kernel/instrmnt.h>
//==========================================================================
#if defined(CYGPKG_KERNEL_SMP_SUPPORT) && (CYGPKG_HAL_SMP_SUPPORT)
//==========================================================================
// SMP support is included
#define CYG_KERNEL_SMP_ENABLED
// -------------------------------------------------------------------------
// Get HAL support
#include <cyg/hal/hal_smp.h>
// -------------------------------------------------------------------------
// Defined values
// These all just map straight through to the HAL.
#define CYGNUM_KERNEL_CPU_MAX HAL_SMP_CPU_MAX
#define CYG_KERNEL_CPU_COUNT() HAL_SMP_CPU_COUNT()
#define CYG_KERNEL_CPU_THIS() HAL_SMP_CPU_THIS()
#define CYG_KERNEL_CPU_NONE HAL_SMP_CPU_NONE
// -------------------------------------------------------------------------
// CPU control
#define CYG_KERNEL_CPU_START( __cpu ) HAL_SMP_CPU_START( __cpu )
#define CYG_KERNEL_CPU_RESCHEDULE_INTERRUPT( __cpu, __wait ) \
HAL_SMP_CPU_RESCHEDULE_INTERRUPT( __cpu, __wait )
#define CYG_KERNEL_CPU_TIMESLICE_INTERRUPT( __cpu, __wait ) \
HAL_SMP_CPU_TIMESLICE_INTERRUPT( __cpu, __wait )
// -------------------------------------------------------------------------
// Scheduler lock default implementation.
// This implementation should serve for most targets. However, some
// targets may have hardware or other features that make simple
// spinlocks impossible, or allow us to implement the scheduler lock
// in a more efficient manner. If that is the case then the HAL will
// implement these macros itself.
#ifndef HAL_SMP_SCHEDLOCK_DATA_TYPE
#define HAL_SMP_SCHEDLOCK_DATA_TYPE struct hal_smp_schedlock_data_type
struct hal_smp_schedlock_data_type {
HAL_SPINLOCK_TYPE spinlock;
volatile HAL_SMP_CPU_TYPE holder;
};
#define HAL_SMP_SCHEDLOCK_INIT( __lock, __data ) \
CYG_MACRO_START \
{ \
__lock = 1; \
HAL_SPINLOCK_CLEAR(__data.spinlock); \
HAL_SPINLOCK_SPIN(__data.spinlock); \
__data.holder = HAL_SMP_CPU_THIS(); \
} \
CYG_MACRO_END
#define HAL_SMP_SCHEDLOCK_INC( __lock, __data ) \
CYG_MACRO_START \
{ \
CYG_INTERRUPT_STATE __state; \
HAL_DISABLE_INTERRUPTS(__state); \
if( __data.holder == HAL_SMP_CPU_THIS() ) \
__lock++; \
else \
{ \
CYG_INSTRUMENT_SMP(LOCK_WAIT,CYG_KERNEL_CPU_THIS(),0); \
HAL_SPINLOCK_SPIN(__data.spinlock); \
__data.holder = HAL_SMP_CPU_THIS(); \
__lock++; \
CYG_INSTRUMENT_SMP(LOCK_GOT,CYG_KERNEL_CPU_THIS(),0); \
} \
HAL_RESTORE_INTERRUPTS(__state); \
} \
CYG_MACRO_END
#define HAL_SMP_SCHEDLOCK_ZERO( __lock, __data ) \
CYG_MACRO_START \
{ \
CYG_INTERRUPT_STATE __state; \
HAL_DISABLE_INTERRUPTS(__state); \
CYG_ASSERT( __data.holder == HAL_SMP_CPU_THIS(), "Zeroing schedlock not owned by me!"); \
__lock = 0; \
__data.holder = HAL_SMP_CPU_NONE; \
HAL_SPINLOCK_CLEAR(__data.spinlock); \
HAL_RESTORE_INTERRUPTS(__state); \
} \
CYG_MACRO_END
#define HAL_SMP_SCHEDLOCK_SET( __lock, __data, __new ) \
CYG_MACRO_START \
{ \
CYG_ASSERT( __data.holder == HAL_SMP_CPU_THIS(), "Setting schedlock not owned by me!"); \
__lock = __new; \
} \
CYG_MACRO_END
#endif
// -------------------------------------------------------------------------
// SpinLock class
// This class supplies a C++ wrapper for the HAL spinlock API.
#ifdef __cplusplus
#ifdef HAL_SPINLOCK_SPIN
class Cyg_SpinLock
{
HAL_SPINLOCK_TYPE lock;
public:
// Constructor, initialize the lock to clear
Cyg_SpinLock() { lock = HAL_SPINLOCK_INIT_CLEAR; };
~Cyg_SpinLock()
{
// CYG_ASSERT( !test(), "spinlock still claimed");
};
// Spin on the lock.
void spin()
{
HAL_SPINLOCK_SPIN(lock);
};
// Clear the lock.
void clear()
{
HAL_SPINLOCK_CLEAR(lock);
};
// Try to claim the lock. Return true if successful, false if not.
cyg_bool trylock()
{
cyg_bool testval;
HAL_SPINLOCK_TRY(lock,testval);
return testval;
};
// Test the current value of the lock
cyg_bool test()
{
cyg_bool testval;
HAL_SPINLOCK_TEST(lock, testval);
return testval;
};
// The following two member functions are only necessary if the
// spinlock is to be used in an ISR.
// Claim the spinlock, but also mask this CPU's interrupts while
// we have it.
void spin_intsave(CYG_INTERRUPT_STATE *state)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -