STM32CubeMX生成的用于C库API多任务调用的MDK, IAR和GCC接口文件
勾选这个:MDK:
/**
******************************************************************************
* @file armlib_lock_glue.c
* @author STMicroelectronics
* @brief Implementation of ARM C library lock interface
*
* @details For more information about which C functions
* need which of these lowlevel functions
* please consult the "Arm C and C++ Libraries and
* Floating-Point Support User Guide"
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2021 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#if !defined(__CC_ARM) && !(defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
#error "armlib_lock_glue.c" should be used with ARM Compilers only
#endif /* !defined(__CC_ARM) && !(defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) */
/* Includes ------------------------------------------------------------------*/
#include <cmsis_compiler.h>
/* Private functions ---------------------------------------------------------*/
/**
* @brief Global Error_Handler
*/
__WEAK void Error_Handler(void)
{
/* Not used if it exists in project */
while (1);
}
#ifdef __MICROLIB
#warning Microlib does not provide mutex locks to guard against code that is not thread safe
#else
/* Includes ------------------------------------------------------------------*/
#include "stm32_lock.h"
/* Private typedef -----------------------------------------------------------*/
typedef void *mutex_t;
struct __lock
{
uint8_t initialized; /**< Flag to indicate that lock is initialized */
LockingData_t lock_data; /**< The locking data */
};
/* Private defines -----------------------------------------------------------*/
/** Maximal number of static allocated locks */
#define MAX_LOCK 8
/* Private macros ------------------------------------------------------------*/
/** Convert pointer to pointer to instance of struct __lock */
#define STM32_GET_LOCK_PTR(mutex_ptr) ((struct __lock *) *(mutex_ptr))
/** See struct __lock definition */
#define STM32_LOCK_PARAMETER(lock_ptr) (&(lock_ptr)->lock_data)
/** See struct __lock definition */
#define STM32_LOCK_INITIALIZED(lock_ptr) ((lock_ptr)->initialized)
/* Private variables ---------------------------------------------------------*/
/** Maximum system locks allowed by armlib */
static struct __lock static_lock;
/** Lock for static_lock array */
static LockingData_t static_list_lock = LOCKING_DATA_INIT;
/* Private functions ---------------------------------------------------------*/
/**
* @brief Thread safety Initialization, called before main
*/
__attribute__ ((constructor)) void __armlib_thread_safety_init()
{
uint32_t index;
/* Mark all system locks as not initialized */
stm32_lock_acquire(&static_list_lock);
for (index = 0; index < STM32_LOCK_ARRAY_SIZE(static_lock); index++)
{
STM32_LOCK_INITIALIZED(&static_lock) = 0;
}
stm32_lock_release(&static_list_lock);
}
/**
* @defgroup _mutex_functions ARM library locks
* @{
*/
/**
* @brief Initialize lock mutex
* @param lock The lock
* @return 0 on failure
*/
__attribute__((used)) int _mutex_initialize(mutex_t *lock)
{
if (lock != NULL)
{
uint32_t index;
stm32_lock_acquire(&static_list_lock);
for (index = 0; index < STM32_LOCK_ARRAY_SIZE(static_lock); index++)
{
if (STM32_LOCK_INITIALIZED(&static_lock) == 0)
{
*lock = &static_lock;
STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) = 1;
stm32_lock_init(STM32_LOCK_PARAMETER(STM32_GET_LOCK_PTR(lock)));
stm32_lock_release(&static_list_lock);
return 1;
}
}
stm32_lock_release(&static_list_lock);
}
/* Not enough mutexes, MAX_LOCK should be incremented */
return 0;
}
/**
* @brief Acquire lock mutex
* @param lock The lock
*/
__attribute__((used)) void _mutex_acquire(mutex_t *lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
stm32_lock_acquire(&static_list_lock);
if (STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) == 1)
{
stm32_lock_acquire(STM32_LOCK_PARAMETER(STM32_GET_LOCK_PTR(lock)));
}
else
{
STM32_LOCK_BLOCK();
}
stm32_lock_release(&static_list_lock);
}
/**
* @brief Release lock mutex
* @param lock The lock
*/
__attribute__((used)) void _mutex_release(mutex_t *lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
stm32_lock_acquire(&static_list_lock);
if (STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) == 1)
{
stm32_lock_release(STM32_LOCK_PARAMETER(STM32_GET_LOCK_PTR(lock)));
}
else
{
STM32_LOCK_BLOCK();
}
stm32_lock_release(&static_list_lock);
}
/**
* @brief Free lock mutex
* @param lock The lock
*/
__attribute__((used)) void _mutex_free(mutex_t *lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
stm32_lock_acquire(&static_list_lock);
if (STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) == 1)
{
STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) = 0;
}
else
{
STM32_LOCK_BLOCK();
}
stm32_lock_release(&static_list_lock);
}
/**
* @}
*/
#endif /* __MICROLIB */
IAR:
/**
******************************************************************************
* @file dlib_lock_glue.c
* @author STMicroelectronics
* @brief Implementation of IAR DLib lock interface
*
* @details
* This file implements locking glue necessary to protect C library
* functions and initialization of local static objects in C++.
* Lock strategies are defined in stm32_lock.h that implements
* different level of thread-safety.
*
* For more information about which C functions
* need which of these lowlevel functions
* please consult the IAR C/C++ Development Guide
* and DLib_Threads.h
*
* @see http://ftp.iar.se/WWWfiles/arm/webic/doc/EWARM_DevelopmentGuide.ENU.pdf
*
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2021 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#ifndef __ICCARM__
#error "dlib_lock_glue.c" should be used with IAR DLib only
#endif /* __ICCARM__ */
/* Includes ------------------------------------------------------------------*/
#include <DLib_Threads.h>
#include <stdio.h>
#include <stdlib.h>
#include "stm32_lock.h"
/* Private functions ---------------------------------------------------------*/
/**
* @brief Global Error_Handler
*/
__WEAK void Error_Handler(void)
{
/* Not used if it exists in project */
while (1);
}
/* Private typedef -----------------------------------------------------------*/
struct __lock
{
uint8_t initialized; /**< Flag to indicate that lock is initialized */
LockingData_t lock_data; /**< The locking data */
};
/* Private macros ------------------------------------------------------------*/
/** Convert pointer to pointer to instance of struct __lock */
#define STM32_GET_LOCK_PTR(iar_Rmtx_ptr) ((struct __lock *) *(iar_Rmtx_ptr))
/** See struct __lock definition */
#define STM32_LOCK_PARAMETER(lock_ptr) (&(lock_ptr)->lock_data)
/** See struct __lock definition */
#define STM32_LOCK_INITIALIZED(lock_ptr) ((lock_ptr)->initialized)
/** Size of array */
#define STM32_LOCK_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)))
/* Private variables ---------------------------------------------------------*/
/** Maximum system locks allowed by DLib */
static __no_init struct __lock static_system_lock;
/** Lock for static_system_lock array */
static LockingData_t static_system_list_lock = LOCKING_DATA_INIT;
#ifdef FOPEN_MAX
/** Maximum file locks allowed by DLib */
static __no_init struct __lock static_file_lock;
/** Lock for static_file_lock array */
static LockingData_t static_file_list_lock = LOCKING_DATA_INIT;
#endif /* FOPEN_MAX */
/* Private functions ---------------------------------------------------------*/
/**
* @brief Thread safety Initialization, called before main
*/
__attribute__ ((constructor)) void __dlib_thread_safety_init()
{
uint32_t index;
/* Mark all system locks as not initialized */
stm32_lock_acquire(&static_system_list_lock);
for (index = 0; index < STM32_LOCK_ARRAY_SIZE(static_system_lock); index++)
{
STM32_LOCK_INITIALIZED(&static_system_lock) = 0;
}
stm32_lock_release(&static_system_list_lock);
/* Mark all file locks as not initialized */
#ifdef FOPEN_MAX
stm32_lock_acquire(&static_file_list_lock);
for (index = 0; index < STM32_LOCK_ARRAY_SIZE(static_file_lock); index++)
{
STM32_LOCK_INITIALIZED(&static_file_lock) = 0;
}
stm32_lock_release(&static_file_list_lock);
#endif /* FOPEN_MAX */
/* Initialize system and file locks */
__iar_Initlocks();
/* Run the C++ global object constructors */
#ifdef __cplusplus
extern void __iar_dynamic_initialization();
__iar_dynamic_initialization();
#endif /* __cplusplus */
}
/**
* @defgroup __iar_system_Mtx_Functions IAR system locks
* @{
*/
/**
* @brief Initialize a system lock
* @param lock The lock
*/
void __iar_system_Mtxinit(__iar_Rmtx *lock)
{
uint32_t index;
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
stm32_lock_acquire(&static_system_list_lock);
for (index = 0; index < STM32_LOCK_ARRAY_SIZE(static_system_lock); index++)
{
if (STM32_LOCK_INITIALIZED(&static_system_lock) == 0)
{
*lock = &static_system_lock;
STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) = 1;
stm32_lock_init(STM32_LOCK_PARAMETER(STM32_GET_LOCK_PTR(lock)));
stm32_lock_release(&static_system_list_lock);
return;
}
}
/* Not enough mutexes, this should never happen */
STM32_LOCK_BLOCK();
/* Release of static_system_list_lock, not possible since STM32_LOCK_BLOCK is invoked */
}
/**
* @brief Lock a system lock
* @param lock The lock
*/
void __iar_system_Mtxlock(__iar_Rmtx *lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
stm32_lock_acquire(&static_system_list_lock);
if (STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) == 1)
{
stm32_lock_acquire(STM32_LOCK_PARAMETER(STM32_GET_LOCK_PTR(lock)));
}
else
{
STM32_LOCK_BLOCK();
}
stm32_lock_release(&static_system_list_lock);
}
/**
* @brief Unlock a system lock
* @param lock The lock
*/
void __iar_system_Mtxunlock(__iar_Rmtx *lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
stm32_lock_acquire(&static_system_list_lock);
if (STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) == 1)
{
stm32_lock_release(STM32_LOCK_PARAMETER(STM32_GET_LOCK_PTR(lock)));
}
else
{
STM32_LOCK_BLOCK();
}
stm32_lock_release(&static_system_list_lock);
}
/**
* @brief Destroy a system lock
* @param lock The lock
*/
void __iar_system_Mtxdst(__iar_Rmtx *lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
stm32_lock_acquire(&static_system_list_lock);
if (STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) == 1)
{
STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) = 0;
}
else
{
STM32_LOCK_BLOCK();
}
stm32_lock_release(&static_system_list_lock);
}
/**
* @}
*/
/**
* @defgroup __iar_file_Mtx_Functions IAR file locks
* @{
*/
/**
* @brief Initialize a file lock
* @param lock The lock
*/
void __iar_file_Mtxinit(__iar_Rmtx *lock)
{
#ifdef FOPEN_MAX
uint32_t index;
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
stm32_lock_acquire(&static_file_list_lock);
for (index = 0; index < STM32_LOCK_ARRAY_SIZE(static_file_lock); index++)
{
if (STM32_LOCK_INITIALIZED(&static_file_lock) == 0)
{
*lock = &static_file_lock;
STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) = 1;
stm32_lock_init(STM32_LOCK_PARAMETER(STM32_GET_LOCK_PTR(lock)));
stm32_lock_release(&static_file_list_lock);
return;
}
}
/* Not enough mutexes, this should never happen */
STM32_LOCK_BLOCK();
/* Release of static_file_lock, not possible since STM32_LOCK_BLOCK is invoked */
#else
STM32_LOCK_UNUSED(lock);
/* Not enough mutexes, this should never happen */
STM32_LOCK_BLOCK();
#endif /* FOPEN_MAX */
}
/**
* @brief Lock a file lock
* @param lock The lock
*/
void __iar_file_Mtxlock(__iar_Rmtx *lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
#ifdef FOPEN_MAX
stm32_lock_acquire(&static_file_list_lock);
if (STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) == 1)
{
stm32_lock_acquire(STM32_LOCK_PARAMETER(STM32_GET_LOCK_PTR(lock)));
}
else
{
STM32_LOCK_BLOCK();
}
stm32_lock_release(&static_file_list_lock);
#else
STM32_LOCK_BLOCK();
#endif /* FOPEN_MAX */
}
/**
* @brief Unlock a file lock
* @param lock The lock
*/
void __iar_file_Mtxunlock(__iar_Rmtx *lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
#ifdef FOPEN_MAX
stm32_lock_acquire(&static_file_list_lock);
if (STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) == 1)
{
stm32_lock_release(STM32_LOCK_PARAMETER(STM32_GET_LOCK_PTR(lock)));
}
else
{
STM32_LOCK_BLOCK();
}
stm32_lock_release(&static_file_list_lock);
#else
STM32_LOCK_BLOCK();
#endif /* FOPEN_MAX */
}
/**
* @brief Destroy a file lock
* @param lock The lock
*/
void __iar_file_Mtxdst(__iar_Rmtx *lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
#ifdef FOPEN_MAX
stm32_lock_acquire(&static_file_list_lock);
if (STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) == 1)
{
STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) = 0;
}
else
{
STM32_LOCK_BLOCK();
}
stm32_lock_release(&static_file_list_lock);
#else
STM32_LOCK_BLOCK();
#endif /* FOPEN_MAX */
}
/**
* @}
*/
/**
* @defgroup __iar_dynamic_Mtx_Functions IAR C++ dynamic locks
* @{
*/
/**
* @brief Initialize a C++ dynamic lock
* @param lock The lock
*/
void __iar_Initdynamiclock(__iar_Rmtx *lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
*lock = malloc(sizeof(LockingData_t));
if (*lock != NULL)
{
stm32_lock_init(*lock);
}
else
{
/* Cannot allocate memory for a new mutex */
STM32_LOCK_BLOCK();
}
}
/**
* @brief Lock a C++ dynamic lock
* @param lock The lock
*/
void __iar_Lockdynamiclock(__iar_Rmtx *lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
if (*lock != NULL)
{
stm32_lock_acquire(*lock);
}
else
{
STM32_LOCK_BLOCK();
}
}
/**
* @brief Unlock a C++ dynamic lock
* @param lock The lock
*/
void __iar_Unlockdynamiclock(__iar_Rmtx *lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
if (*lock != NULL)
{
stm32_lock_release(*lock);
}
else
{
STM32_LOCK_BLOCK();
}
}
/**
* @brief Destroy a C++ dynamic lock
* @param lock The lock
*/
void __iar_Dstdynamiclock(__iar_Rmtx *lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
free(*lock);
*lock = NULL;
}
/**
* @}
*/
GCC:
/**
******************************************************************************
* @file newlib_lock_glue.c
* @author STMicroelectronics
* @brief Implementation of newlib lock interface
*
* @details This file implements locking glue necessary to protect C library
* functions and initialization of local static objects in C++.
* Lock strategies are defined in stm32_lock.h that implements
* different level of thread-safety.
*
* For more information about which C functions need which of these
* low level functions, please consult the newlib libc manual,
* see https://sourceware.org/newlib/libc.html
*
* For more information about the one-time construction API for C++,
* see https://itanium-cxx-abi.github.io/cxx-abi/abi.html#once-ctor
*
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
#if !defined (__GNUC__) || defined (__CC_ARM)
#error "newlib_lock_glue.c" should be used with GNU Compilers only
#endif /* !defined (__GNUC__) || defined (__CC_ARM) */
/* Includes ------------------------------------------------------------------*/
#include <cmsis_compiler.h>
/* Private functions ---------------------------------------------------------*/
/**
* @brief Global Error_Handler
*/
__WEAK void Error_Handler(void)
{
/* Not used if it exists in project */
while (1);
}
#ifdef __SINGLE_THREAD__
#warning C library is in single-threaded mode. Please take care when using C library functions in threaded contexts
#else
/* Includes ------------------------------------------------------------------*/
#include <newlib.h>
#include <stdatomic.h>
#include "stm32_lock.h"
/**
* @defgroup _newlib_lock_functions newlib library locks
* @see https://sourceware.org/newlib/libc.html
* @{
*/
#if __NEWLIB__ >= 3 && defined (_RETARGETABLE_LOCKING)
#include <errno.h>
#include <stdlib.h>
#include <sys/lock.h>
/* Private macros ------------------------------------------------------------*/
/** See struct __lock definition */
#define STM32_LOCK_PARAMETER(lock) (&(lock)->lock_data)
/* Private variables ---------------------------------------------------------*/
struct __lock
{
LockingData_t lock_data; /**< The STM32 lock instance */
};
/** Implementing mutex from <a href="https://sourceware.org/git/?p=newlib-cygwin.git;a=blob_plain;f=newlib/libc/misc/lock.c">newlib/libc/misc/lock.c</a> */
struct __lock __lock___sinit_recursive_mutex = { LOCKING_DATA_INIT };
/** Implementing mutex from <a href="https://sourceware.org/git/?p=newlib-cygwin.git;a=blob_plain;f=newlib/libc/misc/lock.c">newlib/libc/misc/lock.c</a> */
struct __lock __lock___sfp_recursive_mutex = { LOCKING_DATA_INIT };
/** Implementing mutex from <a href="https://sourceware.org/git/?p=newlib-cygwin.git;a=blob_plain;f=newlib/libc/misc/lock.c">newlib/libc/misc/lock.c</a> */
struct __lock __lock___atexit_recursive_mutex = { LOCKING_DATA_INIT };
/** Implementing mutex from <a href="https://sourceware.org/git/?p=newlib-cygwin.git;a=blob_plain;f=newlib/libc/misc/lock.c">newlib/libc/misc/lock.c</a> */
struct __lock __lock___at_quick_exit_mutex = { LOCKING_DATA_INIT };
/** Implementing mutex from <a href="https://sourceware.org/git/?p=newlib-cygwin.git;a=blob_plain;f=newlib/libc/misc/lock.c">newlib/libc/misc/lock.c</a> */
struct __lock __lock___malloc_recursive_mutex = { LOCKING_DATA_INIT };
/** Implementing mutex from <a href="https://sourceware.org/git/?p=newlib-cygwin.git;a=blob_plain;f=newlib/libc/misc/lock.c">newlib/libc/misc/lock.c</a> */
struct __lock __lock___env_recursive_mutex = { LOCKING_DATA_INIT };
/** Implementing mutex from <a href="https://sourceware.org/git/?p=newlib-cygwin.git;a=blob_plain;f=newlib/libc/misc/lock.c">newlib/libc/misc/lock.c</a> */
struct __lock __lock___tz_mutex = { LOCKING_DATA_INIT };
/** Implementing mutex from <a href="https://sourceware.org/git/?p=newlib-cygwin.git;a=blob_plain;f=newlib/libc/misc/lock.c">newlib/libc/misc/lock.c</a> */
struct __lock __lock___dd_hash_mutex = { LOCKING_DATA_INIT };
/** Implementing mutex from <a href="https://sourceware.org/git/?p=newlib-cygwin.git;a=blob_plain;f=newlib/libc/misc/lock.c">newlib/libc/misc/lock.c</a> */
struct __lock __lock___arc4random_mutex = { LOCKING_DATA_INIT };
/* Private functions ---------------------------------------------------------*/
/**
* @brief Initialize lock
* @param lock The lock
*/
void __retarget_lock_init(_LOCK_T *lock)
{
__retarget_lock_init_recursive(lock);
}
/**
* @brief Initialize recursive lock
* @param lock The lock
*/
void __retarget_lock_init_recursive(_LOCK_T *lock)
{
if (lock == NULL)
{
errno = EINVAL;
return;
}
*lock = (_LOCK_T)malloc(sizeof(struct __lock));
if (*lock != NULL)
{
stm32_lock_init(STM32_LOCK_PARAMETER(*lock));
return;
}
/* Unable to allocate memory */
STM32_LOCK_BLOCK();
}
/**
* @brief Close lock
* @param lock The lock
*/
void __retarget_lock_close(_LOCK_T lock)
{
__retarget_lock_close_recursive(lock);
}
/**
* @brief Close recursive lock
* @param lock The lock
*/
void __retarget_lock_close_recursive(_LOCK_T lock)
{
free(lock);
}
/**
* @brief Acquire lock
* @param lock The lock
*/
void __retarget_lock_acquire(_LOCK_T lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
stm32_lock_acquire(STM32_LOCK_PARAMETER(lock));
}
/**
* @brief Acquire recursive lock
* @param lock The lock
*/
void __retarget_lock_acquire_recursive(_LOCK_T lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
stm32_lock_acquire(STM32_LOCK_PARAMETER(lock));
}
/**
* @brief Try acquire lock
* @param lock The lock
* @return 0 always
*/
int __retarget_lock_try_acquire(_LOCK_T lock)
{
__retarget_lock_acquire(lock);
return 0;
}
/**
* @brief Try acquire recursive lock
* @param lock The lock
* @return 0 always
*/
int __retarget_lock_try_acquire_recursive(_LOCK_T lock)
{
__retarget_lock_acquire_recursive(lock);
return 0;
}
/**
* @brief Release lock
* @param lock The lock
*/
void __retarget_lock_release(_LOCK_T lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
stm32_lock_release(STM32_LOCK_PARAMETER(lock));
}
/**
* @brief Release recursive lock
* @param lock The lock
*/
void __retarget_lock_release_recursive(_LOCK_T lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
stm32_lock_release(STM32_LOCK_PARAMETER(lock));
}
#else
#warning This makes malloc, env, and TZ calls thread-safe, not the entire newlib
/* Includes ------------------------------------------------------------------*/
#include <reent.h>
/* Private variables ---------------------------------------------------------*/
/** Mutex used in __malloc_lock and __malloc_unlock */
static LockingData_t __lock___malloc_recursive_mutex = LOCKING_DATA_INIT;
/** Mutex used in __env_lock and __env_unlock */
static LockingData_t __lock___env_recursive_mutex = LOCKING_DATA_INIT;
/** Mutex used in __tz_lock and __tz_unlock */
static LockingData_t __lock___tz_mutex = LOCKING_DATA_INIT;
/* Private functions ---------------------------------------------------------*/
#if __STD_C
/**
* @brief Acquire malloc lock
* @param reent The reentrance struct
*/
void __malloc_lock(struct _reent *reent)
{
STM32_LOCK_UNUSED(reent);
stm32_lock_acquire(&__lock___malloc_recursive_mutex);
}
/**
* @brief Release malloc lock
* @param reent The reentrance struct
*/
void __malloc_unlock(struct _reent *reent)
{
STM32_LOCK_UNUSED(reent);
stm32_lock_release(&__lock___malloc_recursive_mutex);
}
#else
/**
* @brief Acquire malloc lock
*/
void __malloc_lock()
{
stm32_lock_acquire(&__lock___malloc_recursive_mutex);
}
/**
* @brief Release malloc lock
*/
void __malloc_unlock()
{
stm32_lock_release(&__lock___malloc_recursive_mutex);
}
#endif /* __STD_C */
/**
* @brief Acquire env lock
* @param reent The reentrance struct
*/
void __env_lock(struct _reent *reent)
{
STM32_LOCK_UNUSED(reent);
stm32_lock_acquire(&__lock___env_recursive_mutex);
}
/**
* @brief Release env lock
* @param reent The reentrance struct
*/
void __env_unlock(struct _reent *reent)
{
STM32_LOCK_UNUSED(reent);
stm32_lock_release(&__lock___env_recursive_mutex);
}
/**
* @brief Acquire tz lock
*/
void __tz_lock()
{
stm32_lock_acquire(&__lock___tz_mutex);
}
/**
* @brief Release tz lock
*/
void __tz_unlock()
{
stm32_lock_release(&__lock___tz_mutex);
}
#endif /* __NEWLIB__ >= 3 && defined (_RETARGETABLE_LOCKING) */
/**
* @}
*/
/**
* @defgroup __cxa_guard_ GNU C++ one-time construction API
* @see https://itanium-cxx-abi.github.io/cxx-abi/abi.html#once-ctor
*
* When building for C++, please make sure that <tt>-fno-threadsafe-statics</tt> is not passed to the compiler
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/** The guard object is created by the C++ compiler and is 32 bit for ARM EABI. */
typedef struct
{
atomic_uchar initialized; /**< Indicate if object is initialized */
uint8_t acquired; /**< Ensure non-recursive lock */
uint16_t unused; /**< Padding */
} __attribute__((packed)) CxaGuardObject_t;
/* Private variables ---------------------------------------------------------*/
/** Mutex used in __cxa_guard_acquire, __cxa_guard_release and __cxa_guard_abort */
static LockingData_t __cxa_guard_mutex = LOCKING_DATA_INIT;
/* Private functions ---------------------------------------------------------*/
/**
* @brief Acquire __cxa_guard mutex
* @param guard_object Guard object
* @return 0 if object is initialized, else initialization of object required
*/
int __cxa_guard_acquire(CxaGuardObject_t *guard_object)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(guard_object);
if (atomic_load(&guard_object->initialized) == 0)
{
/* Object needs initialization, lock threading context */
stm32_lock_acquire(&__cxa_guard_mutex);
if (atomic_load(&guard_object->initialized) == 0)
{
/* Object needs initialization */
if (guard_object->acquired)
{
/* Object initialization already in progress */
STM32_LOCK_BLOCK();
}
/* Lock acquired */
guard_object->acquired = 1;
return 1;
}
else
{
/* Object initialized in another thread */
stm32_lock_release(&__cxa_guard_mutex);
}
}
/* Object already initialized */
return 0;
}
/**
* @brief Abort __cxa_guard mutex
* @param guard_object Guard object
*/
void __cxa_guard_abort(CxaGuardObject_t *guard_object)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(guard_object);
if (guard_object->acquired)
{
/* Release lock */
guard_object->acquired = 0;
stm32_lock_release(&__cxa_guard_mutex);
}
else
{
/* Trying to release non-acquired lock */
STM32_LOCK_BLOCK();
}
}
/**
* @brief Release __cxa_guard mutex
* @param guard_object Guard object
*/
void __cxa_guard_release(CxaGuardObject_t *guard_object)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(guard_object);
/* Object initialized */
atomic_store(&guard_object->initialized, 1);
/* Release lock */
__cxa_guard_abort(guard_object);
}
/**
* @}
*/
#endif /* __SINGLE_THREAD__ */
页:
[1]