mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
sys/malloc_thread_safe: split out of cpu/atmega_common
Split out Gunar Schorcht's clever approach to provide thread safe malloc for AVR into a system module and make AVR depend on this. This allows other platforms to also use this.
This commit is contained in:
parent
c9d63c9f4f
commit
902aa29b62
@ -7,6 +7,11 @@ USEMODULE += atmega_common
|
||||
# peripheral drivers are linked into the final binary
|
||||
USEMODULE += atmega_common_periph
|
||||
|
||||
# The AVR-libc provides no thread safe malloc implementation and has no hooks
|
||||
# to inject. Use malloc_thread_safe to link calls to malloc to safe wrappers
|
||||
# instead.
|
||||
USEMODULE += malloc_thread_safe
|
||||
|
||||
# the atmel port uses stdio_uart by default
|
||||
ifeq (,$(filter stdio_% slipdev_stdio,$(USEMODULE)))
|
||||
USEMODULE += stdio_uart
|
||||
|
@ -177,45 +177,4 @@ ssize_t write(int fd, const void *src, size_t count)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Following functions are wrappers around the according avr-libc system
|
||||
* functions to avoid their preemption by disabling the interrupts for the
|
||||
* time of their execution.
|
||||
*/
|
||||
extern void *__real_malloc(size_t size);
|
||||
extern void __real_free(void *ptr);
|
||||
extern void *__real_calloc(size_t nmemb, size_t size);
|
||||
extern void *__real_realloc(void *ptr, size_t size);
|
||||
|
||||
void *__wrap_malloc(size_t size)
|
||||
{
|
||||
unsigned state = irq_disable();
|
||||
void *ptr = __real_malloc(size);
|
||||
irq_restore(state);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void __wrap_free(void *ptr)
|
||||
{
|
||||
unsigned state = irq_disable();
|
||||
__real_free(ptr);
|
||||
irq_restore(state);
|
||||
}
|
||||
|
||||
void *__wrap_calloc(size_t nmemb, size_t size)
|
||||
{
|
||||
unsigned state = irq_disable();
|
||||
void *ptr = __real_calloc(nmemb, size);
|
||||
irq_restore(state);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *__wrap_realloc(void *ptr, size_t size)
|
||||
{
|
||||
unsigned state = irq_disable();
|
||||
void *new = __real_realloc(ptr, size);
|
||||
irq_restore(state);
|
||||
return new;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
@ -23,9 +23,6 @@ LDSCRIPT_COMPAT = $(if $(shell $(TARGET_ARCH)-ld --verbose | grep __TEXT_REGION_
|
||||
-T$(RIOTCPU)/$(CPU)/ldscripts_compat/avr_2.26.ld)
|
||||
LINKFLAGS += $(LDSCRIPT_COMPAT)
|
||||
|
||||
# use the wrapper functions for following avr-libc functions
|
||||
LINKFLAGS += -Wl,-wrap=malloc -Wl,-wrap=calloc -Wl,-wrap=realloc -Wl,-wrap=free
|
||||
|
||||
ifeq ($(LTO),1)
|
||||
# avr-gcc <4.8.3 has a bug when using LTO which causes a warning to be printed always:
|
||||
# '_vector_25' appears to be a misspelled signal handler [enabled by default]
|
||||
|
@ -17,6 +17,7 @@ rsource "entropy_source/Kconfig"
|
||||
rsource "event/Kconfig"
|
||||
rsource "fmt/Kconfig"
|
||||
rsource "isrpipe/Kconfig"
|
||||
rsource "malloc_thread_safe/Kconfig"
|
||||
rsource "net/Kconfig"
|
||||
rsource "Kconfig.newlib"
|
||||
rsource "Kconfig.stdio"
|
||||
|
@ -21,6 +21,10 @@ ifneq (,$(filter gnrc_pktbuf,$(USEMODULE)))
|
||||
include $(RIOTBASE)/sys/net/gnrc/pktbuf/Makefile.include
|
||||
endif
|
||||
|
||||
ifneq (,$(filter malloc_thread_safe,$(USEMODULE)))
|
||||
include $(RIOTBASE)/sys/malloc_thread_safe/Makefile.include
|
||||
endif
|
||||
|
||||
ifneq (,$(filter posix_headers,$(USEMODULE)))
|
||||
USEMODULE_INCLUDES += $(RIOTBASE)/sys/posix/include
|
||||
endif
|
||||
|
18
sys/malloc_thread_safe/Kconfig
Normal file
18
sys/malloc_thread_safe/Kconfig
Normal file
@ -0,0 +1,18 @@
|
||||
# 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.
|
||||
#
|
||||
|
||||
config MODULE_MALLOC_THREAD_SAFE
|
||||
bool
|
||||
depends on TEST_KCONFIG
|
||||
help
|
||||
This module provides wrappers for malloc(), calloc(), realloc(), and
|
||||
free() which guarantee mutually exclusive access to heap data
|
||||
structures. This linker is also instructed to redirect all calls to
|
||||
the corresponding wrappers. As a result, all allocations become thread
|
||||
safe without touching the application code or the c library. This module
|
||||
is intended to be pulled in automatically if needed. Hence, applications
|
||||
never should manually use it.
|
1
sys/malloc_thread_safe/Makefile
Normal file
1
sys/malloc_thread_safe/Makefile
Normal file
@ -0,0 +1 @@
|
||||
include $(RIOTBASE)/Makefile.base
|
2
sys/malloc_thread_safe/Makefile.include
Normal file
2
sys/malloc_thread_safe/Makefile.include
Normal file
@ -0,0 +1,2 @@
|
||||
# use the wrapper functions for malloc and friends to provide thread-safety
|
||||
LINKFLAGS += -Wl,-wrap=malloc -Wl,-wrap=calloc -Wl,-wrap=realloc -Wl,-wrap=free
|
26
sys/malloc_thread_safe/doc.txt
Normal file
26
sys/malloc_thread_safe/doc.txt
Normal file
@ -0,0 +1,26 @@
|
||||
/**
|
||||
@defgroup sys_malloc_ts Thread-safe wrappers for malloc and friends
|
||||
@ingroup sys
|
||||
@brief This module provides wrappers for malloc, calloc, realloc and free
|
||||
that provide mutually exclusive access to those functions.
|
||||
@warning This module is automatically selected, if needed. Never add it
|
||||
manually.
|
||||
|
||||
# Background
|
||||
|
||||
Without support of the OS (or resorting to disabling IRQs), the standard C
|
||||
library is unable to guarantee that at most one thread at a time accesses the
|
||||
heap management data structures. Some C libraries provide hooks for locking
|
||||
(e.g. picolibc and newlib do so optionally), others (e.g. AVR libc) don't.
|
||||
By providing wrapper functions for `malloc()` and friends and instructing the
|
||||
linker to link to those instead of their actual implementations, we can provide
|
||||
thread safe access to the heap regardless of C libraries support.
|
||||
|
||||
|
||||
# Usage
|
||||
|
||||
This module is intended to be use by platforms not providing the required
|
||||
locking with other means automatically. Hence, application developers and users
|
||||
should never select this module by hand.
|
||||
|
||||
*/
|
55
sys/malloc_thread_safe/malloc_wrappers.c
Normal file
55
sys/malloc_thread_safe/malloc_wrappers.c
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Implements various POSIX syscalls
|
||||
* @author Gunar Schorcht <gunar@schorcht.net>
|
||||
*/
|
||||
|
||||
#include "irq.h"
|
||||
|
||||
extern void *__real_malloc(size_t size);
|
||||
extern void __real_free(void *ptr);
|
||||
extern void *__real_calloc(size_t nmemb, size_t size);
|
||||
extern void *__real_realloc(void *ptr, size_t size);
|
||||
|
||||
void *__wrap_malloc(size_t size)
|
||||
{
|
||||
unsigned state = irq_disable();
|
||||
void *ptr = __real_malloc(size);
|
||||
irq_restore(state);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void __wrap_free(void *ptr)
|
||||
{
|
||||
unsigned state = irq_disable();
|
||||
__real_free(ptr);
|
||||
irq_restore(state);
|
||||
}
|
||||
|
||||
void *__wrap_calloc(size_t nmemb, size_t size)
|
||||
{
|
||||
unsigned state = irq_disable();
|
||||
void *ptr = __real_calloc(nmemb, size);
|
||||
irq_restore(state);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *__wrap_realloc(void *ptr, size_t size)
|
||||
{
|
||||
unsigned state = irq_disable();
|
||||
void *new = __real_realloc(ptr, size);
|
||||
irq_restore(state);
|
||||
return new;
|
||||
}
|
||||
|
||||
/** @} */
|
Loading…
Reference in New Issue
Block a user