Changeset ffa73c6 in mainline
- Timestamp:
- 2018-09-06T18:49:14Z (6 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 4621d23
- Parents:
- 7328ff4
- git-author:
- Jiří Zárevúcky <jiri.zarevucky@…> (2018-08-13 02:26:04)
- git-committer:
- Jiří Zárevúcky <jiri.zarevucky@…> (2018-09-06 18:49:14)
- Location:
- uspace/lib/c
- Files:
-
- 10 deleted
- 3 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/Makefile
r7328ff4 rffa73c6 129 129 generic/stdio/sstream.c \ 130 130 generic/stdio/vsprintf.c \ 131 generic/thread/atomic.c \132 131 generic/thread/fibril.c \ 133 132 generic/thread/fibril_synch.c \ -
uspace/lib/c/arch/arm32/Makefile.inc
r7328ff4 rffa73c6 29 29 30 30 ARCH_SOURCES = \ 31 arch/$(UARCH)/src/atomic.c \ 31 32 arch/$(UARCH)/src/entryjmp.S \ 32 33 arch/$(UARCH)/src/thread_entry.S \ -
uspace/lib/c/arch/arm32/src/atomic.c
r7328ff4 rffa73c6 1 1 /* 2 2 * Copyright (c) 2007 Michal Kebrt 3 * Copyright (c) 2018 CZ.NIC, z.s.p.o. 3 4 * All rights reserved. 4 5 * … … 27 28 */ 28 29 29 /** @addtogroup libcarm32 30 * @{ 31 */ 32 /** @file 33 * @brief Atomic operations. 30 /* 31 * Older ARMs don't have atomic instructions, so we need to define a bunch 32 * of symbols for GCC to use. 34 33 */ 35 34 36 #ifndef LIBC_arm32_ATOMIC_H_ 37 #define LIBC_arm32_ATOMIC_H_ 35 #include <stdbool.h> 38 36 39 #define LIBC_ARCH_ATOMIC_H_ 40 #define CAS 37 extern volatile unsigned *ras_page; 41 38 42 #include <atomicdflt.h> 43 #include <stdbool.h> 44 #include <stdint.h> 39 bool __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; 45 44 46 extern uintptr_t *ras_page; 47 48 static inline bool cas(atomic_t *val, atomic_count_t ov, atomic_count_t nv) 49 { 50 atomic_count_t ret = 0; 45 unsigned ov = *expected; 46 unsigned ret; 51 47 52 48 /* … … 61 57 " adr %[ret], 2f\n" 62 58 " str %[ret], %[rp1]\n" 59 63 60 " ldr %[ret], %[addr]\n" 64 61 " cmp %[ret], %[ov]\n" 65 62 " streq %[nv], %[addr]\n" 66 63 "2:\n" 67 " moveq %[ret], #1\n" 68 " movne %[ret], #0\n" 69 : [ret] "+&r" (ret), 64 : [ret] "=&r" (ret), 70 65 [rp0] "=m" (ras_page[0]), 71 66 [rp1] "=m" (ras_page[1]), 72 [addr] "+m" ( val->count)67 [addr] "+m" (*mem) 73 68 : [ov] "r" (ov), 74 [nv] "r" ( nv)69 [nv] "r" (desired) 75 70 : "memory" 76 71 ); 77 72 78 73 ras_page[0] = 0; 79 asm volatile (80 "" ::: "memory"81 );82 74 ras_page[1] = 0xffffffff; 83 75 84 return ret != 0; 76 if (ret == ov) 77 return true; 78 79 *expected = ret; 80 return false; 85 81 } 86 82 87 /** Atomic addition. 88 * 89 * @param val Where to add. 90 * @param i Value to be added. 91 * 92 * @return Value after addition. 93 * 94 */ 95 static inline atomic_count_t atomic_add(atomic_t *val, atomic_count_t i) 83 unsigned __atomic_fetch_add_4(volatile unsigned *mem, unsigned val, int model) 96 84 { 97 atomic_count_t ret = 0; 85 (void) model; 86 87 unsigned ret; 98 88 99 89 /* … … 112 102 " str %[ret], %[addr]\n" 113 103 "2:\n" 114 : [ret] " +&r" (ret),104 : [ret] "=&r" (ret), 115 105 [rp0] "=m" (ras_page[0]), 116 106 [rp1] "=m" (ras_page[1]), 117 [addr] "+m" ( val->count)118 : [imm] "r" ( i)107 [addr] "+m" (*mem) 108 : [imm] "r" (val) 119 109 ); 120 110 121 111 ras_page[0] = 0; 122 asm volatile (123 "" ::: "memory"124 );125 112 ras_page[1] = 0xffffffff; 126 113 127 return ret ;114 return ret - val; 128 115 } 129 116 130 131 /** Atomic increment. 132 * 133 * @param val Variable to be incremented. 134 * 135 */ 136 static inline void atomic_inc(atomic_t *val) 117 unsigned __atomic_fetch_sub_4(volatile unsigned *mem, unsigned val, int model) 137 118 { 138 atomic_add(val, 1);119 return __atomic_fetch_add_4(mem, -val, model); 139 120 } 140 121 141 142 /** Atomic decrement. 143 * 144 * @param val Variable to be decremented. 145 * 146 */ 147 static inline void atomic_dec(atomic_t *val) 122 void __sync_synchronize(void) 148 123 { 149 atomic_add(val, -1);124 // FIXME: Full memory barrier. We might need a syscall for this. 150 125 } 151 126 152 153 /** Atomic pre-increment. 154 * 155 * @param val Variable to be incremented. 156 * @return Value after incrementation. 157 * 158 */ 159 static inline atomic_count_t atomic_preinc(atomic_t *val) 127 unsigned __sync_add_and_fetch_4(volatile void *vptr, unsigned val) 160 128 { 161 return atomic_add(val, 1);129 return __atomic_fetch_add_4(vptr, val, __ATOMIC_SEQ_CST) + val; 162 130 } 163 131 164 165 /** Atomic pre-decrement. 166 * 167 * @param val Variable to be decremented. 168 * @return Value after decrementation. 169 * 170 */ 171 static inline atomic_count_t atomic_predec(atomic_t *val) 132 unsigned __sync_sub_and_fetch_4(volatile void *vptr, unsigned val) 172 133 { 173 return atomic_add(val, -1);134 return __atomic_fetch_sub_4(vptr, val, __ATOMIC_SEQ_CST) - val; 174 135 } 175 136 176 177 /** Atomic post-increment. 178 * 179 * @param val Variable to be incremented. 180 * @return Value before incrementation. 181 * 182 */ 183 static inline atomic_count_t atomic_postinc(atomic_t *val) 137 bool __sync_bool_compare_and_swap_4(volatile void *ptr, unsigned old_val, unsigned new_val) 184 138 { 185 return atomic_add(val, 1) - 1; 139 return __atomic_compare_exchange_4(ptr, &old_val, new_val, false, 140 __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); 186 141 } 187 142 188 189 /** Atomic post-decrement. 190 * 191 * @param val Variable to be decremented. 192 * @return Value before decrementation. 193 * 194 */ 195 static inline atomic_count_t atomic_postdec(atomic_t *val) 143 unsigned __sync_val_compare_and_swap_4(volatile void *ptr, unsigned old_val, unsigned new_val) 196 144 { 197 return atomic_add(val, -1) + 1; 145 __atomic_compare_exchange_4(ptr, &old_val, new_val, false, 146 __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); 147 return old_val; 198 148 } 199 149 200 201 #endif202 203 /** @}204 */ -
uspace/lib/c/include/atomic.h
r7328ff4 rffa73c6 36 36 #define LIBC_ATOMIC_H_ 37 37 38 #include <libarch/atomic.h> 38 #include <stdatomic.h> 39 #include <stdbool.h> 40 #include <stddef.h> 41 42 typedef size_t atomic_count_t; 43 typedef ssize_t atomic_signed_t; 44 45 typedef struct atomic { 46 volatile atomic_size_t count; 47 } atomic_t; 48 49 static inline void atomic_set(atomic_t *val, atomic_count_t i) 50 { 51 atomic_store(&val->count, i); 52 } 53 54 static inline atomic_count_t atomic_get(atomic_t *val) 55 { 56 return atomic_load(&val->count); 57 } 58 59 static inline bool cas(atomic_t *val, atomic_count_t ov, atomic_count_t nv) 60 { 61 return atomic_compare_exchange_strong(&val->count, &ov, nv); 62 } 63 64 static inline atomic_count_t atomic_postinc(atomic_t *val) 65 { 66 return atomic_fetch_add(&val->count, 1); 67 } 68 69 static inline atomic_count_t atomic_postdec(atomic_t *val) 70 { 71 return atomic_fetch_sub(&val->count, 1); 72 } 73 74 static inline atomic_count_t atomic_preinc(atomic_t *val) 75 { 76 return atomic_postinc(val) + 1; 77 } 78 79 static inline atomic_count_t atomic_predec(atomic_t *val) 80 { 81 return atomic_postdec(val) - 1; 82 } 83 84 static inline void atomic_inc(atomic_t *val) 85 { 86 atomic_postinc(val); 87 } 88 89 static inline void atomic_dec(atomic_t *val) 90 { 91 atomic_postdec(val); 92 } 39 93 40 94 #endif
Note:
See TracChangeset
for help on using the changeset viewer.