source: mainline/uspace/lib/c/arch/arm32/src/atomic.c@ eec201d

Last change on this file since eec201d was 09ab0a9a, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Fix vertical spacing with new Ccheck revision.

  • Property mode set to 100644
File size: 5.0 KB
Line 
1/*
2 * Copyright (c) 2007 Michal Kebrt
3 * Copyright (c) 2018 CZ.NIC, z.s.p.o.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/*
31 * Older ARMs don't have atomic instructions, so we need to define a bunch
32 * of symbols for GCC to use.
33 */
34
35#include <stdbool.h>
36
37extern volatile unsigned *ras_page;
38
39bool __atomic_compare_exchange_4(volatile unsigned *mem, unsigned *expected, unsigned desired, bool weak, int success, int failure)
40{
41 (void) success;
42 (void) failure;
43 (void) weak;
44
45 unsigned ov = *expected;
46 unsigned ret;
47
48 /*
49 * The following instructions between labels 1 and 2 constitute a
50 * Restartable Atomic Sequence. Should the sequence be non-atomic,
51 * the kernel will restart it.
52 */
53 asm volatile (
54 "1:\n"
55 " adr %[ret], 1b\n"
56 " str %[ret], %[rp0]\n"
57 " adr %[ret], 2f\n"
58 " str %[ret], %[rp1]\n"
59
60 " ldr %[ret], %[addr]\n"
61 " cmp %[ret], %[ov]\n"
62 " streq %[nv], %[addr]\n"
63 "2:\n"
64 : [ret] "=&r" (ret),
65 [rp0] "=m" (ras_page[0]),
66 [rp1] "=m" (ras_page[1]),
67 [addr] "+m" (*mem)
68 : [ov] "r" (ov),
69 [nv] "r" (desired)
70 : "memory"
71 );
72
73 ras_page[0] = 0;
74 ras_page[1] = 0xffffffff;
75
76 if (ret == ov)
77 return true;
78
79 *expected = ret;
80 return false;
81}
82
83unsigned short __atomic_fetch_add_2(volatile unsigned short *mem, unsigned short val, int model)
84{
85 (void) model;
86
87 unsigned short ret;
88
89 /*
90 * The following instructions between labels 1 and 2 constitute a
91 * Restartable Atomic Seqeunce. Should the sequence be non-atomic,
92 * the kernel will restart it.
93 */
94 asm volatile (
95 "1:\n"
96 " adr %[ret], 1b\n"
97 " str %[ret], %[rp0]\n"
98 " adr %[ret], 2f\n"
99 " str %[ret], %[rp1]\n"
100 " ldrh %[ret], %[addr]\n"
101 " add %[ret], %[ret], %[imm]\n"
102 " strh %[ret], %[addr]\n"
103 "2:\n"
104 : [ret] "=&r" (ret),
105 [rp0] "=m" (ras_page[0]),
106 [rp1] "=m" (ras_page[1]),
107 [addr] "+m" (*mem)
108 : [imm] "r" (val)
109 );
110
111 ras_page[0] = 0;
112 ras_page[1] = 0xffffffff;
113
114 return ret - val;
115}
116
117unsigned __atomic_fetch_add_4(volatile unsigned *mem, unsigned val, int model)
118{
119 (void) model;
120
121 unsigned ret;
122
123 /*
124 * The following instructions between labels 1 and 2 constitute a
125 * Restartable Atomic Seqeunce. Should the sequence be non-atomic,
126 * the kernel will restart it.
127 */
128 asm volatile (
129 "1:\n"
130 " adr %[ret], 1b\n"
131 " str %[ret], %[rp0]\n"
132 " adr %[ret], 2f\n"
133 " str %[ret], %[rp1]\n"
134 " ldr %[ret], %[addr]\n"
135 " add %[ret], %[ret], %[imm]\n"
136 " str %[ret], %[addr]\n"
137 "2:\n"
138 : [ret] "=&r" (ret),
139 [rp0] "=m" (ras_page[0]),
140 [rp1] "=m" (ras_page[1]),
141 [addr] "+m" (*mem)
142 : [imm] "r" (val)
143 );
144
145 ras_page[0] = 0;
146 ras_page[1] = 0xffffffff;
147
148 return ret - val;
149}
150
151unsigned __atomic_fetch_sub_4(volatile unsigned *mem, unsigned val, int model)
152{
153 return __atomic_fetch_add_4(mem, -val, model);
154}
155
156void __sync_synchronize(void)
157{
158 // FIXME: Full memory barrier. We might need a syscall for this.
159}
160
161unsigned __sync_add_and_fetch_4(volatile void *vptr, unsigned val)
162{
163 return __atomic_fetch_add_4(vptr, val, __ATOMIC_SEQ_CST) + val;
164}
165
166unsigned __sync_sub_and_fetch_4(volatile void *vptr, unsigned val)
167{
168 return __atomic_fetch_sub_4(vptr, val, __ATOMIC_SEQ_CST) - val;
169}
170
171bool __sync_bool_compare_and_swap_4(volatile void *ptr, unsigned old_val, unsigned new_val)
172{
173 return __atomic_compare_exchange_4(ptr, &old_val, new_val, false,
174 __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
175}
176
177unsigned __sync_val_compare_and_swap_4(volatile void *ptr, unsigned old_val, unsigned new_val)
178{
179 __atomic_compare_exchange_4(ptr, &old_val, new_val, false,
180 __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
181 return old_val;
182}
Note: See TracBrowser for help on using the repository browser.