mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #6368 from kjbracey-arm/atomic_volatile
Sort out volatiles in the atomic functionspull/6437/head
commit
3ddca11395
|
@ -116,104 +116,104 @@ void core_util_critical_section_exit(void)
|
||||||
#pragma diag_suppress 3731
|
#pragma diag_suppress 3731
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool core_util_atomic_cas_u8(uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue)
|
bool core_util_atomic_cas_u8(volatile uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue)
|
||||||
{
|
{
|
||||||
do {
|
do {
|
||||||
uint8_t currentValue = __LDREXB((volatile uint8_t*)ptr);
|
uint8_t currentValue = __LDREXB(ptr);
|
||||||
if (currentValue != *expectedCurrentValue) {
|
if (currentValue != *expectedCurrentValue) {
|
||||||
*expectedCurrentValue = currentValue;
|
*expectedCurrentValue = currentValue;
|
||||||
__CLREX();
|
__CLREX();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} while (__STREXB(desiredValue, (volatile uint8_t*)ptr));
|
} while (__STREXB(desiredValue, ptr));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool core_util_atomic_cas_u16(uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue)
|
bool core_util_atomic_cas_u16(volatile uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue)
|
||||||
{
|
{
|
||||||
do {
|
do {
|
||||||
uint16_t currentValue = __LDREXH((volatile uint16_t*)ptr);
|
uint16_t currentValue = __LDREXH(ptr);
|
||||||
if (currentValue != *expectedCurrentValue) {
|
if (currentValue != *expectedCurrentValue) {
|
||||||
*expectedCurrentValue = currentValue;
|
*expectedCurrentValue = currentValue;
|
||||||
__CLREX();
|
__CLREX();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} while (__STREXH(desiredValue, (volatile uint16_t*)ptr));
|
} while (__STREXH(desiredValue, ptr));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool core_util_atomic_cas_u32(uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue)
|
bool core_util_atomic_cas_u32(volatile uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue)
|
||||||
{
|
{
|
||||||
do {
|
do {
|
||||||
uint32_t currentValue = __LDREXW((volatile uint32_t*)ptr);
|
uint32_t currentValue = __LDREXW(ptr);
|
||||||
if (currentValue != *expectedCurrentValue) {
|
if (currentValue != *expectedCurrentValue) {
|
||||||
*expectedCurrentValue = currentValue;
|
*expectedCurrentValue = currentValue;
|
||||||
__CLREX();
|
__CLREX();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} while (__STREXW(desiredValue, (volatile uint32_t*)ptr));
|
} while (__STREXW(desiredValue, ptr));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t core_util_atomic_incr_u8(uint8_t *valuePtr, uint8_t delta)
|
uint8_t core_util_atomic_incr_u8(volatile uint8_t *valuePtr, uint8_t delta)
|
||||||
{
|
{
|
||||||
uint8_t newValue;
|
uint8_t newValue;
|
||||||
do {
|
do {
|
||||||
newValue = __LDREXB((volatile uint8_t*)valuePtr) + delta;
|
newValue = __LDREXB(valuePtr) + delta;
|
||||||
} while (__STREXB(newValue, (volatile uint8_t*)valuePtr));
|
} while (__STREXB(newValue, valuePtr));
|
||||||
return newValue;
|
return newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t core_util_atomic_incr_u16(uint16_t *valuePtr, uint16_t delta)
|
uint16_t core_util_atomic_incr_u16(volatile uint16_t *valuePtr, uint16_t delta)
|
||||||
{
|
{
|
||||||
uint16_t newValue;
|
uint16_t newValue;
|
||||||
do {
|
do {
|
||||||
newValue = __LDREXH((volatile uint16_t*)valuePtr) + delta;
|
newValue = __LDREXH(valuePtr) + delta;
|
||||||
} while (__STREXH(newValue, (volatile uint16_t*)valuePtr));
|
} while (__STREXH(newValue, valuePtr));
|
||||||
return newValue;
|
return newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t core_util_atomic_incr_u32(uint32_t *valuePtr, uint32_t delta)
|
uint32_t core_util_atomic_incr_u32(volatile uint32_t *valuePtr, uint32_t delta)
|
||||||
{
|
{
|
||||||
uint32_t newValue;
|
uint32_t newValue;
|
||||||
do {
|
do {
|
||||||
newValue = __LDREXW((volatile uint32_t*)valuePtr) + delta;
|
newValue = __LDREXW(valuePtr) + delta;
|
||||||
} while (__STREXW(newValue, (volatile uint32_t*)valuePtr));
|
} while (__STREXW(newValue, valuePtr));
|
||||||
return newValue;
|
return newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t core_util_atomic_decr_u8(uint8_t *valuePtr, uint8_t delta)
|
uint8_t core_util_atomic_decr_u8(volatile uint8_t *valuePtr, uint8_t delta)
|
||||||
{
|
{
|
||||||
uint8_t newValue;
|
uint8_t newValue;
|
||||||
do {
|
do {
|
||||||
newValue = __LDREXB((volatile uint8_t*)valuePtr) - delta;
|
newValue = __LDREXB(valuePtr) - delta;
|
||||||
} while (__STREXB(newValue, (volatile uint8_t*)valuePtr));
|
} while (__STREXB(newValue, valuePtr));
|
||||||
return newValue;
|
return newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t core_util_atomic_decr_u16(uint16_t *valuePtr, uint16_t delta)
|
uint16_t core_util_atomic_decr_u16(volatile uint16_t *valuePtr, uint16_t delta)
|
||||||
{
|
{
|
||||||
uint16_t newValue;
|
uint16_t newValue;
|
||||||
do {
|
do {
|
||||||
newValue = __LDREXH((volatile uint16_t*)valuePtr) - delta;
|
newValue = __LDREXH(valuePtr) - delta;
|
||||||
} while (__STREXH(newValue, (volatile uint16_t*)valuePtr));
|
} while (__STREXH(newValue, valuePtr));
|
||||||
return newValue;
|
return newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t core_util_atomic_decr_u32(uint32_t *valuePtr, uint32_t delta)
|
uint32_t core_util_atomic_decr_u32(volatile uint32_t *valuePtr, uint32_t delta)
|
||||||
{
|
{
|
||||||
uint32_t newValue;
|
uint32_t newValue;
|
||||||
do {
|
do {
|
||||||
newValue = __LDREXW((volatile uint32_t*)valuePtr) - delta;
|
newValue = __LDREXW(valuePtr) - delta;
|
||||||
} while (__STREXW(newValue, (volatile uint32_t*)valuePtr));
|
} while (__STREXW(newValue, valuePtr));
|
||||||
return newValue;
|
return newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
bool core_util_atomic_cas_u8(uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue)
|
bool core_util_atomic_cas_u8(volatile uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue)
|
||||||
{
|
{
|
||||||
bool success;
|
bool success;
|
||||||
uint8_t currentValue;
|
uint8_t currentValue;
|
||||||
|
@ -230,7 +230,7 @@ bool core_util_atomic_cas_u8(uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool core_util_atomic_cas_u16(uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue)
|
bool core_util_atomic_cas_u16(volatile uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue)
|
||||||
{
|
{
|
||||||
bool success;
|
bool success;
|
||||||
uint16_t currentValue;
|
uint16_t currentValue;
|
||||||
|
@ -248,7 +248,7 @@ bool core_util_atomic_cas_u16(uint16_t *ptr, uint16_t *expectedCurrentValue, uin
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool core_util_atomic_cas_u32(uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue)
|
bool core_util_atomic_cas_u32(volatile uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue)
|
||||||
{
|
{
|
||||||
bool success;
|
bool success;
|
||||||
uint32_t currentValue;
|
uint32_t currentValue;
|
||||||
|
@ -266,7 +266,7 @@ bool core_util_atomic_cas_u32(uint32_t *ptr, uint32_t *expectedCurrentValue, uin
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t core_util_atomic_incr_u8(uint8_t *valuePtr, uint8_t delta)
|
uint8_t core_util_atomic_incr_u8(volatile uint8_t *valuePtr, uint8_t delta)
|
||||||
{
|
{
|
||||||
uint8_t newValue;
|
uint8_t newValue;
|
||||||
core_util_critical_section_enter();
|
core_util_critical_section_enter();
|
||||||
|
@ -276,7 +276,7 @@ uint8_t core_util_atomic_incr_u8(uint8_t *valuePtr, uint8_t delta)
|
||||||
return newValue;
|
return newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t core_util_atomic_incr_u16(uint16_t *valuePtr, uint16_t delta)
|
uint16_t core_util_atomic_incr_u16(volatile uint16_t *valuePtr, uint16_t delta)
|
||||||
{
|
{
|
||||||
uint16_t newValue;
|
uint16_t newValue;
|
||||||
core_util_critical_section_enter();
|
core_util_critical_section_enter();
|
||||||
|
@ -286,7 +286,7 @@ uint16_t core_util_atomic_incr_u16(uint16_t *valuePtr, uint16_t delta)
|
||||||
return newValue;
|
return newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t core_util_atomic_incr_u32(uint32_t *valuePtr, uint32_t delta)
|
uint32_t core_util_atomic_incr_u32(volatile uint32_t *valuePtr, uint32_t delta)
|
||||||
{
|
{
|
||||||
uint32_t newValue;
|
uint32_t newValue;
|
||||||
core_util_critical_section_enter();
|
core_util_critical_section_enter();
|
||||||
|
@ -297,7 +297,7 @@ uint32_t core_util_atomic_incr_u32(uint32_t *valuePtr, uint32_t delta)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t core_util_atomic_decr_u8(uint8_t *valuePtr, uint8_t delta)
|
uint8_t core_util_atomic_decr_u8(volatile uint8_t *valuePtr, uint8_t delta)
|
||||||
{
|
{
|
||||||
uint8_t newValue;
|
uint8_t newValue;
|
||||||
core_util_critical_section_enter();
|
core_util_critical_section_enter();
|
||||||
|
@ -307,7 +307,7 @@ uint8_t core_util_atomic_decr_u8(uint8_t *valuePtr, uint8_t delta)
|
||||||
return newValue;
|
return newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t core_util_atomic_decr_u16(uint16_t *valuePtr, uint16_t delta)
|
uint16_t core_util_atomic_decr_u16(volatile uint16_t *valuePtr, uint16_t delta)
|
||||||
{
|
{
|
||||||
uint16_t newValue;
|
uint16_t newValue;
|
||||||
core_util_critical_section_enter();
|
core_util_critical_section_enter();
|
||||||
|
@ -317,7 +317,7 @@ uint16_t core_util_atomic_decr_u16(uint16_t *valuePtr, uint16_t delta)
|
||||||
return newValue;
|
return newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t core_util_atomic_decr_u32(uint32_t *valuePtr, uint32_t delta)
|
uint32_t core_util_atomic_decr_u32(volatile uint32_t *valuePtr, uint32_t delta)
|
||||||
{
|
{
|
||||||
uint32_t newValue;
|
uint32_t newValue;
|
||||||
core_util_critical_section_enter();
|
core_util_critical_section_enter();
|
||||||
|
@ -330,18 +330,18 @@ uint32_t core_util_atomic_decr_u32(uint32_t *valuePtr, uint32_t delta)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
bool core_util_atomic_cas_ptr(void **ptr, void **expectedCurrentValue, void *desiredValue) {
|
bool core_util_atomic_cas_ptr(void * volatile *ptr, void **expectedCurrentValue, void *desiredValue) {
|
||||||
return core_util_atomic_cas_u32(
|
return core_util_atomic_cas_u32(
|
||||||
(uint32_t *)ptr,
|
(volatile uint32_t *)ptr,
|
||||||
(uint32_t *)expectedCurrentValue,
|
(uint32_t *)expectedCurrentValue,
|
||||||
(uint32_t)desiredValue);
|
(uint32_t)desiredValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *core_util_atomic_incr_ptr(void **valuePtr, ptrdiff_t delta) {
|
void *core_util_atomic_incr_ptr(void * volatile *valuePtr, ptrdiff_t delta) {
|
||||||
return (void *)core_util_atomic_incr_u32((uint32_t *)valuePtr, (uint32_t)delta);
|
return (void *)core_util_atomic_incr_u32((volatile uint32_t *)valuePtr, (uint32_t)delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *core_util_atomic_decr_ptr(void **valuePtr, ptrdiff_t delta) {
|
void *core_util_atomic_decr_ptr(void * volatile *valuePtr, ptrdiff_t delta) {
|
||||||
return (void *)core_util_atomic_decr_u32((uint32_t *)valuePtr, (uint32_t)delta);
|
return (void *)core_util_atomic_decr_u32((volatile uint32_t *)valuePtr, (uint32_t)delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -144,7 +144,7 @@ bool core_util_in_critical_section(void);
|
||||||
* always succeeds if the current value is expected, as per the pseudocode
|
* always succeeds if the current value is expected, as per the pseudocode
|
||||||
* above; it will not spuriously fail as "atomic_compare_exchange_weak" may.
|
* above; it will not spuriously fail as "atomic_compare_exchange_weak" may.
|
||||||
*/
|
*/
|
||||||
bool core_util_atomic_cas_u8(uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue);
|
bool core_util_atomic_cas_u8(volatile uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Atomic compare and set. It compares the contents of a memory location to a
|
* Atomic compare and set. It compares the contents of a memory location to a
|
||||||
|
@ -201,7 +201,7 @@ bool core_util_atomic_cas_u8(uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_
|
||||||
* always succeeds if the current value is expected, as per the pseudocode
|
* always succeeds if the current value is expected, as per the pseudocode
|
||||||
* above; it will not spuriously fail as "atomic_compare_exchange_weak" may.
|
* above; it will not spuriously fail as "atomic_compare_exchange_weak" may.
|
||||||
*/
|
*/
|
||||||
bool core_util_atomic_cas_u16(uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue);
|
bool core_util_atomic_cas_u16(volatile uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Atomic compare and set. It compares the contents of a memory location to a
|
* Atomic compare and set. It compares the contents of a memory location to a
|
||||||
|
@ -258,7 +258,7 @@ bool core_util_atomic_cas_u16(uint16_t *ptr, uint16_t *expectedCurrentValue, uin
|
||||||
* above; it will not spuriously fail as "atomic_compare_exchange_weak" may.
|
* above; it will not spuriously fail as "atomic_compare_exchange_weak" may.
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
bool core_util_atomic_cas_u32(uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue);
|
bool core_util_atomic_cas_u32(volatile uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Atomic compare and set. It compares the contents of a memory location to a
|
* Atomic compare and set. It compares the contents of a memory location to a
|
||||||
|
@ -315,7 +315,7 @@ bool core_util_atomic_cas_u32(uint32_t *ptr, uint32_t *expectedCurrentValue, uin
|
||||||
* always succeeds if the current value is expected, as per the pseudocode
|
* always succeeds if the current value is expected, as per the pseudocode
|
||||||
* above; it will not spuriously fail as "atomic_compare_exchange_weak" may.
|
* above; it will not spuriously fail as "atomic_compare_exchange_weak" may.
|
||||||
*/
|
*/
|
||||||
bool core_util_atomic_cas_ptr(void **ptr, void **expectedCurrentValue, void *desiredValue);
|
bool core_util_atomic_cas_ptr(void * volatile *ptr, void **expectedCurrentValue, void *desiredValue);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Atomic increment.
|
* Atomic increment.
|
||||||
|
@ -323,7 +323,7 @@ bool core_util_atomic_cas_ptr(void **ptr, void **expectedCurrentValue, void *des
|
||||||
* @param delta The amount being incremented.
|
* @param delta The amount being incremented.
|
||||||
* @return The new incremented value.
|
* @return The new incremented value.
|
||||||
*/
|
*/
|
||||||
uint8_t core_util_atomic_incr_u8(uint8_t *valuePtr, uint8_t delta);
|
uint8_t core_util_atomic_incr_u8(volatile uint8_t *valuePtr, uint8_t delta);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Atomic increment.
|
* Atomic increment.
|
||||||
|
@ -331,7 +331,7 @@ uint8_t core_util_atomic_incr_u8(uint8_t *valuePtr, uint8_t delta);
|
||||||
* @param delta The amount being incremented.
|
* @param delta The amount being incremented.
|
||||||
* @return The new incremented value.
|
* @return The new incremented value.
|
||||||
*/
|
*/
|
||||||
uint16_t core_util_atomic_incr_u16(uint16_t *valuePtr, uint16_t delta);
|
uint16_t core_util_atomic_incr_u16(volatile uint16_t *valuePtr, uint16_t delta);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Atomic increment.
|
* Atomic increment.
|
||||||
|
@ -339,7 +339,7 @@ uint16_t core_util_atomic_incr_u16(uint16_t *valuePtr, uint16_t delta);
|
||||||
* @param delta The amount being incremented.
|
* @param delta The amount being incremented.
|
||||||
* @return The new incremented value.
|
* @return The new incremented value.
|
||||||
*/
|
*/
|
||||||
uint32_t core_util_atomic_incr_u32(uint32_t *valuePtr, uint32_t delta);
|
uint32_t core_util_atomic_incr_u32(volatile uint32_t *valuePtr, uint32_t delta);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Atomic increment.
|
* Atomic increment.
|
||||||
|
@ -350,7 +350,7 @@ uint32_t core_util_atomic_incr_u32(uint32_t *valuePtr, uint32_t delta);
|
||||||
* @note The type of the pointer argument is not taken into account
|
* @note The type of the pointer argument is not taken into account
|
||||||
* and the pointer is incremented by bytes.
|
* and the pointer is incremented by bytes.
|
||||||
*/
|
*/
|
||||||
void *core_util_atomic_incr_ptr(void **valuePtr, ptrdiff_t delta);
|
void *core_util_atomic_incr_ptr(void * volatile *valuePtr, ptrdiff_t delta);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Atomic decrement.
|
* Atomic decrement.
|
||||||
|
@ -358,7 +358,7 @@ void *core_util_atomic_incr_ptr(void **valuePtr, ptrdiff_t delta);
|
||||||
* @param delta The amount being decremented.
|
* @param delta The amount being decremented.
|
||||||
* @return The new decremented value.
|
* @return The new decremented value.
|
||||||
*/
|
*/
|
||||||
uint8_t core_util_atomic_decr_u8(uint8_t *valuePtr, uint8_t delta);
|
uint8_t core_util_atomic_decr_u8(volatile uint8_t *valuePtr, uint8_t delta);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Atomic decrement.
|
* Atomic decrement.
|
||||||
|
@ -366,7 +366,7 @@ uint8_t core_util_atomic_decr_u8(uint8_t *valuePtr, uint8_t delta);
|
||||||
* @param delta The amount being decremented.
|
* @param delta The amount being decremented.
|
||||||
* @return The new decremented value.
|
* @return The new decremented value.
|
||||||
*/
|
*/
|
||||||
uint16_t core_util_atomic_decr_u16(uint16_t *valuePtr, uint16_t delta);
|
uint16_t core_util_atomic_decr_u16(volatile uint16_t *valuePtr, uint16_t delta);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Atomic decrement.
|
* Atomic decrement.
|
||||||
|
@ -374,7 +374,7 @@ uint16_t core_util_atomic_decr_u16(uint16_t *valuePtr, uint16_t delta);
|
||||||
* @param delta The amount being decremented.
|
* @param delta The amount being decremented.
|
||||||
* @return The new decremented value.
|
* @return The new decremented value.
|
||||||
*/
|
*/
|
||||||
uint32_t core_util_atomic_decr_u32(uint32_t *valuePtr, uint32_t delta);
|
uint32_t core_util_atomic_decr_u32(volatile uint32_t *valuePtr, uint32_t delta);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Atomic decrement.
|
* Atomic decrement.
|
||||||
|
@ -385,7 +385,7 @@ uint32_t core_util_atomic_decr_u32(uint32_t *valuePtr, uint32_t delta);
|
||||||
* @note The type of the pointer argument is not taken into account
|
* @note The type of the pointer argument is not taken into account
|
||||||
* and the pointer is decremented by bytes
|
* and the pointer is decremented by bytes
|
||||||
*/
|
*/
|
||||||
void *core_util_atomic_decr_ptr(void **valuePtr, ptrdiff_t delta);
|
void *core_util_atomic_decr_ptr(void * volatile *valuePtr, ptrdiff_t delta);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
Loading…
Reference in New Issue