193b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro/*
293b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro * Copyright (C) 2010 The Android Open Source Project
393b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro *
493b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro * Licensed under the Apache License, Version 2.0 (the "License");
593b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro * you may not use this file except in compliance with the License.
693b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro * You may obtain a copy of the License at
793b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro *
893b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro *      http://www.apache.org/licenses/LICENSE-2.0
993b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro *
1093b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro * Unless required by applicable law or agreed to in writing, software
1193b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro * distributed under the License is distributed on an "AS IS" BASIS,
1293b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1393b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro * See the License for the specific language governing permissions and
1493b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro * limitations under the License.
1593b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro */
1693b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro
1793b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro#ifndef ANDROID_CUTILS_ATOMIC_ARM_H
1893b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro#define ANDROID_CUTILS_ATOMIC_ARM_H
1993b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro
2093b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro#include <stdint.h>
2193b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro
225206d5971208fab8208669dabc98bbb9f7e4a45aBen Cheng#ifndef ANDROID_ATOMIC_INLINE
235206d5971208fab8208669dabc98bbb9f7e4a45aBen Cheng#define ANDROID_ATOMIC_INLINE inline __attribute__((always_inline))
245206d5971208fab8208669dabc98bbb9f7e4a45aBen Cheng#endif
255206d5971208fab8208669dabc98bbb9f7e4a45aBen Cheng
2662980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogersextern ANDROID_ATOMIC_INLINE void android_compiler_barrier()
2793b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro{
2893b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    __asm__ __volatile__ ("" : : : "memory");
2993b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro}
3093b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro
3162980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogersextern ANDROID_ATOMIC_INLINE void android_memory_barrier()
32464431e65fbede57b0d41d230fe6f6dc465c20f8Brian Carlstrom{
3362980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogers#if ANDROID_SMP == 0
34464431e65fbede57b0d41d230fe6f6dc465c20f8Brian Carlstrom    android_compiler_barrier();
3562980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogers#else
3693b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    __asm__ __volatile__ ("dmb" : : : "memory");
3762980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogers#endif
3893b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro}
3962980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogers
4062980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogersextern ANDROID_ATOMIC_INLINE void android_memory_store_barrier()
41464431e65fbede57b0d41d230fe6f6dc465c20f8Brian Carlstrom{
4262980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogers#if ANDROID_SMP == 0
4362980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogers    android_compiler_barrier();
4493b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro#else
4562980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogers    __asm__ __volatile__ ("dmb st" : : : "memory");
4693b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro#endif
4762980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogers}
4893b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro
495206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE
505206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengint32_t android_atomic_acquire_load(volatile const int32_t *ptr)
5193b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro{
5293b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    int32_t value = *ptr;
5393b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    android_memory_barrier();
5493b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    return value;
5593b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro}
5693b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro
575206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE
585206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengint32_t android_atomic_release_load(volatile const int32_t *ptr)
5993b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro{
6093b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    android_memory_barrier();
6193b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    return *ptr;
6293b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro}
6393b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro
6462980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogersextern ANDROID_ATOMIC_INLINE
6562980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogersvoid android_atomic_acquire_store(int32_t value, volatile int32_t *ptr)
6693b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro{
6793b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    *ptr = value;
6893b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    android_memory_barrier();
6993b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro}
7093b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro
7162980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogersextern ANDROID_ATOMIC_INLINE
7262980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogersvoid android_atomic_release_store(int32_t value, volatile int32_t *ptr)
7393b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro{
7493b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    android_memory_barrier();
7593b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    *ptr = value;
7693b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro}
7793b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro
7862980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogersextern ANDROID_ATOMIC_INLINE
7962980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogersint android_atomic_cas(int32_t old_value, int32_t new_value,
8062980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogers                       volatile int32_t *ptr)
8193b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro{
8293b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    int32_t prev, status;
8393b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    do {
8493b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro        __asm__ __volatile__ ("ldrex %0, [%3]\n"
8593b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro                              "mov %1, #0\n"
8693b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro                              "teq %0, %4\n"
8762980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogers#ifdef __thumb2__
8862980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogers                              "it eq\n"
8962980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogers#endif
9093b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro                              "strexeq %1, %5, [%3]"
9193b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro                              : "=&r" (prev), "=&r" (status), "+m"(*ptr)
9293b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro                              : "r" (ptr), "Ir" (old_value), "r" (new_value)
9393b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro                              : "cc");
9493b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    } while (__builtin_expect(status != 0, 0));
9593b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    return prev != old_value;
9693b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro}
9793b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro
9862980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogersextern ANDROID_ATOMIC_INLINE
9962980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogersint android_atomic_acquire_cas(int32_t old_value, int32_t new_value,
10062980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogers                               volatile int32_t *ptr)
10193b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro{
10293b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    int status = android_atomic_cas(old_value, new_value, ptr);
10393b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    android_memory_barrier();
10493b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    return status;
10593b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro}
10693b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro
10762980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogersextern ANDROID_ATOMIC_INLINE
10862980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogersint android_atomic_release_cas(int32_t old_value, int32_t new_value,
10962980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogers                               volatile int32_t *ptr)
11093b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro{
11193b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    android_memory_barrier();
11293b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    return android_atomic_cas(old_value, new_value, ptr);
11393b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro}
11493b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro
11562980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogersextern ANDROID_ATOMIC_INLINE
11662980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogersint32_t android_atomic_add(int32_t increment, volatile int32_t *ptr)
11793b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro{
11893b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    int32_t prev, tmp, status;
11993b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    android_memory_barrier();
12093b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    do {
12193b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro        __asm__ __volatile__ ("ldrex %0, [%4]\n"
12293b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro                              "add %1, %0, %5\n"
12393b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro                              "strex %2, %1, [%4]"
12493b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro                              : "=&r" (prev), "=&r" (tmp),
12593b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro                                "=&r" (status), "+m" (*ptr)
12693b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro                              : "r" (ptr), "Ir" (increment)
12793b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro                              : "cc");
12893b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    } while (__builtin_expect(status != 0, 0));
12993b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    return prev;
13093b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro}
13193b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro
1325206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE int32_t android_atomic_inc(volatile int32_t *addr)
133d55f0adfb5ec4202ad5bd5d188e66c0f6a27b0aaCarl Shapiro{
13493b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    return android_atomic_add(1, addr);
13593b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro}
13693b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro
1375206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE int32_t android_atomic_dec(volatile int32_t *addr)
138d55f0adfb5ec4202ad5bd5d188e66c0f6a27b0aaCarl Shapiro{
13993b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    return android_atomic_add(-1, addr);
14093b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro}
14193b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro
14262980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogersextern ANDROID_ATOMIC_INLINE
14362980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogersint32_t android_atomic_and(int32_t value, volatile int32_t *ptr)
14493b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro{
14593b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    int32_t prev, tmp, status;
14693b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    android_memory_barrier();
14793b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    do {
14893b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro        __asm__ __volatile__ ("ldrex %0, [%4]\n"
14993b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro                              "and %1, %0, %5\n"
15093b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro                              "strex %2, %1, [%4]"
15193b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro                              : "=&r" (prev), "=&r" (tmp),
15293b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro                                "=&r" (status), "+m" (*ptr)
15393b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro                              : "r" (ptr), "Ir" (value)
15493b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro                              : "cc");
15593b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    } while (__builtin_expect(status != 0, 0));
15693b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    return prev;
15793b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro}
15893b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro
15962980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogersextern ANDROID_ATOMIC_INLINE
16062980e817c51c56208971ed5c3e98e0cb21e1685Ian Rogersint32_t android_atomic_or(int32_t value, volatile int32_t *ptr)
16193b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro{
16293b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    int32_t prev, tmp, status;
16393b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    android_memory_barrier();
16493b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    do {
16593b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro        __asm__ __volatile__ ("ldrex %0, [%4]\n"
16693b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro                              "orr %1, %0, %5\n"
16793b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro                              "strex %2, %1, [%4]"
16893b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro                              : "=&r" (prev), "=&r" (tmp),
16993b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro                                "=&r" (status), "+m" (*ptr)
17093b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro                              : "r" (ptr), "Ir" (value)
17193b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro                              : "cc");
17293b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    } while (__builtin_expect(status != 0, 0));
17393b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro    return prev;
17493b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro}
17593b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro
17693b0cb40c18cae594c931677be2b9214420610b7Carl Shapiro#endif /* ANDROID_CUTILS_ATOMIC_ARM_H */
177