Close #2695. --- cpukit/score/Makefile.am | 1 + cpukit/score/cpu/sparc/Makefile.am | 1 - cpukit/score/cpu/sparc/sparcv8-atomic.c | 211 -------------------------------- cpukit/score/src/libatomic.c | 79 ++++++++++++ 4 files changed, 80 insertions(+), 212 deletions(-) delete mode 100644 cpukit/score/cpu/sparc/sparcv8-atomic.c create mode 100644 cpukit/score/src/libatomic.c
diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am index 455c99d..566182f 100644 --- a/cpukit/score/Makefile.am +++ b/cpukit/score/Makefile.am @@ -361,6 +361,7 @@ libscore_a_SOURCES += src/sched.c libscore_a_SOURCES += src/semaphore.c libscore_a_SOURCES += src/smpbarrierwait.c libscore_a_SOURCES += src/kern_tc.c +libscore_a_SOURCES += src/libatomic.c EXTRA_DIST = src/Unlimited.txt diff --git a/cpukit/score/cpu/sparc/Makefile.am b/cpukit/score/cpu/sparc/Makefile.am index 8cf4f4a..edebbb6 100644 --- a/cpukit/score/cpu/sparc/Makefile.am +++ b/cpukit/score/cpu/sparc/Makefile.am @@ -14,7 +14,6 @@ libscorecpu_a_SOURCES = cpu.c cpu_asm.S libscorecpu_a_SOURCES += sparc-context-volatile-clobber.S libscorecpu_a_SOURCES += sparc-context-validate.S libscorecpu_a_SOURCES += sparc-counter.c -libscorecpu_a_SOURCES += sparcv8-atomic.c libscorecpu_a_CPPFLAGS = $(AM_CPPFLAGS) include $(srcdir)/preinstall.am diff --git a/cpukit/score/cpu/sparc/sparcv8-atomic.c b/cpukit/score/cpu/sparc/sparcv8-atomic.c deleted file mode 100644 index 2b3bdbc..0000000 --- a/cpukit/score/cpu/sparc/sparcv8-atomic.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (c) 2014-2015 embedded brains GmbH. All rights reserved. - * - * embedded brains GmbH - * Dornierstr. 4 - * 82178 Puchheim - * Germany - * <rt...@embedded-brains.de> - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include <rtems/score/cpuopts.h> -#include <rtems/score/isrlevel.h> - -/* - * This file is a dirty hack. A proper solution would be to add RTEMS support - * for libatomic in GCC (see also libatomic/configure.tgt). - */ - -#if defined(RTEMS_SMP) -static volatile uint32_t _SPARCV8_The_one_lock; - -static inline uint32_t _SPARCV8_Atomic_swap( - volatile uint32_t *address, - uint32_t value -) -{ - asm volatile ( - "swap [%2], %0" - : "=r" (value) - : "0" (value), "r" (address) - : "memory" - ); - - return value; -} -#endif - -static ISR_Level _SPARCV8_Acquire_the_one_lock( void ) -{ - ISR_Level level; - - _ISR_Disable_without_giant( level ); - -#if defined(RTEMS_SMP) - do { - while ( _SPARCV8_The_one_lock ) { - /* Wait */ - } - } while ( _SPARCV8_Atomic_swap( &_SPARCV8_The_one_lock, 1 ) ); -#endif - - return level; -} - -static void _SPARCV8_Release_the_one_lock( ISR_Level level ) -{ -#if defined(RTEMS_SMP) - _SPARCV8_The_one_lock = 0; -#endif - _ISR_Enable_without_giant( level ); -} - -uint8_t __atomic_exchange_1( uint8_t *mem, uint8_t val, int model ) -{ - uint8_t prev; - ISR_Level level; - - level = _SPARCV8_Acquire_the_one_lock(); - - prev = *mem; - *mem = val; - - _SPARCV8_Release_the_one_lock( level ); - - return prev; -} - -/* - * In order to get rid of the warning "conflicting types for built-in function - * '__atomic_compare_exchange_4' [enabled by default]", you must port libatomic - * to SPARC/RTEMS. The libatomic is provided by GCC. - */ -uint32_t __atomic_exchange_4( uint32_t *mem, uint32_t val, int model ) -{ - uint32_t prev; - ISR_Level level; - - level = _SPARCV8_Acquire_the_one_lock(); - - prev = *mem; - *mem = val; - - _SPARCV8_Release_the_one_lock( level ); - - return prev; -} - -/* - * You get probably a warning here which can be ignored: "warning: conflicting - * types for built-in function '__atomic_compare_exchange_4' [enabled by - * default]" - */ -bool __atomic_compare_exchange_4( - uint32_t *mem, - uint32_t *expected, - uint32_t desired, - int success, - int failure -) -{ - bool equal; - ISR_Level level; - uint32_t actual; - - level = _SPARCV8_Acquire_the_one_lock(); - - actual = *mem; - equal = ( actual == *expected ); - if ( equal ) { - *mem = desired; - } else { - *expected = actual; - } - - _SPARCV8_Release_the_one_lock( level ); - - return equal; -} - -uint32_t __atomic_fetch_add_4( uint32_t *mem, uint32_t val, int model ) -{ - uint32_t prev; - ISR_Level level; - - level = _SPARCV8_Acquire_the_one_lock(); - - prev = *mem; - *mem = prev + val; - - _SPARCV8_Release_the_one_lock( level ); - - return prev; -} - -uint32_t __atomic_fetch_sub_4( uint32_t *mem, uint32_t val, int model ) -{ - uint32_t prev; - ISR_Level level; - - level = _SPARCV8_Acquire_the_one_lock(); - - prev = *mem; - *mem = prev - val; - - _SPARCV8_Release_the_one_lock( level ); - - return prev; -} - -uint32_t __atomic_fetch_and_4( uint32_t *mem, uint32_t val, int model ) -{ - uint32_t prev; - ISR_Level level; - - level = _SPARCV8_Acquire_the_one_lock(); - - prev = *mem; - *mem = prev & val; - - _SPARCV8_Release_the_one_lock( level ); - - return prev; -} - -uint32_t __atomic_fetch_or_4( uint32_t *mem, uint32_t val, int model ) -{ - uint32_t prev; - ISR_Level level; - - level = _SPARCV8_Acquire_the_one_lock(); - - prev = *mem; - *mem = prev | val; - - _SPARCV8_Release_the_one_lock( level ); - - return prev; -} - -uint32_t __atomic_fetch_xor_4( uint32_t *mem, uint32_t val, int model ) -{ - uint32_t prev; - ISR_Level level; - - level = _SPARCV8_Acquire_the_one_lock(); - - prev = *mem; - *mem = prev ^ val; - - _SPARCV8_Release_the_one_lock( level ); - - return prev; -} diff --git a/cpukit/score/src/libatomic.c b/cpukit/score/src/libatomic.c new file mode 100644 index 0000000..871b2c2 --- /dev/null +++ b/cpukit/score/src/libatomic.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2016 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rt...@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <machine/_libatomic.h> + +#include <rtems/score/apimutex.h> +#include <rtems/score/atomic.h> +#include <rtems/score/isrlevel.h> + +#if defined(RTEMS_SMP) +/* + * For real SMP targets this is not useful. The main purpose is support for + * testing on simulators like SIS. + */ +static Atomic_Flag _Libatomic_The_one_lock = ATOMIC_INITIALIZER_FLAG; +#endif + +__uint32_t _Libatomic_Protect_start( void *ptr ) +{ + ISR_Level isr_level; + + (void) ptr; + _ISR_Disable_without_giant( isr_level ); + +#if defined(RTEMS_SMP) + while ( + _Atomic_Flag_test_and_set( &_Libatomic_The_one_lock, ATOMIC_ORDER_SEQ_CST ) + ) { + /* Next try. Yes, a TAS spin lock implementation is stupid. */ + } +#endif + + return isr_level; +} + +void _Libatomic_Protect_end( void *ptr, __uint32_t isr_level ) +{ + (void) ptr; + +#if defined(RTEMS_SMP) + _Atomic_Flag_clear( &_Libatomic_The_one_lock, ATOMIC_ORDER_SEQ_CST ); +#endif + + _ISR_Enable_without_giant( isr_level ); +} + +/* + * FIXME: The once lock should be only a temporary solution. We need a + * dedicated internal mutex for this. + */ + +void _Libatomic_Lock_n( void *ptr, __size_t n ) +{ + (void) ptr; + (void) n; + _Once_Lock(); +} + +void _Libatomic_Unlock_n( void *ptr, __size_t n ) +{ + (void) ptr; + (void) n; + _Once_Unlock(); +} -- 1.8.4.5 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel