- Naming style migrated to camel-case - P7lib logger sources added - Vcpkg manifest, CMake presets and build moved to root - SDL2, Vulkan and RmlUi dependencies added - Logger LOG macro added - Logger configuration - SDL2 window configuration - Vulkan configuration - RmlUi configuration - SDL event loop
145 lines
5.8 KiB
C
145 lines
5.8 KiB
C
////////////////////////////////////////////////////////////////////////////////
|
|
// /
|
|
// 2012-2020 (c) Baical /
|
|
// /
|
|
// This library is free software; you can redistribute it and/or /
|
|
// modify it under the terms of the GNU Lesser General Public /
|
|
// License as published by the Free Software Foundation; either /
|
|
// version 3.0 of the License, or (at your option) any later version. /
|
|
// /
|
|
// This library is distributed in the hope that it will be useful, /
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
|
|
// Lesser General Public License for more details. /
|
|
// /
|
|
// You should have received a copy of the GNU Lesser General Public /
|
|
// License along with this library. /
|
|
// /
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
#ifndef PATOMIC_H
|
|
#define PATOMIC_H
|
|
|
|
#ifdef __ARM_ARCH_5TEJ__
|
|
|
|
//Source:
|
|
//http://svn.dd-wrt.com/browser/src/linux/xscale/linux-2.6.23/arch/arm/kernel/entry-armv.S?rev=8329
|
|
// Reference prototype:
|
|
//
|
|
// int __kernel_cmpxchg(int oldval, int newval, int *ptr)
|
|
//
|
|
// Input:
|
|
//
|
|
// r0 = oldval
|
|
// r1 = newval
|
|
// r2 = ptr
|
|
// lr = return address
|
|
//
|
|
// Output:
|
|
//
|
|
// r0 = returned value (zero or non-zero)
|
|
// C flag = set if r0 == 0, clear if r0 != 0
|
|
//
|
|
// Clobbered:
|
|
//
|
|
// r3, ip, flags
|
|
//
|
|
// Definition and user space usage example:
|
|
//
|
|
// typedef int (__kernel_cmpxchg_t)(int oldval, int newval, int *ptr);
|
|
// #define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0)
|
|
//
|
|
// Atomically store newval in *ptr if *ptr is equal to oldval for user space.
|
|
// Return zero if *ptr was changed or non-zero if no exchange happened.
|
|
// The C flag is also set if *ptr was changed to allow for assembly
|
|
// optimization in the calling code.
|
|
//
|
|
// Notes:
|
|
//
|
|
// - This routine already includes memory barriers as needed.
|
|
//
|
|
// - A failure might be transient, i.e. it is possible, although unlikely,
|
|
// that "failure" be returned even if *ptr == oldval.
|
|
//
|
|
//Another implementations:
|
|
//http://upc.lbl.gov/web-translator/2.8.0/runtime/inst/opt/include/gasnet_atomic_bits.h
|
|
//http://upc.lbl.gov/web-translator/ - in last versions very interesting
|
|
// For arm 6 & 7:
|
|
//http://lxr.free-electrons.com/source/arch/arm/include/asm/atomic.h
|
|
|
|
#define ATOMIC_ADD(ptr, val) \
|
|
__extension__ ({ volatile register tINT32 *__ptr asm("r2") = (ptr); \
|
|
register tINT32 __result asm("r1"); \
|
|
asm volatile ( \
|
|
"1: @ atomic_add\n\t" \
|
|
"ldr r0, [r2]\n\t" \
|
|
"mov r3, #0xffff0fff\n\t" \
|
|
"add lr, pc, #4\n\t" \
|
|
"add r1, r0, %2\n\t" \
|
|
"add pc, r3, #(0xffff0fc0 - 0xffff0fff)\n\t" \
|
|
"bcc 1b" \
|
|
: "=&r" (__result) \
|
|
: "r" (__ptr), "rIL" (val) \
|
|
: "r0","r3","ip","lr","cc","memory" ); \
|
|
__result; })
|
|
|
|
|
|
#define ATOMIC_SUB(ptr, val) \
|
|
__extension__ ({ volatile register tINT32 *__ptr asm("r2") = (ptr); \
|
|
register tINT32 __result asm("r1"); \
|
|
asm volatile ( \
|
|
"1: @ atomic_add\n\t" \
|
|
"ldr r0, [r2]\n\t" \
|
|
"mov r3, #0xffff0fff\n\t" \
|
|
"add lr, pc, #4\n\t" \
|
|
"sub r1, r0, %2\n\t" \
|
|
"add pc, r3, #(0xffff0fc0 - 0xffff0fff)\n\t" \
|
|
"bcc 1b" \
|
|
: "=&r" (__result) \
|
|
: "r" (__ptr), "rIL" (val) \
|
|
: "r0","r3","ip","lr","cc","memory" ); \
|
|
__result; })
|
|
|
|
//#ifdef __ARM_ARCH_5TEJ__
|
|
#elif defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_6__)
|
|
#define ATOMIC_ADD(ptr, val) \
|
|
__extension__ ({ int32_t tmp; \
|
|
int result; \
|
|
__asm__ __volatile__("@ atomic_add\n" \
|
|
"1: ldrex %0, [%3]\n" \
|
|
" add %0, %0, %4\n" \
|
|
" strex %1, %0, [%3]\n" \
|
|
" teq %1, #0\n" \
|
|
" bne 1b" \
|
|
: "=&r" (result), "=&r" (tmp), "+Qo" (*ptr) \
|
|
: "r" (ptr), "Ir" (val) \
|
|
: "cc"); \
|
|
result;})
|
|
|
|
#define ATOMIC_SUB(ptr, val) \
|
|
__extension__ ({ unsigned long tmp; \
|
|
int result; \
|
|
__asm__ __volatile__("@ atomic_sub\n" \
|
|
"1: ldrex %0, [%3]\n" \
|
|
" sub %0, %0, %4\n" \
|
|
" strex %1, %0, [%3]\n" \
|
|
" teq %1, #0\n" \
|
|
" bne 1b" \
|
|
: "=&r" (result), "=&r" (tmp), "+Qo" (*ptr) \
|
|
: "r" (ptr), "Ir" (val) \
|
|
: "cc"); \
|
|
result;})
|
|
#else //#elif defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_6__)
|
|
|
|
#define ATOMIC_ADD(io_Val, i_Add) __sync_add_and_fetch(io_Val, i_Add)
|
|
#define ATOMIC_SUB(io_Val, i_Add) __sync_sub_and_fetch(io_Val, i_Add)
|
|
#define ATOMIC_SET(io_Var, i_Val) __sync_lock_test_and_set(io_Var, i_Val)
|
|
|
|
#endif //#ifdef __ARM_ARCH_5TEJ__
|
|
|
|
|
|
#define ATOMIC_INC(io_Val) ATOMIC_ADD(io_Val, 1)
|
|
#define ATOMIC_DEC(io_Val) ATOMIC_SUB(io_Val, 1)
|
|
|
|
#endif //PATOMIC_H
|
|
|