mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-24 22:13:52 +01:00
cpu/esp32: workaround for static object init
This commit is contained in:
parent
b9a01437be
commit
7b160a7dd3
@ -7,6 +7,10 @@ DIRS += periph
|
||||
DIRS += freertos
|
||||
DIRS += vendor
|
||||
|
||||
ifneq (, $(filter esp_cxx, $(USEMODULE)))
|
||||
DIRS += cxx
|
||||
endif
|
||||
|
||||
ifneq (, $(filter esp_can, $(USEMODULE)))
|
||||
DIRS += esp-can
|
||||
endif
|
||||
|
||||
@ -33,6 +33,10 @@ ifneq (,$(findstring core_thread_flags,$(USEMODULE)))
|
||||
USEMODULE += pthread
|
||||
endif
|
||||
|
||||
ifneq (,$(filter cpp,$(FEATURES_USED)))
|
||||
USEMODULE += esp_cxx
|
||||
endif
|
||||
|
||||
ifneq (,$(filter esp_gdbstub,$(USEMODULE)))
|
||||
USEMODULE += esp_gdb
|
||||
endif
|
||||
@ -142,6 +146,10 @@ LINKFLAGS += -T$(RIOTCPU)/$(CPU)/ld/esp32.rom.ld
|
||||
LINKFLAGS += -T$(RIOTCPU)/$(CPU)/ld/esp32.rom.nanofmt.ld
|
||||
LINKFLAGS += -nostdlib -lgcc -Wl,-gc-sections
|
||||
|
||||
ifneq (,$(filter esp_cxx,$(USEMODULE)))
|
||||
UNDEF += $(BINDIR)/esp_cxx/cxa_guard.o
|
||||
endif
|
||||
|
||||
# The ELFFILE is the base one used for flashing
|
||||
FLASHFILE ?= $(ELFFILE)
|
||||
|
||||
|
||||
3
cpu/esp32/cxx/Makefile
Normal file
3
cpu/esp32/cxx/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
MODULE=esp_cxx
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
||||
111
cpu/esp32/cxx/cxa_guard.cpp
Normal file
111
cpu/esp32/cxx/cxa_guard.cpp
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Gunar Schorcht
|
||||
*
|
||||
* 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 cpu_esp32_cxx
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief C++ functions for guarded initialization of static variables
|
||||
*
|
||||
* @author Gunar Schorcht <gunar@schorcht.net>
|
||||
*
|
||||
* This module implements very basic versions of the glibc++ functions
|
||||
* `__cxa_guard_acquire` and `__cxa_guard_release`. These functions operate
|
||||
* on guard variables that are used to realize thread-safe static object
|
||||
* initialization.
|
||||
*
|
||||
* The glibc++ built-in versions of these functions had to be replaced since
|
||||
* they use the `pthread_once` function from module `pthread` for singleton
|
||||
* objects initialization where the parameter `once` is of incompatible type.
|
||||
*
|
||||
* The functions implemented by this module don't use a global mutex to
|
||||
* avoid deadlocks. Instead, within the initialization of a static variable,
|
||||
* creating a thread that in turn tries to initialize the same static variable
|
||||
* is not allowed and results in an abort.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <cxxabi.h>
|
||||
|
||||
#include "assert.h"
|
||||
#include "esp_common_log.h"
|
||||
#include "irq.h"
|
||||
#include "irq_arch.h"
|
||||
#include "mutex.h"
|
||||
|
||||
/**
|
||||
* Structure of guard variable in glibc++
|
||||
* ((char*)&__guard)[0] == 1: _GLIBCXX_GUARD_BIT (static variable already initialized)
|
||||
* ((char*)&__guard)[1] == 1: _GLIBCXX_GUARD_PENDING_BIT (static variable is being initialized)
|
||||
* ((char*)&__guard)[2] == 1: _GLIBCXX_GUARD_WAITING_BIT (other thread is waiting)
|
||||
*/
|
||||
typedef struct {
|
||||
char done; /* initialization is already done */
|
||||
char pending; /* initialization is in progress */
|
||||
char waiting; /* another thread is waiting until initialization is finished */
|
||||
} guard_t;
|
||||
|
||||
namespace __cxxabiv1
|
||||
{
|
||||
extern "C"
|
||||
int __cxa_guard_acquire (__guard *g)
|
||||
{
|
||||
guard_t *_gt = (guard_t *)g;
|
||||
|
||||
assert(_gt);
|
||||
|
||||
/* return if the static object is already initialized */
|
||||
if (_gt->done) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
critical_enter();
|
||||
|
||||
/* if another thread is already initializing the static object */
|
||||
if (_gt->pending) {
|
||||
critical_exit();
|
||||
LOG_ERROR("Recursive static object initialization\n");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/* mark the initialization in process and aquire */
|
||||
_gt->pending = 1;
|
||||
|
||||
critical_exit();
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void __cxa_guard_release (__guard *g)
|
||||
{
|
||||
guard_t *_gt = (guard_t *)g;
|
||||
|
||||
assert(_gt);
|
||||
assert(_gt->pending);
|
||||
|
||||
critical_enter();
|
||||
|
||||
_gt->done = 1;
|
||||
_gt->pending = 0;
|
||||
|
||||
critical_exit();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void __cxa_guard_abort (__guard *g)
|
||||
{
|
||||
guard_t *_gt = (guard_t *)g;
|
||||
|
||||
assert(_gt);
|
||||
assert(_gt->pending);
|
||||
|
||||
_gt->pending = 0;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user