1/** \file
2 *  \brief compare and set (cas) implementations
3 */
4
5/*
6 * Copyright (c) 2009, ETH Zurich.
7 * All rights reserved.
8 *
9 * This file is distributed under the terms in the attached LICENSE file.
10 * If you do not find this file, copies can be found by writing to:
11 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
12 */
13
14#ifndef CAS_H_
15#define CAS_H_
16
17#include <stdint.h>
18#include <stdbool.h>
19
20/*
21 * \brief compare and set. If the value at address
22 *        equals old, set it to new otherwise don't write to address.
23 *        Returns the actual previous value at the address.
24 */
25static inline uintptr_t cas_ret_act(volatile uintptr_t *address, uintptr_t old,
26        uintptr_t new)
27{
28    register uintptr_t res;
29    __asm volatile("lock; cmpxchgq %2,%0    \n\t"
30                   : "+m" (*address), "=a" (res)
31                   : "r" (new), "a" (old)
32                   : "memory");
33    return res;
34}
35
36/*
37 * \brief compare and set. If the value at address
38 *        equals old, set it to new and return true,
39 *        otherwise don't write to address and return false
40 */
41static inline bool cas(volatile uintptr_t *address, uintptr_t old,
42        uintptr_t new)
43{
44    register bool res;
45    __asm volatile("lock; cmpxchgq %2,%0     \n\t"
46                   "setz %1                  \n\t"
47                   : "+m" (*address), "=q" (res)
48                   : "r" (new), "a" (old)
49                   : "memory");
50    return res;
51}
52
53#endif /* CAS_H_ */
54