mirror of
https://github.com/apache/nuttx.git
synced 2026-05-31 14:17:13 +08:00
arch/sparc add support of spinlock for LEON3 and LEON4
This commit is contained in:
@@ -44,12 +44,10 @@
|
||||
|
||||
/* The Type of a spinlock.
|
||||
*
|
||||
* This must be a uint32_ becaue it will be set using S32C1I instruction.
|
||||
* That instruction atomically stores to a memory location only if its
|
||||
* current value is the expected one. The state register (SCOMPARE1) is
|
||||
* used to provide the additional comparison operand. Some implementations
|
||||
* also have a state register (ATOMCTL) for further control of the atomic
|
||||
* operation in cache and on the PIF bus.
|
||||
* This must be a uint32_ becaue it will be set using CASA instruction.
|
||||
* That instruction atomically Compare the 32-bitvalues in the register
|
||||
* and memory, if its current value is the expected one. swap the values
|
||||
* of second register with the memory.
|
||||
*/
|
||||
|
||||
typedef uint32_t spinlock_t;
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
|
||||
#include <nuttx/spinlock.h>
|
||||
#include "up_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
@@ -61,11 +61,11 @@ void modifyreg16(unsigned int addr, uint16_t clearbits, uint16_t setbits)
|
||||
irqstate_t flags;
|
||||
uint16_t regval;
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(NULL);
|
||||
regval = getreg16(addr);
|
||||
regval &= ~clearbits;
|
||||
regval |= setbits;
|
||||
putreg16(regval, addr);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(NULL, flags);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
|
||||
#include <nuttx/spinlock.h>
|
||||
#include "up_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
@@ -61,11 +61,11 @@ void modifyreg32(unsigned int addr, uint32_t clearbits, uint32_t setbits)
|
||||
irqstate_t flags;
|
||||
uint32_t regval;
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(NULL);
|
||||
regval = getreg32(addr);
|
||||
regval &= ~clearbits;
|
||||
regval |= setbits;
|
||||
putreg32(regval, addr);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(NULL, flags);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
|
||||
#include <nuttx/spinlock.h>
|
||||
#include "up_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
@@ -61,11 +61,11 @@ void modifyreg8(unsigned int addr, uint8_t clearbits, uint8_t setbits)
|
||||
irqstate_t flags;
|
||||
uint8_t regval;
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(NULL);
|
||||
regval = getreg8(addr);
|
||||
regval &= ~clearbits;
|
||||
regval |= setbits;
|
||||
putreg8(regval, addr);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(NULL, flags);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
/****************************************************************************
|
||||
* arch/sparc/src/common/up_testset.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#ifdef CONFIG_SPINLOCK
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sparc_compareset
|
||||
*
|
||||
* Description:
|
||||
* Wrapper for the Sparc compare-and-swap instruction. This function will
|
||||
* atomically compare *addr to compare, and if it's the same, will swap
|
||||
* *addr with set. It will return the value of set which is the old value
|
||||
* of *addr.
|
||||
*
|
||||
* Note: The ldstub and swap instructions are available in all LEON
|
||||
* processors, while casa is optional. The CASA is a SPARC-V9 Compare and
|
||||
* Swap Alternative instruction but LEON3(GR712R) and LEON4 implements the
|
||||
* SPARC V9 Compare and Swap Alternative (CASA) instruction. The CASA
|
||||
* operates as described in the SPARC-V9 manual. This instruction is
|
||||
* privileged, except when setting ASI = 0xA (user data). All multi-core
|
||||
* LEON based components from Cobham Gaisler have casa. According to BCC
|
||||
* User's Manual the GCC option -mcpu=leon3 is required to generate SPARC-V8
|
||||
* code but support for the casa instruction.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline uint32_t sparc_compareset(volatile uint32_t *addr,
|
||||
uint32_t compare,
|
||||
uint32_t set)
|
||||
{
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"casa [%2] 0xb, %3, %0\n" /* Atomically compare [%2] to %3, and swap
|
||||
* [%2] with %0 if the lock is the same as
|
||||
* compare, otherwise, no write-access.
|
||||
*/
|
||||
: "=&r" (set) : "0" (set), "r" (addr), "r" (compare) : "memory"
|
||||
);
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_testset
|
||||
*
|
||||
* Description:
|
||||
* Perform an atomic compare and swap operation on the provided spinlock.
|
||||
*
|
||||
* This function must be provided via the architecture-specific logic.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lock - A reference to the spinlock object.
|
||||
*
|
||||
* Returned Value:
|
||||
* The spinlock is always locked upon return. The previous value of the
|
||||
* spinlock variable is returned, either SP_LOCKED if the spinlock was
|
||||
* previously locked (meaning that the test-and-set operation failed to
|
||||
* obtain the lock) or SP_UNLOCKED if the spinlock was previously unlocked
|
||||
* (meaning that we successfully obtained the lock).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
spinlock_t up_testset(volatile spinlock_t *lock)
|
||||
{
|
||||
/* Perform the 32-bit compare and set operation */
|
||||
|
||||
return sparc_compareset((volatile uint32_t *)lock,
|
||||
SP_UNLOCKED, SP_LOCKED);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SPINLOCK */
|
||||
Reference in New Issue
Block a user