1 /*
2 * Copyright (c) 2019, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 #include "AEEatomic.h"
30
31 #ifdef _WIN32
32 #include "Windows.h"
atomic_CompareAndExchange(uint32 * volatile puDest,uint32 uExchange,uint32 uCompare)33 uint32 atomic_CompareAndExchange(uint32 * volatile puDest, uint32 uExchange, uint32 uCompare) {
34 C_ASSERT(sizeof(LONG) == sizeof(uint32));
35 return (uint32)InterlockedCompareExchange((LONG*)puDest, (LONG)uExchange, (LONG)uCompare);
36 }
atomic_CompareAndExchangeUP(uintptr_t * volatile puDest,uintptr_t uExchange,uintptr_t uCompare)37 uintptr_t atomic_CompareAndExchangeUP(uintptr_t * volatile puDest, uintptr_t uExchange, uintptr_t uCompare) {
38 C_ASSERT(sizeof(uintptr_t) == sizeof(void*));
39 return (uintptr_t)InterlockedCompareExchangePointer((void**)puDest, (void*)uExchange, (void*)uCompare);
40 }
41 #elif __hexagon__
42
43 #ifndef C_ASSERT
44 #define C_ASSERT(test) \
45 switch(0) {\
46 case 0:\
47 case test:;\
48 }
49 #endif
50
51 static inline unsigned int
qurt_atomic_compare_val_and_set(unsigned int * target,unsigned int old_val,unsigned int new_val)52 qurt_atomic_compare_val_and_set(unsigned int* target,
53 unsigned int old_val,
54 unsigned int new_val)
55 {
56 unsigned int current_val;
57
58 __asm__ __volatile__(
59 "1: %0 = memw_locked(%2)\n"
60 " p0 = cmp.eq(%0, %3)\n"
61 " if !p0 jump 2f\n"
62 " memw_locked(%2, p0) = %4\n"
63 " if !p0 jump 1b\n"
64 "2:\n"
65 : "=&r" (current_val),"+m" (*target)
66 : "r" (target), "r" (old_val), "r" (new_val)
67 : "p0");
68
69 return current_val;
70 }
atomic_CompareAndExchange(uint32 * volatile puDest,uint32 uExchange,uint32 uCompare)71 uint32 atomic_CompareAndExchange(uint32 * volatile puDest, uint32 uExchange, uint32 uCompare) {
72 return (uint32)qurt_atomic_compare_val_and_set((unsigned int*)puDest, uCompare, uExchange);
73 }
atomic_CompareAndExchangeUP(uintptr_t * volatile puDest,uintptr_t uExchange,uintptr_t uCompare)74 uintptr_t atomic_CompareAndExchangeUP(uintptr_t * volatile puDest, uintptr_t uExchange, uintptr_t uCompare) {
75 C_ASSERT(sizeof(uintptr_t) == sizeof(uint32));
76 return (uint32)atomic_CompareAndExchange((uint32*)puDest, (uint32)uExchange, (uint32)uCompare);
77 }
78 #elif __GNUC__
atomic_CompareAndExchange(uint32 * volatile puDest,uint32 uExchange,uint32 uCompare)79 uint32 atomic_CompareAndExchange(uint32 * volatile puDest, uint32 uExchange, uint32 uCompare) {
80 return __sync_val_compare_and_swap(puDest, uCompare, uExchange);
81 }
atomic_CompareAndExchange64(uint64 * volatile puDest,uint64 uExchange,uint64 uCompare)82 uint64 atomic_CompareAndExchange64(uint64 * volatile puDest, uint64 uExchange, uint64 uCompare) {
83 return __sync_val_compare_and_swap(puDest, uCompare, uExchange);
84 }
atomic_CompareAndExchangeUP(uintptr_t * volatile puDest,uintptr_t uExchange,uintptr_t uCompare)85 uintptr_t atomic_CompareAndExchangeUP(uintptr_t * volatile puDest, uintptr_t uExchange, uintptr_t uCompare) {
86 return __sync_val_compare_and_swap(puDest, uCompare, uExchange);
87 }
88 #endif //compare and exchange
89