| Index: src/include/linux/mips/atomic_ops.h
|
| diff --git a/src/include/linux/mips/atomic_ops.h b/src/include/linux/mips/atomic_ops.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..0f86ca96f80a1359d367eb7c60277e1588609b9e
|
| --- /dev/null
|
| +++ b/src/include/linux/mips/atomic_ops.h
|
| @@ -0,0 +1,76 @@
|
| +/*
|
| + * Copyright (c) 2012 The Native Client Authors. All rights reserved.
|
| + * Use of this source code is governed by a BSD-style license that can be
|
| + * found in the LICENSE file.
|
| + */
|
| +
|
| +#ifndef NATIVE_CLIENT_SRC_INCLUDE_LINUX_MIPS_ATOMIC_OPS_LINUX_MIPS_H_
|
| +#define NATIVE_CLIENT_SRC_INCLUDE_LINUX_MIPS_ATOMIC_OPS_LINUX_MIPS_H_ 1
|
| +
|
| +/*
|
| + * Used only by trusted code. Untrusted code uses gcc intrinsics.
|
| + */
|
| +
|
| +#include "native_client/src/include/portability.h"
|
| +#include <stdint.h>
|
| +
|
| +typedef int32_t Atomic32;
|
| +
|
| +static INLINE Atomic32 CompareAndSwap(volatile Atomic32* ptr,
|
| + Atomic32 old_value,
|
| + Atomic32 new_value) {
|
| + Atomic32 ret;
|
| +
|
| + __asm__ __volatile__("1:\n"
|
| + "ll %0, %1\n" /* ret = *ptr */
|
| + "bne %0, %3, 2f\n" /* if (ret != old_value) goto 2 */
|
| + "nop\n" /* delay slot nop */
|
| + "sc %2, %1\n" /* *ptr = new_value (with atomic check) */
|
| + "beqz %2, 1b\n" /* start again on atomic error */
|
| + "nop\n" /* delay slot nop */
|
| + "2:\n"
|
| + : "=&r" (ret), "=m" (*ptr), "+&r" (new_value)
|
| + : "Ir" (old_value), "r" (new_value), "m" (*ptr)
|
| + : "memory");
|
| +
|
| +
|
| + return ret;
|
| +}
|
| +
|
| +static INLINE Atomic32 AtomicExchange(volatile Atomic32* ptr,
|
| + Atomic32 new_value) {
|
| + Atomic32 tmp, old;
|
| +
|
| + __asm__ __volatile__("1:\n"
|
| + "ll %1, %2\n" /* old = *ptr */
|
| + "move %0, %3\n" /* tmp = new_value */
|
| + "sc %0, %2\n" /* *ptr = tmp (with atomic check) */
|
| + "beqz %0, 1b\n" /* start again on atomic error */
|
| + "nop\n" /* delay slot nop */
|
| + : "=&r" (tmp), "=&r" (old), "=m" (*ptr)
|
| + : "r" (new_value), "m" (*ptr)
|
| + : "memory");
|
| +
|
| + return old;
|
| +}
|
| +
|
| +static INLINE Atomic32 AtomicIncrement(volatile Atomic32* ptr,
|
| + Atomic32 increment) {
|
| + Atomic32 tmp, res;
|
| +
|
| + __asm__ __volatile__("1:\n"
|
| + "ll %0, %2\n" /* tmp = *ptr */
|
| + "addu %0, %3\n" /* tmp = tmp + increment */
|
| + "move %1, %0\n" /* res = tmp */
|
| + "sc %0, %2\n" /* *ptr = tmp (with atomic check) */
|
| + "beqz %0, 1b\n" /* start again on atomic error */
|
| + "nop\n" /* delay slot nop */
|
| + : "=&r" (tmp), "=&r" (res), "=m" (*ptr)
|
| + : "Ir" (increment), "m" (*ptr)
|
| + : "memory");
|
| + /* res now holds the final value. */
|
| +
|
| + return res;
|
| +}
|
| +
|
| +#endif /* NATIVE_CLIENT_SRC_INCLUDE_LINUX_MIPS_ATOMIC_OPS_LINUX_MIPS_H_ */
|
|
|