From patchwork Tue Feb 3 12:52:27 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 435894 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id B70981401DE for ; Tue, 3 Feb 2015 23:56:53 +1100 (AEDT) Received: from localhost ([::1]:59102 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YId2B-00054p-CV for incoming@patchwork.ozlabs.org; Tue, 03 Feb 2015 07:56:51 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:40784) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YIcyM-0007TY-9a for qemu-devel@nongnu.org; Tue, 03 Feb 2015 07:52:55 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YIcyJ-0008CP-58 for qemu-devel@nongnu.org; Tue, 03 Feb 2015 07:52:54 -0500 Received: from mail-we0-x234.google.com ([2a00:1450:400c:c03::234]:32861) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YIcyI-0008CH-QA for qemu-devel@nongnu.org; Tue, 03 Feb 2015 07:52:51 -0500 Received: by mail-we0-f180.google.com with SMTP id m14so44775492wev.11 for ; Tue, 03 Feb 2015 04:52:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=IOaawTrSK9vEriyR0Ec4n/HGmjOpCzTP4oHDyPHbOwc=; b=ofuNDySnai8CWejZEthLSfhArCY8+OjUyQ1bQW47Dc9cEv5mbtqEYk+KX2nfst3QLs Tflrq2r9EGmB1RN9D/rsoqQdSbEIm3SBZr7GzNGFoBrakuqaX6EhNYRp89Dz6qmuB9zh vW/EgsOgcr6T62YGMGyWIeJco2ckhcGeBx4ilbkS8+iWPJVpzeHnWVVW3ONQK+zxberd QNifA6VlVY/UJY8LPupw+A+tEb0TEzlTHpBKN6mtIYSeh3caBh4b3KBTrA/NwF5RY1lq +6+SekH+7+PHL4TmkbCBolSFTjLe6HGAg0E1Klod8cwNvhc2UJbTuPgHv2intmqwTSTY gxng== X-Received: by 10.180.206.19 with SMTP id lk19mr34530912wic.83.1422967970146; Tue, 03 Feb 2015 04:52:50 -0800 (PST) Received: from playground.station (net-93-66-105-136.cust.vodafonedsl.it. [93.66.105.136]) by mx.google.com with ESMTPSA id n6sm32516460wjy.8.2015.02.03.04.52.48 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 03 Feb 2015 04:52:49 -0800 (PST) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Tue, 3 Feb 2015 13:52:27 +0100 Message-Id: <1422967948-3261-9-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1422967948-3261-1-git-send-email-pbonzini@redhat.com> References: <1422967948-3261-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2a00:1450:400c:c03::234 Cc: Mike Day , peter.maydell@linaro.org, famz@redhat.com, fred.konrad@greensocs.com Subject: [Qemu-devel] [PATCH 8/9] exec: convert ram_list to QLIST X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Mike Day QLIST has RCU-friendly primitives, so switch to it. Signed-off-by: Mike Day Signed-off-by: Paolo Bonzini Signed-off-by: Mike Day --- arch_init.c | 19 ++++++++-------- exec.c | 52 +++++++++++++++++++++++++------------------- include/exec/cpu-all.h | 4 ++-- scripts/dump-guest-memory.py | 8 +++---- 4 files changed, 46 insertions(+), 37 deletions(-) diff --git a/arch_init.c b/arch_init.c index b13f74b..757632b 100644 --- a/arch_init.c +++ b/arch_init.c @@ -523,7 +523,7 @@ static void migration_bitmap_sync(void) trace_migration_bitmap_sync_start(); 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); } 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; if (!block) - block = QTAILQ_FIRST(&ram_list.blocks); + block = QLIST_FIRST(&ram_list.blocks); while (true) { mr = block->mr; @@ -672,9 +672,9 @@ static int ram_find_and_save_block(QEMUFile *f, bool last_stage) } if (offset >= block->used_length) { offset = 0; - block = QTAILQ_NEXT(block, next); + block = QLIST_NEXT(block, next); if (!block) { - block = QTAILQ_FIRST(&ram_list.blocks); + block = QLIST_FIRST(&ram_list.blocks); complete_round = true; ram_bulk_stage = false; } @@ -728,8 +728,9 @@ uint64_t ram_bytes_total(void) RAMBlock *block; uint64_t total = 0; - QTAILQ_FOREACH(block, &ram_list.blocks, next) + QLIST_FOREACH(block, &ram_list.blocks, next) { total += block->used_length; + } return total; } @@ -830,7 +831,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque) * gaps due to alignment or unplugs. */ migration_dirty_pages = 0; - QTAILQ_FOREACH(block, &ram_list.blocks, next) { + QLIST_FOREACH(block, &ram_list.blocks, next) { uint64_t block_pages; block_pages = block->used_length >> TARGET_PAGE_BITS; @@ -843,7 +844,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque) 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_buffer(f, (uint8_t *)block->idstr, strlen(block->idstr)); qemu_put_be64(f, block->used_length); @@ -1029,7 +1030,7 @@ static inline void *host_from_stream_offset(QEMUFile *f, qemu_get_buffer(f, (uint8_t *)id, len); id[len] = 0; - QTAILQ_FOREACH(block, &ram_list.blocks, next) { + QLIST_FOREACH(block, &ram_list.blocks, next) { if (!strncmp(id, block->idstr, sizeof(id)) && block->max_length > offset) { return memory_region_get_ram_ptr(block->mr) + offset; @@ -1086,7 +1087,7 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) id[len] = 0; 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 (length != block->used_length) { Error *local_err = NULL; diff --git a/exec.c b/exec.c index 8239370..d1a5cef4 100644 --- a/exec.c +++ b/exec.c @@ -58,7 +58,7 @@ #if !defined(CONFIG_USER_ONLY) 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_io; @@ -815,7 +815,7 @@ static RAMBlock *qemu_get_ram_block(ram_addr_t addr) if (block && addr - block->offset < block->max_length) { goto found; } - QTAILQ_FOREACH(block, &ram_list.blocks, next) { + QLIST_FOREACH(block, &ram_list.blocks, next) { if (addr - block->offset < block->max_length) { 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 */ - if (QTAILQ_EMPTY(&ram_list.blocks)) + if (QLIST_EMPTY(&ram_list.blocks)) { return 0; + } - QTAILQ_FOREACH(block, &ram_list.blocks, next) { + QLIST_FOREACH(block, &ram_list.blocks, next) { ram_addr_t end, next = RAM_ADDR_MAX; 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) { next = MIN(next, next_block->offset); } @@ -1230,9 +1231,9 @@ ram_addr_t last_ram_offset(void) RAMBlock *block; 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); - + } return last; } @@ -1256,7 +1257,7 @@ static RAMBlock *find_ram_block(ram_addr_t addr) { RAMBlock *block; - QTAILQ_FOREACH(block, &ram_list.blocks, next) { + QLIST_FOREACH(block, &ram_list.blocks, next) { if (block->offset == addr) { 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); 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)) { fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n", 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) { RAMBlock *block; + RAMBlock *last_block = NULL; ram_addr_t old_ram_size, new_ram_size; 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. */ - QTAILQ_FOREACH(block, &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, &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(&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(&ram_list.blocks, new_block, next); } ram_list.mru_block = NULL; atomic_rcu_set(&ram_list.version, ram_list.version + 1); @@ -1546,9 +1554,9 @@ void qemu_ram_free_from_ptr(ram_addr_t addr) /* This assumes the iothread lock is taken here too. */ qemu_mutex_lock_ramlist(); - QTAILQ_FOREACH(block, &ram_list.blocks, next) { + QLIST_FOREACH(block, &ram_list.blocks, next) { if (addr == block->offset) { - QTAILQ_REMOVE(&ram_list.blocks, block, next); + QLIST_REMOVE(block, next); ram_list.mru_block = NULL; atomic_rcu_set(&ram_list.version, ram_list.version + 1); call_rcu(block, (void (*)(struct RAMBlock *))g_free, rcu); @@ -1582,9 +1590,9 @@ void qemu_ram_free(ram_addr_t addr) /* This assumes the iothread lock is taken here too. */ qemu_mutex_lock_ramlist(); - QTAILQ_FOREACH(block, &ram_list.blocks, next) { + QLIST_FOREACH(block, &ram_list.blocks, next) { if (addr == block->offset) { - QTAILQ_REMOVE(&ram_list.blocks, block, next); + QLIST_REMOVE(block, next); ram_list.mru_block = NULL; atomic_rcu_set(&ram_list.version, ram_list.version + 1); call_rcu(block, reclaim_ramblock, rcu); @@ -1602,7 +1610,7 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length) int flags; void *area, *vaddr; - QTAILQ_FOREACH(block, &ram_list.blocks, next) { + QLIST_FOREACH(block, &ram_list.blocks, next) { offset = addr - block->offset; if (offset < block->max_length) { 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); } else { 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 + *size > block->max_length) *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; } - QTAILQ_FOREACH(block, &ram_list.blocks, next) { + QLIST_FOREACH(block, &ram_list.blocks, next) { /* This case append when the block is not mapped. */ if (block->host == NULL) { continue; @@ -3015,7 +3023,7 @@ void qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque) { 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); } } diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index f7a3625..87b8658 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -282,7 +282,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; }; @@ -299,7 +299,7 @@ typedef struct RAMList { unsigned long *dirty_memory[DIRTY_MEMORY_NUM]; RAMBlock *mru_block; /* Protected by the ramlist lock. */ - QTAILQ_HEAD(, RAMBlock) blocks; + QLIST_HEAD(, RAMBlock) blocks; uint32_t version; } RAMList; extern RAMList ram_list; diff --git a/scripts/dump-guest-memory.py b/scripts/dump-guest-memory.py index 1ed8b67..dc8e44a 100644 --- a/scripts/dump-guest-memory.py +++ b/scripts/dump-guest-memory.py @@ -108,16 +108,16 @@ shape and this command should mostly work.""" assert (val["hi"] == 0) return val["lo"] - def qtailq_foreach(self, head, field_str): - var_p = head["tqh_first"] + def qlist_foreach(self, head, field_str): + var_p = head["lh_first"] while (var_p != 0): var = var_p.dereference() yield var - var_p = var[field_str]["tqe_next"] + var_p = var[field_str]["le_next"] def qemu_get_ram_block(self, ram_addr): 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"]): return block raise gdb.GdbError("Bad ram offset %x" % ram_addr)