00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00036 #ifndef LIBC_arm32_ATOMIC_H_
00037 #define LIBC_arm32_ATOMIC_H_
00038
00039 #define LIBC_ARCH_ATOMIC_H_
00040 #define CAS
00041
00042 #include <atomicdflt.h>
00043 #include <bool.h>
00044 #include <sys/types.h>
00045
00046 extern uintptr_t *ras_page;
00047
00048 static inline bool cas(atomic_t *val, atomic_count_t ov, atomic_count_t nv)
00049 {
00050 atomic_count_t ret = 0;
00051
00052
00053
00054
00055
00056
00057 asm volatile (
00058 "1:\n"
00059 " adr %[ret], 1b\n"
00060 " str %[ret], %[rp0]\n"
00061 " adr %[ret], 2f\n"
00062 " str %[ret], %[rp1]\n"
00063 " ldr %[ret], %[addr]\n"
00064 " cmp %[ret], %[ov]\n"
00065 " streq %[nv], %[addr]\n"
00066 "2:\n"
00067 " moveq %[ret], #1\n"
00068 " movne %[ret], #0\n"
00069 : [ret] "+&r" (ret),
00070 [rp0] "=m" (ras_page[0]),
00071 [rp1] "=m" (ras_page[1]),
00072 [addr] "+m" (val->count)
00073 : [ov] "r" (ov),
00074 [nv] "r" (nv)
00075 : "memory"
00076 );
00077
00078 ras_page[0] = 0;
00079 asm volatile (
00080 "" ::: "memory"
00081 );
00082 ras_page[1] = 0xffffffff;
00083
00084 return (bool) ret;
00085 }
00086
00095 static inline atomic_count_t atomic_add(atomic_t *val, atomic_count_t i)
00096 {
00097 atomic_count_t ret = 0;
00098
00099
00100
00101
00102
00103
00104 asm volatile (
00105 "1:\n"
00106 " adr %[ret], 1b\n"
00107 " str %[ret], %[rp0]\n"
00108 " adr %[ret], 2f\n"
00109 " str %[ret], %[rp1]\n"
00110 " ldr %[ret], %[addr]\n"
00111 " add %[ret], %[ret], %[imm]\n"
00112 " str %[ret], %[addr]\n"
00113 "2:\n"
00114 : [ret] "+&r" (ret),
00115 [rp0] "=m" (ras_page[0]),
00116 [rp1] "=m" (ras_page[1]),
00117 [addr] "+m" (val->count)
00118 : [imm] "r" (i)
00119 );
00120
00121 ras_page[0] = 0;
00122 asm volatile (
00123 "" ::: "memory"
00124 );
00125 ras_page[1] = 0xffffffff;
00126
00127 return ret;
00128 }
00129
00130
00136 static inline void atomic_inc(atomic_t *val)
00137 {
00138 atomic_add(val, 1);
00139 }
00140
00141
00147 static inline void atomic_dec(atomic_t *val)
00148 {
00149 atomic_add(val, -1);
00150 }
00151
00152
00159 static inline atomic_count_t atomic_preinc(atomic_t *val)
00160 {
00161 return atomic_add(val, 1);
00162 }
00163
00164
00171 static inline atomic_count_t atomic_predec(atomic_t *val)
00172 {
00173 return atomic_add(val, -1);
00174 }
00175
00176
00183 static inline atomic_count_t atomic_postinc(atomic_t *val)
00184 {
00185 return atomic_add(val, 1) - 1;
00186 }
00187
00188
00195 static inline atomic_count_t atomic_postdec(atomic_t *val)
00196 {
00197 return atomic_add(val, -1) + 1;
00198 }
00199
00200
00201 #endif
00202