Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This introduces read/set accessors for int64_t and uint64_t. Signed-off-by: Emilio G. Cota <cota@braap.org> Message-Id: <20180910232752.31565-3-cota@braap.org> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
- Loading branch information
Showing
4 changed files
with
121 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
/* | ||
* Copyright (C) 2018, Emilio G. Cota <cota@braap.org> | ||
* | ||
* License: GNU GPL, version 2 or later. | ||
* See the COPYING file in the top-level directory. | ||
*/ | ||
#include "qemu/osdep.h" | ||
#include "qemu/atomic.h" | ||
#include "qemu/thread.h" | ||
|
||
#ifdef CONFIG_ATOMIC64 | ||
#error This file must only be compiled if !CONFIG_ATOMIC64 | ||
#endif | ||
|
||
/* | ||
* When !CONFIG_ATOMIC64, we serialize both reads and writes with spinlocks. | ||
* We use an array of spinlocks, with padding computed at run-time based on | ||
* the host's dcache line size. | ||
* We point to the array with a void * to simplify the padding's computation. | ||
* Each spinlock is located every lock_size bytes. | ||
*/ | ||
static void *lock_array; | ||
static size_t lock_size; | ||
|
||
/* | ||
* Systems without CONFIG_ATOMIC64 are unlikely to have many cores, so we use a | ||
* small array of locks. | ||
*/ | ||
#define NR_LOCKS 16 | ||
|
||
static QemuSpin *addr_to_lock(const void *addr) | ||
{ | ||
uintptr_t a = (uintptr_t)addr; | ||
uintptr_t idx; | ||
|
||
idx = a >> qemu_dcache_linesize_log; | ||
idx ^= (idx >> 8) ^ (idx >> 16); | ||
idx &= NR_LOCKS - 1; | ||
return lock_array + idx * lock_size; | ||
} | ||
|
||
#define GEN_READ(name, type) \ | ||
type name(const type *ptr) \ | ||
{ \ | ||
QemuSpin *lock = addr_to_lock(ptr); \ | ||
type ret; \ | ||
\ | ||
qemu_spin_lock(lock); \ | ||
ret = *ptr; \ | ||
qemu_spin_unlock(lock); \ | ||
return ret; \ | ||
} | ||
|
||
GEN_READ(atomic_read_i64, int64_t) | ||
GEN_READ(atomic_read_u64, uint64_t) | ||
#undef GEN_READ | ||
|
||
#define GEN_SET(name, type) \ | ||
void name(type *ptr, type val) \ | ||
{ \ | ||
QemuSpin *lock = addr_to_lock(ptr); \ | ||
\ | ||
qemu_spin_lock(lock); \ | ||
*ptr = val; \ | ||
qemu_spin_unlock(lock); \ | ||
} | ||
|
||
GEN_SET(atomic_set_i64, int64_t) | ||
GEN_SET(atomic_set_u64, uint64_t) | ||
#undef GEN_SET | ||
|
||
void atomic64_init(void) | ||
{ | ||
int i; | ||
|
||
lock_size = ROUND_UP(sizeof(QemuSpin), qemu_dcache_linesize); | ||
lock_array = qemu_memalign(qemu_dcache_linesize, lock_size * NR_LOCKS); | ||
for (i = 0; i < NR_LOCKS; i++) { | ||
QemuSpin *lock = lock_array + i * lock_size; | ||
|
||
qemu_spin_init(lock); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters