mirror of https://github.com/xqemu/xqemu.git
exec: protect mru_block with RCU
Hence, freeing a RAMBlock has to be switched to call_rcu. Reviewed-by: Fam Zheng <famz@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
439c5e02d5
commit
43771539d4
52
exec.c
52
exec.c
|
@ -811,7 +811,7 @@ static RAMBlock *qemu_get_ram_block(ram_addr_t addr)
|
||||||
RAMBlock *block;
|
RAMBlock *block;
|
||||||
|
|
||||||
/* The list is protected by the iothread lock here. */
|
/* The list is protected by the iothread lock here. */
|
||||||
block = ram_list.mru_block;
|
block = atomic_rcu_read(&ram_list.mru_block);
|
||||||
if (block && addr - block->offset < block->max_length) {
|
if (block && addr - block->offset < block->max_length) {
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
|
@ -825,6 +825,22 @@ static RAMBlock *qemu_get_ram_block(ram_addr_t addr)
|
||||||
abort();
|
abort();
|
||||||
|
|
||||||
found:
|
found:
|
||||||
|
/* It is safe to write mru_block outside the iothread lock. This
|
||||||
|
* is what happens:
|
||||||
|
*
|
||||||
|
* mru_block = xxx
|
||||||
|
* rcu_read_unlock()
|
||||||
|
* xxx removed from list
|
||||||
|
* rcu_read_lock()
|
||||||
|
* read mru_block
|
||||||
|
* mru_block = NULL;
|
||||||
|
* call_rcu(reclaim_ramblock, xxx);
|
||||||
|
* rcu_read_unlock()
|
||||||
|
*
|
||||||
|
* atomic_rcu_set is not needed here. The block was already published
|
||||||
|
* when it was placed into the list. Here we're just making an extra
|
||||||
|
* copy of the pointer.
|
||||||
|
*/
|
||||||
ram_list.mru_block = block;
|
ram_list.mru_block = block;
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
@ -1526,13 +1542,31 @@ void qemu_ram_free_from_ptr(ram_addr_t addr)
|
||||||
QTAILQ_REMOVE(&ram_list.blocks, block, next);
|
QTAILQ_REMOVE(&ram_list.blocks, block, next);
|
||||||
ram_list.mru_block = NULL;
|
ram_list.mru_block = NULL;
|
||||||
ram_list.version++;
|
ram_list.version++;
|
||||||
g_free(block);
|
g_free_rcu(block, rcu);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qemu_mutex_unlock_ramlist();
|
qemu_mutex_unlock_ramlist();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void reclaim_ramblock(RAMBlock *block)
|
||||||
|
{
|
||||||
|
if (block->flags & RAM_PREALLOC) {
|
||||||
|
;
|
||||||
|
} else if (xen_enabled()) {
|
||||||
|
xen_invalidate_map_cache_entry(block->host);
|
||||||
|
#ifndef _WIN32
|
||||||
|
} else if (block->fd >= 0) {
|
||||||
|
munmap(block->host, block->max_length);
|
||||||
|
close(block->fd);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
qemu_anon_ram_free(block->host, block->max_length);
|
||||||
|
}
|
||||||
|
g_free(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Called with the iothread lock held */
|
||||||
void qemu_ram_free(ram_addr_t addr)
|
void qemu_ram_free(ram_addr_t addr)
|
||||||
{
|
{
|
||||||
RAMBlock *block;
|
RAMBlock *block;
|
||||||
|
@ -1544,19 +1578,7 @@ void qemu_ram_free(ram_addr_t addr)
|
||||||
QTAILQ_REMOVE(&ram_list.blocks, block, next);
|
QTAILQ_REMOVE(&ram_list.blocks, block, next);
|
||||||
ram_list.mru_block = NULL;
|
ram_list.mru_block = NULL;
|
||||||
ram_list.version++;
|
ram_list.version++;
|
||||||
if (block->flags & RAM_PREALLOC) {
|
call_rcu(block, reclaim_ramblock, rcu);
|
||||||
;
|
|
||||||
} else if (xen_enabled()) {
|
|
||||||
xen_invalidate_map_cache_entry(block->host);
|
|
||||||
#ifndef _WIN32
|
|
||||||
} else if (block->fd >= 0) {
|
|
||||||
munmap(block->host, block->max_length);
|
|
||||||
close(block->fd);
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
qemu_anon_ram_free(block->host, block->max_length);
|
|
||||||
}
|
|
||||||
g_free(block);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "exec/memory.h"
|
#include "exec/memory.h"
|
||||||
#include "qemu/thread.h"
|
#include "qemu/thread.h"
|
||||||
#include "qom/cpu.h"
|
#include "qom/cpu.h"
|
||||||
|
#include "qemu/rcu.h"
|
||||||
|
|
||||||
/* some important defines:
|
/* some important defines:
|
||||||
*
|
*
|
||||||
|
@ -268,6 +269,7 @@ CPUArchState *cpu_copy(CPUArchState *env);
|
||||||
typedef struct RAMBlock RAMBlock;
|
typedef struct RAMBlock RAMBlock;
|
||||||
|
|
||||||
struct RAMBlock {
|
struct RAMBlock {
|
||||||
|
struct rcu_head rcu;
|
||||||
struct MemoryRegion *mr;
|
struct MemoryRegion *mr;
|
||||||
uint8_t *host;
|
uint8_t *host;
|
||||||
ram_addr_t offset;
|
ram_addr_t offset;
|
||||||
|
|
Loading…
Reference in New Issue