From 19805483df6722f8bacb51183ec05ad23a75506a Mon Sep 17 00:00:00 2001 From: Alexey Guseynov Date: Mon, 13 Nov 2017 14:37:00 +0100 Subject: [PATCH] Correct implementation of gcc specific internal functions Last bit not implemented by a4496b927bb7889ed076e7b7f0cc27fa0c4b9b75 Squash and rebase of https://github.com/arduino/Arduino/pull/108 --- cores/arduino/abi.cpp | 60 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 11 deletions(-) diff --git a/cores/arduino/abi.cpp b/cores/arduino/abi.cpp index 8d719b8..f4f473b 100644 --- a/cores/arduino/abi.cpp +++ b/cores/arduino/abi.cpp @@ -15,21 +15,59 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include +#include +#include -#include +#include +#include -extern "C" void __cxa_pure_virtual(void) __attribute__ ((__noreturn__)); -extern "C" void __cxa_deleted_virtual(void) __attribute__ ((__noreturn__)); +namespace { +// guard is an integer type big enough to hold flag and a mutex. +// By default gcc uses long long int and avr ABI does not change it +// So we have 32 or 64 bits available. Actually, we need 16. + +inline char& flag_part(__guard *g) { + return *(reinterpret_cast(g)); +} + +inline uint8_t& sreg_part(__guard *g) { + return *(reinterpret_cast(g) + sizeof(char)); +} +} + +int __cxa_guard_acquire(__guard *g) { + uint8_t oldSREG = SREG; + cli(); + // Initialization of static variable has to be done with blocked interrupts + // because if this function is called from interrupt and sees that somebody + // else is already doing initialization it MUST wait until initializations + // is complete. That's impossible. + // If you don't want this overhead compile with -fno-threadsafe-statics + if (flag_part(g)) { + SREG = oldSREG; + return false; + } else { + sreg_part(g) = oldSREG; + return true; + } +} + +void __cxa_guard_release (__guard *g) { + flag_part(g) = 1; + SREG = sreg_part(g); +} + +void __cxa_guard_abort (__guard *g) { + SREG = sreg_part(g); +} void __cxa_pure_virtual(void) { - // We might want to write some diagnostics to uart in this case - //std::terminate(); - abort(); + // We might want to write some diagnostics to uart in this case + std::terminate(); } void __cxa_deleted_virtual(void) { - // We might want to write some diagnostics to uart in this case - //std::terminate(); - abort(); -} - + // We might want to write some diagnostics to uart in this case + std::terminate(); +} \ No newline at end of file