]>
git.proxmox.com Git - mirror_qemu.git/blob - include/qemu/stats64.h
2 * Atomic operations on 64-bit quantities.
4 * Copyright (C) 2017 Red Hat, Inc.
6 * Author: Paolo Bonzini <pbonzini@redhat.com>
8 * This work is licensed under the terms of the GNU GPL, version 2 or later.
9 * See the COPYING file in the top-level directory.
12 #ifndef QEMU_STATS64_H
13 #define QEMU_STATS64_H
15 #include "qemu/atomic.h"
17 /* This provides atomic operations on 64-bit type, using a reader-writer
18 * spinlock on architectures that do not have 64-bit accesses. Even on
19 * those architectures, it tries hard not to take the lock.
22 typedef struct Stat64
{
23 #ifdef CONFIG_ATOMIC64
24 aligned_uint64_t value
;
31 #ifdef CONFIG_ATOMIC64
32 static inline void stat64_init(Stat64
*s
, uint64_t value
)
34 /* This is not guaranteed to be atomic! */
35 *s
= (Stat64
) { value
};
38 static inline uint64_t stat64_get(const Stat64
*s
)
40 return qatomic_read__nocheck(&s
->value
);
43 static inline void stat64_set(Stat64
*s
, uint64_t value
)
45 qatomic_set__nocheck(&s
->value
, value
);
48 static inline void stat64_add(Stat64
*s
, uint64_t value
)
50 qatomic_add(&s
->value
, value
);
53 static inline void stat64_min(Stat64
*s
, uint64_t value
)
55 uint64_t orig
= qatomic_read__nocheck(&s
->value
);
56 while (orig
> value
) {
57 orig
= qatomic_cmpxchg__nocheck(&s
->value
, orig
, value
);
61 static inline void stat64_max(Stat64
*s
, uint64_t value
)
63 uint64_t orig
= qatomic_read__nocheck(&s
->value
);
64 while (orig
< value
) {
65 orig
= qatomic_cmpxchg__nocheck(&s
->value
, orig
, value
);
69 uint64_t stat64_get(const Stat64
*s
);
70 void stat64_set(Stat64
*s
, uint64_t value
);
71 bool stat64_min_slow(Stat64
*s
, uint64_t value
);
72 bool stat64_max_slow(Stat64
*s
, uint64_t value
);
73 bool stat64_add32_carry(Stat64
*s
, uint32_t low
, uint32_t high
);
75 static inline void stat64_init(Stat64
*s
, uint64_t value
)
77 /* This is not guaranteed to be atomic! */
78 *s
= (Stat64
) { .low
= value
, .high
= value
>> 32, .lock
= 0 };
81 static inline void stat64_add(Stat64
*s
, uint64_t value
)
85 low
= (uint32_t) value
;
88 qatomic_add(&s
->high
, high
);
94 uint32_t orig
= s
->low
;
95 uint32_t result
= orig
+ low
;
98 if (result
< low
|| high
) {
99 /* If the high part is affected, take the lock. */
100 if (stat64_add32_carry(s
, low
, high
)) {
106 /* No carry, try with a 32-bit cmpxchg. The result is independent of
107 * the high 32 bits, so it can race just fine with stat64_add32_carry
108 * and even stat64_get!
110 old
= qatomic_cmpxchg(&s
->low
, orig
, result
);
117 static inline void stat64_min(Stat64
*s
, uint64_t value
)
120 uint32_t orig_low
, orig_high
;
123 low
= (uint32_t) value
;
125 orig_high
= qatomic_read(&s
->high
);
126 if (orig_high
< high
) {
130 if (orig_high
== high
) {
131 /* High 32 bits are equal. Read low after high, otherwise we
132 * can get a false positive (e.g. 0x1235,0x0000 changes to
133 * 0x1234,0x8000 and we read it as 0x1234,0x0000). Pairs with
134 * the write barrier in stat64_min_slow.
137 orig_low
= qatomic_read(&s
->low
);
138 if (orig_low
<= low
) {
142 /* See if we were lucky and a writer raced against us. The
143 * barrier is theoretically unnecessary, but if we remove it
144 * we may miss being lucky.
147 orig_high
= qatomic_read(&s
->high
);
148 if (orig_high
< high
) {
153 /* If the value changes in any way, we have to take the lock. */
154 } while (!stat64_min_slow(s
, value
));
157 static inline void stat64_max(Stat64
*s
, uint64_t value
)
160 uint32_t orig_low
, orig_high
;
163 low
= (uint32_t) value
;
165 orig_high
= qatomic_read(&s
->high
);
166 if (orig_high
> high
) {
170 if (orig_high
== high
) {
171 /* High 32 bits are equal. Read low after high, otherwise we
172 * can get a false positive (e.g. 0x1234,0x8000 changes to
173 * 0x1235,0x0000 and we read it as 0x1235,0x8000). Pairs with
174 * the write barrier in stat64_max_slow.
177 orig_low
= qatomic_read(&s
->low
);
178 if (orig_low
>= low
) {
182 /* See if we were lucky and a writer raced against us. The
183 * barrier is theoretically unnecessary, but if we remove it
184 * we may miss being lucky.
187 orig_high
= qatomic_read(&s
->high
);
188 if (orig_high
> high
) {
193 /* If the value changes in any way, we have to take the lock. */
194 } while (!stat64_max_slow(s
, value
));