mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
6520db8ed9
For thread-safe calling of C++ constructs of statically allocated class instances some platform support code is needed. This commit ads one implementation compatible with g++.
83 lines
2.3 KiB
C
83 lines
2.3 KiB
C
/*
|
|
* Copyright (C) 2020 Otto-von-Guericke-Universität Magdeburg
|
|
*
|
|
* This file is subject to the terms and conditions of the GNU Lesser
|
|
* General Public License v2.1. See the file LICENSE in the top level
|
|
* directory for more details.
|
|
*/
|
|
|
|
/**
|
|
* @ingroup sys_cxx_ctor_guards
|
|
* @{
|
|
*
|
|
* @file
|
|
* @brief Implementation of the C++ ctor guards
|
|
*
|
|
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
|
|
*/
|
|
|
|
#include "test_utils/expect.h"
|
|
#include "rmutex.h"
|
|
|
|
#ifdef CXX_CTOR_GUARDS_CUSTOM_TYPE
|
|
/* Some architectures (such as ARM) have custom types for __guard in their
|
|
* ABI defined. To support such cases, a custom header can be provided and
|
|
* `CXX_CTOR_GUARDS_CUSTOM_TYPE` can be defined */
|
|
#include "cxx_ctor_guards_arch.h"
|
|
#else
|
|
/* The ABI for"generic" CPUs defines __guard as follows:
|
|
* (see "libstdc++-v3/config/cpu/generic/cxxabi_tweaks.h" in GCC source) */
|
|
__extension__ typedef int __guard __attribute__((mode(__DI__)));
|
|
/* Above is just a fancy version of `typedef int64_t __guard`. But let's stick
|
|
* with the official type definition */
|
|
#endif
|
|
|
|
#define GUARD_DONE 0x01
|
|
#define GUARD_PENDING 0x02
|
|
|
|
/* A recursive mutex is needed, as the initialization of a static class could
|
|
* require calling ctors of members of that class. With a regular mutex, this
|
|
* would result in a deadlock.
|
|
*/
|
|
static rmutex_t cxa_rmutex = RMUTEX_INIT;
|
|
|
|
int __cxa_guard_acquire(__guard *g)
|
|
{
|
|
uint8_t *guard = (uint8_t *)g;
|
|
/* Optimize for the case that the instance is already initialized by
|
|
* doing a lock-free check. */
|
|
if (__atomic_load_1(guard, __ATOMIC_SEQ_CST) & GUARD_DONE) {
|
|
return 0;
|
|
}
|
|
|
|
rmutex_lock(&cxa_rmutex);
|
|
/* Check again (this time protected by the rmutex) for the instance being
|
|
* already initialized */
|
|
if (*guard & GUARD_DONE) {
|
|
rmutex_unlock(&cxa_rmutex);
|
|
return 0;
|
|
}
|
|
|
|
if (*guard & GUARD_PENDING) {
|
|
/* Recursive initialization of the *same* instance --> bug */
|
|
expect(0);
|
|
}
|
|
|
|
*guard = GUARD_PENDING;
|
|
return 1;
|
|
}
|
|
|
|
void __cxa_guard_release(__guard *g)
|
|
{
|
|
uint8_t *guard = (uint8_t *)g;
|
|
*guard = GUARD_DONE;
|
|
rmutex_unlock(&cxa_rmutex);
|
|
}
|
|
|
|
void __cxa_guard_abort(__guard *g)
|
|
{
|
|
uint8_t *guard = (uint8_t *)g;
|
|
*guard = 0;
|
|
rmutex_unlock(&cxa_rmutex);
|
|
}
|