exec: convert ram_list to QLIST

QLIST has RCU-friendly primitives, so switch to it.

Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Mike Day <ncmike@ncultra.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Mike Day 2015-01-21 13:45:24 +01:00 committed by Paolo Bonzini
parent ae3a7047d0
commit 0d53d9fe8a
4 changed files with 46 additions and 37 deletions

View file

@ -523,7 +523,7 @@ static void migration_bitmap_sync(void)
trace_migration_bitmap_sync_start(); trace_migration_bitmap_sync_start();
address_space_sync_dirty_bitmap(&address_space_memory); address_space_sync_dirty_bitmap(&address_space_memory);
QTAILQ_FOREACH(block, &ram_list.blocks, next) { QLIST_FOREACH(block, &ram_list.blocks, next) {
migration_bitmap_sync_range(block->mr->ram_addr, block->used_length); migration_bitmap_sync_range(block->mr->ram_addr, block->used_length);
} }
trace_migration_bitmap_sync_end(migration_dirty_pages trace_migration_bitmap_sync_end(migration_dirty_pages
@ -661,7 +661,7 @@ static int ram_find_and_save_block(QEMUFile *f, bool last_stage)
MemoryRegion *mr; MemoryRegion *mr;
if (!block) if (!block)
block = QTAILQ_FIRST(&ram_list.blocks); block = QLIST_FIRST(&ram_list.blocks);
while (true) { while (true) {
mr = block->mr; mr = block->mr;
@ -672,9 +672,9 @@ static int ram_find_and_save_block(QEMUFile *f, bool last_stage)
} }
if (offset >= block->used_length) { if (offset >= block->used_length) {
offset = 0; offset = 0;
block = QTAILQ_NEXT(block, next); block = QLIST_NEXT(block, next);
if (!block) { if (!block) {
block = QTAILQ_FIRST(&ram_list.blocks); block = QLIST_FIRST(&ram_list.blocks);
complete_round = true; complete_round = true;
ram_bulk_stage = false; ram_bulk_stage = false;
} }
@ -728,8 +728,9 @@ uint64_t ram_bytes_total(void)
RAMBlock *block; RAMBlock *block;
uint64_t total = 0; uint64_t total = 0;
QTAILQ_FOREACH(block, &ram_list.blocks, next) QLIST_FOREACH(block, &ram_list.blocks, next) {
total += block->used_length; total += block->used_length;
}
return total; return total;
} }
@ -831,7 +832,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
* gaps due to alignment or unplugs. * gaps due to alignment or unplugs.
*/ */
migration_dirty_pages = 0; migration_dirty_pages = 0;
QTAILQ_FOREACH(block, &ram_list.blocks, next) { QLIST_FOREACH(block, &ram_list.blocks, next) {
uint64_t block_pages; uint64_t block_pages;
block_pages = block->used_length >> TARGET_PAGE_BITS; block_pages = block->used_length >> TARGET_PAGE_BITS;
@ -844,7 +845,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
qemu_put_be64(f, ram_bytes_total() | RAM_SAVE_FLAG_MEM_SIZE); qemu_put_be64(f, ram_bytes_total() | RAM_SAVE_FLAG_MEM_SIZE);
QTAILQ_FOREACH(block, &ram_list.blocks, next) { QLIST_FOREACH(block, &ram_list.blocks, next) {
qemu_put_byte(f, strlen(block->idstr)); qemu_put_byte(f, strlen(block->idstr));
qemu_put_buffer(f, (uint8_t *)block->idstr, strlen(block->idstr)); qemu_put_buffer(f, (uint8_t *)block->idstr, strlen(block->idstr));
qemu_put_be64(f, block->used_length); qemu_put_be64(f, block->used_length);
@ -1031,7 +1032,7 @@ static inline void *host_from_stream_offset(QEMUFile *f,
qemu_get_buffer(f, (uint8_t *)id, len); qemu_get_buffer(f, (uint8_t *)id, len);
id[len] = 0; id[len] = 0;
QTAILQ_FOREACH(block, &ram_list.blocks, next) { QLIST_FOREACH(block, &ram_list.blocks, next) {
if (!strncmp(id, block->idstr, sizeof(id)) && if (!strncmp(id, block->idstr, sizeof(id)) &&
block->max_length > offset) { block->max_length > offset) {
return memory_region_get_ram_ptr(block->mr) + offset; return memory_region_get_ram_ptr(block->mr) + offset;
@ -1088,7 +1089,7 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
id[len] = 0; id[len] = 0;
length = qemu_get_be64(f); length = qemu_get_be64(f);
QTAILQ_FOREACH(block, &ram_list.blocks, next) { QLIST_FOREACH(block, &ram_list.blocks, next) {
if (!strncmp(id, block->idstr, sizeof(id))) { if (!strncmp(id, block->idstr, sizeof(id))) {
if (length != block->used_length) { if (length != block->used_length) {
Error *local_err = NULL; Error *local_err = NULL;

52
exec.c
View file

@ -58,7 +58,7 @@
#if !defined(CONFIG_USER_ONLY) #if !defined(CONFIG_USER_ONLY)
static bool in_migration; static bool in_migration;
RAMList ram_list = { .blocks = QTAILQ_HEAD_INITIALIZER(ram_list.blocks) }; RAMList ram_list = { .blocks = QLIST_HEAD_INITIALIZER(ram_list.blocks) };
static MemoryRegion *system_memory; static MemoryRegion *system_memory;
static MemoryRegion *system_io; static MemoryRegion *system_io;
@ -815,7 +815,7 @@ static RAMBlock *qemu_get_ram_block(ram_addr_t addr)
if (block && addr - block->offset < block->max_length) { if (block && addr - block->offset < block->max_length) {
goto found; goto found;
} }
QTAILQ_FOREACH(block, &ram_list.blocks, next) { QLIST_FOREACH(block, &ram_list.blocks, next) {
if (addr - block->offset < block->max_length) { if (addr - block->offset < block->max_length) {
goto found; goto found;
} }
@ -1197,15 +1197,16 @@ static ram_addr_t find_ram_offset(ram_addr_t size)
assert(size != 0); /* it would hand out same offset multiple times */ assert(size != 0); /* it would hand out same offset multiple times */
if (QTAILQ_EMPTY(&ram_list.blocks)) if (QLIST_EMPTY(&ram_list.blocks)) {
return 0; return 0;
}
QTAILQ_FOREACH(block, &ram_list.blocks, next) { QLIST_FOREACH(block, &ram_list.blocks, next) {
ram_addr_t end, next = RAM_ADDR_MAX; ram_addr_t end, next = RAM_ADDR_MAX;
end = block->offset + block->max_length; end = block->offset + block->max_length;
QTAILQ_FOREACH(next_block, &ram_list.blocks, next) { QLIST_FOREACH(next_block, &ram_list.blocks, next) {
if (next_block->offset >= end) { if (next_block->offset >= end) {
next = MIN(next, next_block->offset); next = MIN(next, next_block->offset);
} }
@ -1230,9 +1231,9 @@ ram_addr_t last_ram_offset(void)
RAMBlock *block; RAMBlock *block;
ram_addr_t last = 0; ram_addr_t last = 0;
QTAILQ_FOREACH(block, &ram_list.blocks, next) QLIST_FOREACH(block, &ram_list.blocks, next) {
last = MAX(last, block->offset + block->max_length); last = MAX(last, block->offset + block->max_length);
}
return last; return last;
} }
@ -1256,7 +1257,7 @@ static RAMBlock *find_ram_block(ram_addr_t addr)
{ {
RAMBlock *block; RAMBlock *block;
QTAILQ_FOREACH(block, &ram_list.blocks, next) { QLIST_FOREACH(block, &ram_list.blocks, next) {
if (block->offset == addr) { if (block->offset == addr) {
return block; return block;
} }
@ -1284,7 +1285,7 @@ void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev)
pstrcat(new_block->idstr, sizeof(new_block->idstr), name); pstrcat(new_block->idstr, sizeof(new_block->idstr), name);
qemu_mutex_lock_ramlist(); qemu_mutex_lock_ramlist();
QTAILQ_FOREACH(block, &ram_list.blocks, next) { QLIST_FOREACH(block, &ram_list.blocks, next) {
if (block != new_block && !strcmp(block->idstr, new_block->idstr)) { if (block != new_block && !strcmp(block->idstr, new_block->idstr)) {
fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n", fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n",
new_block->idstr); new_block->idstr);
@ -1366,6 +1367,7 @@ int qemu_ram_resize(ram_addr_t base, ram_addr_t newsize, Error **errp)
static ram_addr_t ram_block_add(RAMBlock *new_block, Error **errp) static ram_addr_t ram_block_add(RAMBlock *new_block, Error **errp)
{ {
RAMBlock *block; RAMBlock *block;
RAMBlock *last_block = NULL;
ram_addr_t old_ram_size, new_ram_size; ram_addr_t old_ram_size, new_ram_size;
old_ram_size = last_ram_offset() >> TARGET_PAGE_BITS; old_ram_size = last_ram_offset() >> TARGET_PAGE_BITS;
@ -1392,16 +1394,22 @@ static ram_addr_t ram_block_add(RAMBlock *new_block, Error **errp)
} }
} }
/* Keep the list sorted from biggest to smallest block. */ /* Keep the list sorted from biggest to smallest block. Unlike QTAILQ,
QTAILQ_FOREACH(block, &ram_list.blocks, next) { * QLIST (which has an RCU-friendly variant) does not have insertion at
* tail, so save the last element in last_block.
*/
QLIST_FOREACH(block, &ram_list.blocks, next) {
last_block = block;
if (block->max_length < new_block->max_length) { if (block->max_length < new_block->max_length) {
break; break;
} }
} }
if (block) { if (block) {
QTAILQ_INSERT_BEFORE(block, new_block, next); QLIST_INSERT_BEFORE(block, new_block, next);
} else { } else if (last_block) {
QTAILQ_INSERT_TAIL(&ram_list.blocks, new_block, next); QLIST_INSERT_AFTER(last_block, new_block, next);
} else { /* list is empty */
QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);
} }
ram_list.mru_block = NULL; ram_list.mru_block = NULL;
@ -1546,9 +1554,9 @@ void qemu_ram_free_from_ptr(ram_addr_t addr)
/* This assumes the iothread lock is taken here too. */ /* This assumes the iothread lock is taken here too. */
qemu_mutex_lock_ramlist(); qemu_mutex_lock_ramlist();
QTAILQ_FOREACH(block, &ram_list.blocks, next) { QLIST_FOREACH(block, &ram_list.blocks, next) {
if (addr == block->offset) { if (addr == block->offset) {
QTAILQ_REMOVE(&ram_list.blocks, block, next); QLIST_REMOVE(block, next);
ram_list.mru_block = NULL; ram_list.mru_block = NULL;
ram_list.version++; ram_list.version++;
g_free_rcu(block, rcu); g_free_rcu(block, rcu);
@ -1582,9 +1590,9 @@ void qemu_ram_free(ram_addr_t addr)
/* This assumes the iothread lock is taken here too. */ /* This assumes the iothread lock is taken here too. */
qemu_mutex_lock_ramlist(); qemu_mutex_lock_ramlist();
QTAILQ_FOREACH(block, &ram_list.blocks, next) { QLIST_FOREACH(block, &ram_list.blocks, next) {
if (addr == block->offset) { if (addr == block->offset) {
QTAILQ_REMOVE(&ram_list.blocks, block, next); QLIST_REMOVE(block, next);
ram_list.mru_block = NULL; ram_list.mru_block = NULL;
ram_list.version++; ram_list.version++;
call_rcu(block, reclaim_ramblock, rcu); call_rcu(block, reclaim_ramblock, rcu);
@ -1602,7 +1610,7 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
int flags; int flags;
void *area, *vaddr; void *area, *vaddr;
QTAILQ_FOREACH(block, &ram_list.blocks, next) { QLIST_FOREACH(block, &ram_list.blocks, next) {
offset = addr - block->offset; offset = addr - block->offset;
if (offset < block->max_length) { if (offset < block->max_length) {
vaddr = ramblock_ptr(block, offset); vaddr = ramblock_ptr(block, offset);
@ -1707,7 +1715,7 @@ static void *qemu_ram_ptr_length(ram_addr_t addr, hwaddr *size)
return xen_map_cache(addr, *size, 1); return xen_map_cache(addr, *size, 1);
} else { } else {
RAMBlock *block; RAMBlock *block;
QTAILQ_FOREACH(block, &ram_list.blocks, next) { QLIST_FOREACH(block, &ram_list.blocks, next) {
if (addr - block->offset < block->max_length) { if (addr - block->offset < block->max_length) {
if (addr - block->offset + *size > block->max_length) if (addr - block->offset + *size > block->max_length)
*size = block->max_length - addr + block->offset; *size = block->max_length - addr + block->offset;
@ -1747,7 +1755,7 @@ MemoryRegion *qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
goto found; goto found;
} }
QTAILQ_FOREACH(block, &ram_list.blocks, next) { QLIST_FOREACH(block, &ram_list.blocks, next) {
/* This case append when the block is not mapped. */ /* This case append when the block is not mapped. */
if (block->host == NULL) { if (block->host == NULL) {
continue; continue;
@ -3019,7 +3027,7 @@ void qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque)
{ {
RAMBlock *block; RAMBlock *block;
QTAILQ_FOREACH(block, &ram_list.blocks, next) { QLIST_FOREACH(block, &ram_list.blocks, next) {
func(block->host, block->offset, block->used_length, opaque); func(block->host, block->offset, block->used_length, opaque);
} }
} }

View file

@ -282,7 +282,7 @@ struct RAMBlock {
/* Reads can take either the iothread or the ramlist lock. /* Reads can take either the iothread or the ramlist lock.
* Writes must take both locks. * Writes must take both locks.
*/ */
QTAILQ_ENTRY(RAMBlock) next; QLIST_ENTRY(RAMBlock) next;
int fd; int fd;
}; };
@ -299,7 +299,7 @@ typedef struct RAMList {
unsigned long *dirty_memory[DIRTY_MEMORY_NUM]; unsigned long *dirty_memory[DIRTY_MEMORY_NUM];
RAMBlock *mru_block; RAMBlock *mru_block;
/* Protected by the ramlist lock. */ /* Protected by the ramlist lock. */
QTAILQ_HEAD(, RAMBlock) blocks; QLIST_HEAD(, RAMBlock) blocks;
uint32_t version; uint32_t version;
} RAMList; } RAMList;
extern RAMList ram_list; extern RAMList ram_list;

View file

@ -108,16 +108,16 @@ shape and this command should mostly work."""
assert (val["hi"] == 0) assert (val["hi"] == 0)
return val["lo"] return val["lo"]
def qtailq_foreach(self, head, field_str): def qlist_foreach(self, head, field_str):
var_p = head["tqh_first"] var_p = head["lh_first"]
while (var_p != 0): while (var_p != 0):
var = var_p.dereference() var = var_p.dereference()
yield var yield var
var_p = var[field_str]["tqe_next"] var_p = var[field_str]["le_next"]
def qemu_get_ram_block(self, ram_addr): def qemu_get_ram_block(self, ram_addr):
ram_blocks = gdb.parse_and_eval("ram_list.blocks") ram_blocks = gdb.parse_and_eval("ram_list.blocks")
for block in self.qtailq_foreach(ram_blocks, "next"): for block in self.qlist_foreach(ram_blocks, "next"):
if (ram_addr - block["offset"] < block["length"]): if (ram_addr - block["offset"] < block["length"]):
return block return block
raise gdb.GdbError("Bad ram offset %x" % ram_addr) raise gdb.GdbError("Bad ram offset %x" % ram_addr)