]>
Commit | Line | Data |
---|---|---|
d6491d15 | 1 | /* AMD GCN atomic operations |
a945c346 | 2 | Copyright (C) 2020-2024 Free Software Foundation, Inc. |
d6491d15 KCY |
3 | Contributed by Mentor Graphics. |
4 | ||
5 | This file is free software; you can redistribute it and/or modify it | |
6 | under the terms of the GNU General Public License as published by the | |
7 | Free Software Foundation; either version 3, or (at your option) any | |
8 | later version. | |
9 | ||
10 | This file is distributed in the hope that it will be useful, but | |
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | General Public License for more details. | |
14 | ||
15 | Under Section 7 of GPL version 3, you are granted additional | |
16 | permissions described in the GCC Runtime Library Exception, version | |
17 | 3.1, as published by the Free Software Foundation. | |
18 | ||
19 | You should have received a copy of the GNU General Public License and | |
20 | a copy of the GCC Runtime Library Exception along with this program; | |
21 | see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
22 | <http://www.gnu.org/licenses/>. */ | |
23 | ||
24 | #include <stdbool.h> | |
d6491d15 KCY |
25 | |
26 | #define __SYNC_SUBWORD_COMPARE_AND_SWAP(TYPE, SIZE) \ | |
27 | \ | |
28 | TYPE \ | |
29 | __sync_val_compare_and_swap_##SIZE (TYPE *ptr, TYPE oldval, TYPE newval) \ | |
30 | { \ | |
45052655 | 31 | unsigned int valmask = (1 << (SIZE * 8)) - 1; \ |
af9bd920 KCY |
32 | unsigned int *wordptr = (unsigned int *)((__UINTPTR_TYPE__ ) ptr & ~3UL); \ |
33 | int shift = ((__UINTPTR_TYPE__ ) ptr & 3UL) * 8; \ | |
d6491d15 KCY |
34 | unsigned int wordmask = ~(valmask << shift); \ |
35 | unsigned int oldword = *wordptr; \ | |
36 | for (;;) \ | |
37 | { \ | |
38 | TYPE prevval = (oldword >> shift) & valmask; \ | |
39 | if (__builtin_expect (prevval != oldval, 0)) \ | |
40 | return prevval; \ | |
41 | unsigned int newword = oldword & wordmask; \ | |
42 | newword |= ((unsigned int) newval) << shift; \ | |
43 | unsigned int prevword \ | |
44 | = __sync_val_compare_and_swap_4 (wordptr, oldword, newword); \ | |
45 | if (__builtin_expect (prevword == oldword, 1)) \ | |
46 | return oldval; \ | |
47 | oldword = prevword; \ | |
48 | } \ | |
49 | } \ | |
50 | \ | |
51 | bool \ | |
52 | __sync_bool_compare_and_swap_##SIZE (TYPE *ptr, TYPE oldval, TYPE newval) \ | |
53 | { \ | |
54 | return __sync_val_compare_and_swap_##SIZE (ptr, oldval, newval) == oldval; \ | |
55 | } | |
56 | ||
57 | __SYNC_SUBWORD_COMPARE_AND_SWAP (unsigned char, 1) | |
58 | __SYNC_SUBWORD_COMPARE_AND_SWAP (unsigned short, 2) | |
59 | ||
45052655 TB |
60 | |
61 | #define __ATOMIC_COMPARE_EXCHANGE(TYPE,SIZE) \ | |
62 | bool \ | |
63 | __atomic_compare_exchange_##SIZE (TYPE *ptr, TYPE *expected, \ | |
64 | TYPE desired, bool weak, \ | |
65 | int success_memorder, int failure_memorder) \ | |
66 | { \ | |
67 | unsigned int valmask = (1 << (SIZE * 8)) - 1; \ | |
68 | \ | |
69 | unsigned int *wordptr = (unsigned int *)((__UINTPTR_TYPE__ ) ptr & ~3UL); \ | |
70 | int ptrshift = ((__UINTPTR_TYPE__ ) ptr & 3UL) * 8; \ | |
71 | unsigned int wordmask = ~(valmask << ptrshift); \ | |
72 | \ | |
73 | unsigned int ptrword = *wordptr; \ | |
74 | unsigned int exptword = ptrword & wordmask; \ | |
75 | unsigned int newword = ptrword & wordmask; \ | |
76 | exptword |= ((unsigned int) *expected) << ptrshift; \ | |
77 | newword |= ((unsigned int) desired) << ptrshift; \ | |
78 | if (__atomic_compare_exchange_4 (wordptr, &exptword, newword, weak, \ | |
79 | success_memorder, failure_memorder)) \ | |
80 | return true; \ | |
81 | *expected = (TYPE) ((exptword >> ptrshift) & valmask); \ | |
82 | return false; \ | |
83 | } | |
84 | ||
85 | __ATOMIC_COMPARE_EXCHANGE (unsigned char, 1) | |
86 | __ATOMIC_COMPARE_EXCHANGE (unsigned short, 2) |