exec: convert ram_list to QLIST

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

Backports commit 0d53d9fe8a0dcb849bc7c9836e9e6a287f9aa787 from qemu
This commit is contained in:
Mike Day 2018-02-18 18:37:38 -05:00 committed by Lioncash
parent 15b3a9358e
commit 2b93290eea
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
3 changed files with 31 additions and 24 deletions

View file

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

View file

@ -697,7 +697,7 @@ static RAMBlock *qemu_get_ram_block(struct uc_struct *uc, ram_addr_t addr)
if (block && addr - block->offset < block->max_length) {
return block;
}
QTAILQ_FOREACH(block, &uc->ram_list.blocks, next) {
QLIST_FOREACH(block, &uc->ram_list.blocks, next) {
if (addr - block->offset < block->max_length) {
goto found;
}
@ -944,15 +944,16 @@ static ram_addr_t find_ram_offset(struct uc_struct *uc, ram_addr_t size)
assert(size != 0); /* it would hand out same offset multiple times */
if (QTAILQ_EMPTY(&uc->ram_list.blocks))
if (QLIST_EMPTY(&uc->ram_list.blocks)) {
return 0;
}
QTAILQ_FOREACH(block, &uc->ram_list.blocks, next) {
QLIST_FOREACH(block, &uc->ram_list.blocks, next) {
ram_addr_t end, next = RAM_ADDR_MAX;
end = block->offset + block->max_length;
QTAILQ_FOREACH(next_block, &uc->ram_list.blocks, next) {
QLIST_FOREACH(next_block, &uc->ram_list.blocks, next) {
if (next_block->offset >= end) {
next = MIN(next, next_block->offset);
}
@ -977,9 +978,9 @@ ram_addr_t last_ram_offset(struct uc_struct *uc)
RAMBlock *block;
ram_addr_t last = 0;
QTAILQ_FOREACH(block, &uc->ram_list.blocks, next)
QLIST_FOREACH(block, &uc->ram_list.blocks, next) {
last = MAX(last, block->offset + block->max_length);
}
return last;
}
@ -991,7 +992,7 @@ static RAMBlock *find_ram_block(struct uc_struct *uc, ram_addr_t addr)
{
RAMBlock *block;
QTAILQ_FOREACH(block, &uc->ram_list.blocks, next) {
QLIST_FOREACH(block, &uc->ram_list.blocks, next) {
if (block->offset == addr) {
return block;
}
@ -1066,6 +1067,7 @@ int qemu_ram_resize(struct uc_struct *uc, ram_addr_t base, ram_addr_t newsize, E
static ram_addr_t ram_block_add(struct uc_struct *uc, RAMBlock *new_block, Error **errp)
{
RAMBlock *block;
RAMBlock *last_block = NULL;
ram_addr_t old_ram_size, new_ram_size;
old_ram_size = last_ram_offset(uc) >> TARGET_PAGE_BITS;
@ -1084,16 +1086,22 @@ static ram_addr_t ram_block_add(struct uc_struct *uc, RAMBlock *new_block, Error
memory_try_enable_merging(new_block->host, new_block->max_length);
}
/* Keep the list sorted from biggest to smallest block. */
QTAILQ_FOREACH(block, &uc->ram_list.blocks, next) {
/* Keep the list sorted from biggest to smallest block. Unlike QTAILQ,
* QLIST (which has an RCU-friendly variant) does not have insertion at
* tail, so save the last element in last_block.
*/
QLIST_FOREACH(block, &uc->ram_list.blocks, next) {
last_block = block;
if (block->max_length < new_block->max_length) {
break;
}
}
if (block) {
QTAILQ_INSERT_BEFORE(block, new_block, next);
} else {
QTAILQ_INSERT_TAIL(&uc->ram_list.blocks, new_block, next);
QLIST_INSERT_BEFORE(block, new_block, next);
} else if (last_block) {
QLIST_INSERT_AFTER(last_block, new_block, next);
} else { /* list is empty */
QLIST_INSERT_HEAD(&uc->ram_list.blocks, new_block, next);
}
uc->ram_list.mru_block = NULL;
@ -1191,9 +1199,9 @@ void qemu_ram_free(struct uc_struct *uc, ram_addr_t addr)
{
RAMBlock *block;
QTAILQ_FOREACH(block, &uc->ram_list.blocks, next) {
QLIST_FOREACH(block, &uc->ram_list.blocks, next) {
if (addr == block->offset) {
QTAILQ_REMOVE(&uc->ram_list.blocks, block, next);
QLIST_REMOVE(block, next);
uc->ram_list.mru_block = NULL;
uc->ram_list.version++;
if (block->flags & RAM_PREALLOC) {
@ -1220,7 +1228,7 @@ void qemu_ram_remap(struct uc_struct *uc, ram_addr_t addr, ram_addr_t length)
int flags;
void *area, *vaddr;
QTAILQ_FOREACH(block, &uc->ram_list.blocks, next) {
QLIST_FOREACH(block, &uc->ram_list.blocks, next) {
offset = addr - block->offset;
if (offset < block->max_length) {
vaddr = ramblock_ptr(block, offset);
@ -1350,7 +1358,7 @@ RAMBlock *qemu_ram_block_from_host(struct uc_struct* uc, void *ptr, bool round_o
goto found;
}
QTAILQ_FOREACH(block, &uc->ram_list.blocks, next) {
QLIST_FOREACH(block, &uc->ram_list.blocks, next) {
/* This case append when the block is not mapped. */
if (block->host == NULL) {
continue;
@ -1382,8 +1390,8 @@ RAMBlock *qemu_ram_block_by_name(struct uc_struct* uc, const char *name)
{
RAMBlock *block;
// Unicorn: Changed from QLIST_FOREACH_RCU to QTAILQ_FOREACH
QTAILQ_FOREACH(block, &uc->ram_list.blocks, next) {
// Unicorn: Changed from QLIST_FOREACH_RCU to QLIST_FOREACH
QLIST_FOREACH(block, &uc->ram_list.blocks, next) {
if (!strcmp(name, block->idstr)) {
return block;
}
@ -2852,7 +2860,7 @@ void qemu_ram_foreach_block(struct uc_struct *uc, RAMBlockIterFunc func, void *o
{
RAMBlock *block;
QTAILQ_FOREACH(block, &uc->ram_list.blocks, next) {
QLIST_FOREACH(block, &uc->ram_list.blocks, next) {
func(block->host, block->offset, block->used_length, opaque);
}
}

5
uc.c
View file

@ -152,9 +152,8 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result)
uc->arch = arch;
uc->mode = mode;
// uc->ram_list = { .blocks = QTAILQ_HEAD_INITIALIZER(ram_list.blocks) };
uc->ram_list.blocks.tqh_first = NULL;
uc->ram_list.blocks.tqh_last = &(uc->ram_list.blocks.tqh_first);
// uc->ram_list = { .blocks = QLIST_HEAD_INITIALIZER(ram_list.blocks) };
uc->ram_list.blocks.lh_first = NULL;
uc->memory_listeners.tqh_first = NULL;
uc->memory_listeners.tqh_last = &uc->memory_listeners.tqh_first;