qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: John Snow <jsnow@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Marc Marí" <marc.mari.barcelo@gmail.com>
Subject: Re: [Qemu-devel] [PATCH] libqos: Convert malloc-pc allocator to a generic allocator
Date: Wed, 22 Oct 2014 12:33:37 -0400	[thread overview]
Message-ID: <5447DC61.50005@redhat.com> (raw)
In-Reply-To: <1413624257-7714-1-git-send-email-marc.mari.barcelo@gmail.com>



On 10/18/2014 05:24 AM, Marc Marí wrote:
> The allocator in malloc-pc has been extracted, so it can be used in every arch.
> This operation showed that both the alloc and free functions can be also
> generic.
> Because of this, the QGuestAllocator has been removed from is function to wrap
> the alloc and free function, and now just contains the allocator parameters.
> As a result, only the allocator initalizer and unitializer are arch dependent.
>
> Signed-off-by: Marc Marí <marc.mari.barcelo@gmail.com>
> ---
>   tests/Makefile           |    2 +-
>   tests/libqos/malloc-pc.c |  280 +---------------------------------------------
>   tests/libqos/malloc-pc.h |   11 +-
>   tests/libqos/malloc.c    |  268 ++++++++++++++++++++++++++++++++++++++++++++
>   tests/libqos/malloc.h    |   45 +++++---
>   5 files changed, 307 insertions(+), 299 deletions(-)
>   create mode 100644 tests/libqos/malloc.c
>
> diff --git a/tests/Makefile b/tests/Makefile
> index 834279c..15bc670 100644
> --- a/tests/Makefile
> +++ b/tests/Makefile
> @@ -296,7 +296,7 @@ tests/test-opts-visitor$(EXESUF): tests/test-opts-visitor.o $(test-qapi-obj-y) l
>   tests/test-mul64$(EXESUF): tests/test-mul64.o libqemuutil.a
>   tests/test-bitops$(EXESUF): tests/test-bitops.o libqemuutil.a
>
> -libqos-obj-y = tests/libqos/pci.o tests/libqos/fw_cfg.o
> +libqos-obj-y = tests/libqos/pci.o tests/libqos/fw_cfg.o tests/libqos/malloc.o
>   libqos-obj-y += tests/libqos/i2c.o
>   libqos-pc-obj-y = $(libqos-obj-y) tests/libqos/pci-pc.o
>   libqos-pc-obj-y += tests/libqos/malloc-pc.o
> diff --git a/tests/libqos/malloc-pc.c b/tests/libqos/malloc-pc.c
> index f4218c6..c9c48fd 100644
> --- a/tests/libqos/malloc-pc.c
> +++ b/tests/libqos/malloc-pc.c
> @@ -17,296 +17,28 @@
>   #include "hw/nvram/fw_cfg.h"
>
>   #include "qemu-common.h"
> -#include "qemu/queue.h"
>   #include <glib.h>
>
>   #define PAGE_SIZE (4096)
>
> -#define MLIST_ENTNAME entries
> -typedef QTAILQ_HEAD(MemList, MemBlock) MemList;
> -typedef struct MemBlock {
> -    QTAILQ_ENTRY(MemBlock) MLIST_ENTNAME;
> -    uint64_t size;
> -    uint64_t addr;
> -} MemBlock;
> -
> -typedef struct PCAlloc
> -{
> -    QGuestAllocator alloc;
> -    PCAllocOpts opts;
> -    uint64_t start;
> -    uint64_t end;
> -
> -    MemList used;
> -    MemList free;
> -} PCAlloc;
> -
> -static MemBlock *mlist_new(uint64_t addr, uint64_t size)
> -{
> -    MemBlock *block;
> -
> -    if (!size) {
> -        return NULL;
> -    }
> -    block = g_malloc0(sizeof(MemBlock));
> -
> -    block->addr = addr;
> -    block->size = size;
> -
> -    return block;
> -}
> -
> -static void mlist_delete(MemList *list, MemBlock *node)
> -{
> -    g_assert(list && node);
> -    QTAILQ_REMOVE(list, node, MLIST_ENTNAME);
> -    g_free(node);
> -}
> -
> -static MemBlock *mlist_find_key(MemList *head, uint64_t addr)
> -{
> -    MemBlock *node;
> -    QTAILQ_FOREACH(node, head, MLIST_ENTNAME) {
> -        if (node->addr == addr) {
> -            return node;
> -        }
> -    }
> -    return NULL;
> -}
> -
> -static MemBlock *mlist_find_space(MemList *head, uint64_t size)
> -{
> -    MemBlock *node;
> -
> -    QTAILQ_FOREACH(node, head, MLIST_ENTNAME) {
> -        if (node->size >= size) {
> -            return node;
> -        }
> -    }
> -    return NULL;
> -}
> -
> -static MemBlock *mlist_sort_insert(MemList *head, MemBlock *insr)
> -{
> -    MemBlock *node;
> -    g_assert(head && insr);
> -
> -    QTAILQ_FOREACH(node, head, MLIST_ENTNAME) {
> -        if (insr->addr < node->addr) {
> -            QTAILQ_INSERT_BEFORE(node, insr, MLIST_ENTNAME);
> -            return insr;
> -        }
> -    }
> -
> -    QTAILQ_INSERT_TAIL(head, insr, MLIST_ENTNAME);
> -    return insr;
> -}
> -
> -static inline uint64_t mlist_boundary(MemBlock *node)
> -{
> -    return node->size + node->addr;
> -}
> -
> -static MemBlock *mlist_join(MemList *head, MemBlock *left, MemBlock *right)
> -{
> -    g_assert(head && left && right);
> -
> -    left->size += right->size;
> -    mlist_delete(head, right);
> -    return left;
> -}
> -
> -static void mlist_coalesce(MemList *head, MemBlock *node)
> -{
> -    g_assert(node);
> -    MemBlock *left;
> -    MemBlock *right;
> -    char merge;
> -
> -    do {
> -        merge = 0;
> -        left = QTAILQ_PREV(node, MemList, MLIST_ENTNAME);
> -        right = QTAILQ_NEXT(node, MLIST_ENTNAME);
> -
> -        /* clowns to the left of me */
> -        if (left && mlist_boundary(left) == node->addr) {
> -            node = mlist_join(head, left, node);
> -            merge = 1;
> -        }
> -
> -        /* jokers to the right */
> -        if (right && mlist_boundary(node) == right->addr) {
> -            node = mlist_join(head, node, right);
> -            merge = 1;
> -        }
> -
> -    } while (merge);
> -}
> -
> -static uint64_t pc_mlist_fulfill(PCAlloc *s, MemBlock *freenode, uint64_t size)
> -{
> -    uint64_t addr;
> -    MemBlock *usednode;
> -
> -    g_assert(freenode);
> -    g_assert_cmpint(freenode->size, >=, size);
> -
> -    addr = freenode->addr;
> -    if (freenode->size == size) {
> -        /* re-use this freenode as our used node */
> -        QTAILQ_REMOVE(&s->free, freenode, MLIST_ENTNAME);
> -        usednode = freenode;
> -    } else {
> -        /* adjust the free node and create a new used node */
> -        freenode->addr += size;
> -        freenode->size -= size;
> -        usednode = mlist_new(addr, size);
> -    }
> -
> -    mlist_sort_insert(&s->used, usednode);
> -    return addr;
> -}
> -
> -/* To assert the correctness of the list.
> - * Used only if PC_ALLOC_PARANOID is set. */
> -static void pc_mlist_check(PCAlloc *s)
> -{
> -    MemBlock *node;
> -    uint64_t addr = s->start > 0 ? s->start - 1 : 0;
> -    uint64_t next = s->start;
> -
> -    QTAILQ_FOREACH(node, &s->free, MLIST_ENTNAME) {
> -        g_assert_cmpint(node->addr, >, addr);
> -        g_assert_cmpint(node->addr, >=, next);
> -        addr = node->addr;
> -        next = node->addr + node->size;
> -    }
> -
> -    addr = s->start > 0 ? s->start - 1 : 0;
> -    next = s->start;
> -    QTAILQ_FOREACH(node, &s->used, MLIST_ENTNAME) {
> -        g_assert_cmpint(node->addr, >, addr);
> -        g_assert_cmpint(node->addr, >=, next);
> -        addr = node->addr;
> -        next = node->addr + node->size;
> -    }
> -}
> -
> -static uint64_t pc_mlist_alloc(PCAlloc *s, uint64_t size)
> -{
> -    MemBlock *node;
> -
> -    node = mlist_find_space(&s->free, size);
> -    if (!node) {
> -        fprintf(stderr, "Out of guest memory.\n");
> -        g_assert_not_reached();
> -    }
> -    return pc_mlist_fulfill(s, node, size);
> -}
> -
> -static void pc_mlist_free(PCAlloc *s, uint64_t addr)
> -{
> -    MemBlock *node;
> -
> -    if (addr == 0) {
> -        return;
> -    }
> -
> -    node = mlist_find_key(&s->used, addr);
> -    if (!node) {
> -        fprintf(stderr, "Error: no record found for an allocation at "
> -                "0x%016" PRIx64 ".\n",
> -                addr);
> -        g_assert_not_reached();
> -    }
> -
> -    /* Rip it out of the used list and re-insert back into the free list. */
> -    QTAILQ_REMOVE(&s->used, node, MLIST_ENTNAME);
> -    mlist_sort_insert(&s->free, node);
> -    mlist_coalesce(&s->free, node);
> -}
> -
> -static uint64_t pc_alloc(QGuestAllocator *allocator, size_t size)
> -{
> -    PCAlloc *s = container_of(allocator, PCAlloc, alloc);
> -    uint64_t rsize = size;
> -    uint64_t naddr;
> -
> -    rsize += (PAGE_SIZE - 1);
> -    rsize &= -PAGE_SIZE;
> -    g_assert_cmpint((s->start + rsize), <=, s->end);
> -    g_assert_cmpint(rsize, >=, size);
> -
> -    naddr = pc_mlist_alloc(s, rsize);
> -    if (s->opts & PC_ALLOC_PARANOID) {
> -        pc_mlist_check(s);
> -    }
> -
> -    return naddr;
> -}
> -
> -static void pc_free(QGuestAllocator *allocator, uint64_t addr)
> -{
> -    PCAlloc *s = container_of(allocator, PCAlloc, alloc);
> -
> -    pc_mlist_free(s, addr);
> -    if (s->opts & PC_ALLOC_PARANOID) {
> -        pc_mlist_check(s);
> -    }
> -}
> -
>   /*
>    * Mostly for valgrind happiness, but it does offer
>    * a chokepoint for debugging guest memory leaks, too.
>    */
>   void pc_alloc_uninit(QGuestAllocator *allocator)
>   {
> -    PCAlloc *s = container_of(allocator, PCAlloc, alloc);
> -    MemBlock *node;
> -    MemBlock *tmp;
> -    PCAllocOpts mask;
> -
> -    /* Check for guest leaks, and destroy the list. */
> -    QTAILQ_FOREACH_SAFE(node, &s->used, MLIST_ENTNAME, tmp) {
> -        if (s->opts & (PC_ALLOC_LEAK_WARN | PC_ALLOC_LEAK_ASSERT)) {
> -            fprintf(stderr, "guest malloc leak @ 0x%016" PRIx64 "; "
> -                    "size 0x%016" PRIx64 ".\n",
> -                    node->addr, node->size);
> -        }
> -        if (s->opts & (PC_ALLOC_LEAK_ASSERT)) {
> -            g_assert_not_reached();
> -        }
> -        g_free(node);
> -    }
> -
> -    /* If we have previously asserted that there are no leaks, then there
> -     * should be only one node here with a specific address and size. */
> -    mask = PC_ALLOC_LEAK_ASSERT | PC_ALLOC_PARANOID;
> -    QTAILQ_FOREACH_SAFE(node, &s->free, MLIST_ENTNAME, tmp) {
> -        if ((s->opts & mask) == mask) {
> -            if ((node->addr != s->start) ||
> -                (node->size != s->end - s->start)) {
> -                fprintf(stderr, "Free list is corrupted.\n");
> -                g_assert_not_reached();
> -            }
> -        }
> -
> -        g_free(node);
> -    }
> -
> -    g_free(s);
> +    alloc_uninit(allocator);
>   }
>
> -QGuestAllocator *pc_alloc_init_flags(PCAllocOpts flags)
> +QGuestAllocator *pc_alloc_init_flags(QAllocOpts flags)
>   {
> -    PCAlloc *s = g_malloc0(sizeof(*s));
> +    QGuestAllocator *s = g_malloc0(sizeof(*s));
>       uint64_t ram_size;
>       QFWCFG *fw_cfg = pc_fw_cfg_init();
>       MemBlock *node;
>
>       s->opts = flags;
> -    s->alloc.alloc = pc_alloc;
> -    s->alloc.free = pc_free;
> +    s->page_size = PAGE_SIZE;
>
>       ram_size = qfw_cfg_get_u64(fw_cfg, FW_CFG_RAM_SIZE);
>
> @@ -325,10 +57,10 @@ QGuestAllocator *pc_alloc_init_flags(PCAllocOpts flags)
>       node = mlist_new(s->start, s->end - s->start);
>       QTAILQ_INSERT_HEAD(&s->free, node, MLIST_ENTNAME);
>
> -    return &s->alloc;
> +    return s;
>   }
>
>   inline QGuestAllocator *pc_alloc_init(void)
>   {
> -    return pc_alloc_init_flags(PC_ALLOC_NO_FLAGS);
> +    return pc_alloc_init_flags(ALLOC_NO_FLAGS);
>   }
> diff --git a/tests/libqos/malloc-pc.h b/tests/libqos/malloc-pc.h
> index 9f525e3..86ab9f0 100644
> --- a/tests/libqos/malloc-pc.h
> +++ b/tests/libqos/malloc-pc.h
> @@ -15,15 +15,8 @@
>
>   #include "libqos/malloc.h"
>
> -typedef enum {
> -    PC_ALLOC_NO_FLAGS    = 0x00,
> -    PC_ALLOC_LEAK_WARN   = 0x01,
> -    PC_ALLOC_LEAK_ASSERT = 0x02,
> -    PC_ALLOC_PARANOID    = 0x04
> -} PCAllocOpts;
> -
>   QGuestAllocator *pc_alloc_init(void);
> -QGuestAllocator *pc_alloc_init_flags(PCAllocOpts flags);
> -void             pc_alloc_uninit(QGuestAllocator *allocator);
> +QGuestAllocator *pc_alloc_init_flags(QAllocOpts flags);
> +void pc_alloc_uninit(QGuestAllocator *allocator);
>
>   #endif
> diff --git a/tests/libqos/malloc.c b/tests/libqos/malloc.c
> new file mode 100644
> index 0000000..e145fd9
> --- /dev/null
> +++ b/tests/libqos/malloc.c
> @@ -0,0 +1,268 @@
> +/*
> + * libqos malloc support
> + *
> + * Copyright (c) 2014
> + *
> + * Author:
> + *  John Snow <jsnow@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + */
> +
> +#include "libqos/malloc.h"
> +#include "qemu-common.h"
> +#include <stdio.h>
> +#include <inttypes.h>
> +#include <glib.h>
> +
> +static void mlist_delete(MemList *list, MemBlock *node)
> +{
> +    g_assert(list && node);
> +    QTAILQ_REMOVE(list, node, MLIST_ENTNAME);
> +    g_free(node);
> +}
> +
> +static MemBlock *mlist_find_key(MemList *head, uint64_t addr)
> +{
> +    MemBlock *node;
> +    QTAILQ_FOREACH(node, head, MLIST_ENTNAME) {
> +        if (node->addr == addr) {
> +            return node;
> +        }
> +    }
> +    return NULL;
> +}
> +
> +static MemBlock *mlist_find_space(MemList *head, uint64_t size)
> +{
> +    MemBlock *node;
> +
> +    QTAILQ_FOREACH(node, head, MLIST_ENTNAME) {
> +        if (node->size >= size) {
> +            return node;
> +        }
> +    }
> +    return NULL;
> +}
> +
> +static MemBlock *mlist_sort_insert(MemList *head, MemBlock *insr)
> +{
> +    MemBlock *node;
> +    g_assert(head && insr);
> +
> +    QTAILQ_FOREACH(node, head, MLIST_ENTNAME) {
> +        if (insr->addr < node->addr) {
> +            QTAILQ_INSERT_BEFORE(node, insr, MLIST_ENTNAME);
> +            return insr;
> +        }
> +    }
> +
> +    QTAILQ_INSERT_TAIL(head, insr, MLIST_ENTNAME);
> +    return insr;
> +}
> +
> +static inline uint64_t mlist_boundary(MemBlock *node)
> +{
> +    return node->size + node->addr;
> +}
> +
> +static MemBlock *mlist_join(MemList *head, MemBlock *left, MemBlock *right)
> +{
> +    g_assert(head && left && right);
> +
> +    left->size += right->size;
> +    mlist_delete(head, right);
> +    return left;
> +}
> +
> +static void mlist_coalesce(MemList *head, MemBlock *node)
> +{
> +    g_assert(node);
> +    MemBlock *left;
> +    MemBlock *right;
> +    char merge;
> +
> +    do {
> +        merge = 0;
> +        left = QTAILQ_PREV(node, MemList, MLIST_ENTNAME);
> +        right = QTAILQ_NEXT(node, MLIST_ENTNAME);
> +
> +        /* clowns to the left of me */
> +        if (left && mlist_boundary(left) == node->addr) {
> +            node = mlist_join(head, left, node);
> +            merge = 1;
> +        }
> +
> +        /* jokers to the right */
> +        if (right && mlist_boundary(node) == right->addr) {
> +            node = mlist_join(head, node, right);
> +            merge = 1;
> +        }
> +
> +    } while (merge);
> +}
> +
> +static uint64_t mlist_fulfill(QGuestAllocator *s, MemBlock *freenode,
> +                                                                uint64_t size)
> +{
> +    uint64_t addr;
> +    MemBlock *usednode;
> +
> +    g_assert(freenode);
> +    g_assert_cmpint(freenode->size, >=, size);
> +
> +    addr = freenode->addr;
> +    if (freenode->size == size) {
> +        /* re-use this freenode as our used node */
> +        QTAILQ_REMOVE(&s->free, freenode, MLIST_ENTNAME);
> +        usednode = freenode;
> +    } else {
> +        /* adjust the free node and create a new used node */
> +        freenode->addr += size;
> +        freenode->size -= size;
> +        usednode = mlist_new(addr, size);
> +    }
> +
> +    mlist_sort_insert(&s->used, usednode);
> +    return addr;
> +}
> +
> +/* To assert the correctness of the list.
> + * Used only if ALLOC_PARANOID is set. */
> +static void mlist_check(QGuestAllocator *s)
> +{
> +    MemBlock *node;
> +    uint64_t addr = s->start > 0 ? s->start - 1 : 0;
> +    uint64_t next = s->start;
> +
> +    QTAILQ_FOREACH(node, &s->free, MLIST_ENTNAME) {
> +        g_assert_cmpint(node->addr, >, addr);
> +        g_assert_cmpint(node->addr, >=, next);
> +        addr = node->addr;
> +        next = node->addr + node->size;
> +    }
> +
> +    addr = s->start > 0 ? s->start - 1 : 0;
> +    next = s->start;
> +    QTAILQ_FOREACH(node, &s->used, MLIST_ENTNAME) {
> +        g_assert_cmpint(node->addr, >, addr);
> +        g_assert_cmpint(node->addr, >=, next);
> +        addr = node->addr;
> +        next = node->addr + node->size;
> +    }
> +}
> +
> +static uint64_t mlist_alloc(QGuestAllocator *s, uint64_t size)
> +{
> +    MemBlock *node;
> +
> +    node = mlist_find_space(&s->free, size);
> +    if (!node) {
> +        fprintf(stderr, "Out of guest memory.\n");
> +        g_assert_not_reached();
> +    }
> +    return mlist_fulfill(s, node, size);
> +}
> +
> +static void mlist_free(QGuestAllocator *s, uint64_t addr)
> +{
> +    MemBlock *node;
> +
> +    if (addr == 0) {
> +        return;
> +    }
> +
> +    node = mlist_find_key(&s->used, addr);
> +    if (!node) {
> +        fprintf(stderr, "Error: no record found for an allocation at "
> +                "0x%016" PRIx64 ".\n",
> +                addr);
> +        g_assert_not_reached();
> +    }
> +
> +    /* Rip it out of the used list and re-insert back into the free list. */
> +    QTAILQ_REMOVE(&s->used, node, MLIST_ENTNAME);
> +    mlist_sort_insert(&s->free, node);
> +    mlist_coalesce(&s->free, node);
> +}
> +
> +MemBlock *mlist_new(uint64_t addr, uint64_t size)
> +{
> +    MemBlock *block;
> +
> +    if (!size) {
> +        return NULL;
> +    }
> +    block = g_malloc0(sizeof(MemBlock));
> +
> +    block->addr = addr;
> +    block->size = size;
> +
> +    return block;
> +}
> +
> +/*
> + * Mostly for valgrind happiness, but it does offer
> + * a chokepoint for debugging guest memory leaks, too.
> + */
> +void alloc_uninit(QGuestAllocator *allocator)
> +{
> +    MemBlock *node;
> +    MemBlock *tmp;
> +    QAllocOpts mask;
> +
> +    /* Check for guest leaks, and destroy the list. */
> +    QTAILQ_FOREACH_SAFE(node, &allocator->used, MLIST_ENTNAME, tmp) {
> +        if (allocator->opts & (ALLOC_LEAK_WARN | ALLOC_LEAK_ASSERT)) {
> +            fprintf(stderr, "guest malloc leak @ 0x%016" PRIx64 "; "
> +                    "size 0x%016" PRIx64 ".\n",
> +                    node->addr, node->size);
> +        }
> +        if (allocator->opts & (ALLOC_LEAK_ASSERT)) {
> +            g_assert_not_reached();
> +        }
> +        g_free(node);
> +    }
> +
> +    /* If we have previously asserted that there are no leaks, then there
> +     * should be only one node here with a specific address and size. */
> +    mask = ALLOC_LEAK_ASSERT | ALLOC_PARANOID;
> +    QTAILQ_FOREACH_SAFE(node, &allocator->free, MLIST_ENTNAME, tmp) {
> +        if ((allocator->opts & mask) == mask) {
> +            if ((node->addr != allocator->start) ||
> +                (node->size != allocator->end - allocator->start)) {
> +                fprintf(stderr, "Free list is corrupted.\n");
> +                g_assert_not_reached();
> +            }
> +        }
> +
> +        g_free(node);
> +    }
> +}

The original malloc-pc implementation for alloc_uninit() also deletes 
the QGuestAllocator here, but this version doesn't, which creates a 
small leak. Did you have a different cleanup pathway in mind?

> +uint64_t guest_alloc(QGuestAllocator *allocator, size_t size)
> +{
> +    uint64_t rsize = size;
> +    uint64_t naddr;
> +
> +    rsize += (allocator->page_size - 1);
> +    rsize &= -allocator->page_size;
> +    g_assert_cmpint((allocator->start + rsize), <=, allocator->end);
> +    g_assert_cmpint(rsize, >=, size);
> +
> +    naddr = mlist_alloc(allocator, rsize);
> +    if (allocator->opts & ALLOC_PARANOID) {
> +        mlist_check(allocator);
> +    }
> +
> +    return naddr;
> +}
> +
> +void guest_free(QGuestAllocator *allocator, uint64_t addr)
> +{
> +    mlist_free(allocator, addr);
> +    if (allocator->opts & ALLOC_PARANOID) {
> +        mlist_check(allocator);
> +    }
> +}
> diff --git a/tests/libqos/malloc.h b/tests/libqos/malloc.h
> index 5565381..465efeb 100644
> --- a/tests/libqos/malloc.h
> +++ b/tests/libqos/malloc.h
> @@ -15,24 +15,39 @@
>
>   #include <stdint.h>
>   #include <sys/types.h>
> +#include "qemu/queue.h"
>
> -typedef struct QGuestAllocator QGuestAllocator;
> +#define MLIST_ENTNAME entries
>
> -struct QGuestAllocator
> -{
> -    uint64_t (*alloc)(QGuestAllocator *allocator, size_t size);
> -    void (*free)(QGuestAllocator *allocator, uint64_t addr);
> -};
> +typedef enum {
> +    ALLOC_NO_FLAGS    = 0x00,
> +    ALLOC_LEAK_WARN   = 0x01,
> +    ALLOC_LEAK_ASSERT = 0x02,
> +    ALLOC_PARANOID    = 0x04
> +} QAllocOpts;
> +
> +typedef QTAILQ_HEAD(MemList, MemBlock) MemList;
> +typedef struct MemBlock {
> +    QTAILQ_ENTRY(MemBlock) MLIST_ENTNAME;
> +    uint64_t size;
> +    uint64_t addr;
> +} MemBlock;
> +
> +typedef struct QGuestAllocator {
> +    QAllocOpts opts;
> +    uint64_t start;
> +    uint64_t end;
> +    uint32_t page_size;
> +
> +    MemList used;
> +    MemList free;
> +} QGuestAllocator;
> +
> +MemBlock *mlist_new(uint64_t addr, uint64_t size);
> +void alloc_uninit(QGuestAllocator *allocator);
>
>   /* Always returns page aligned values */
> -static inline uint64_t guest_alloc(QGuestAllocator *allocator, size_t size)
> -{
> -    return allocator->alloc(allocator, size);
> -}
> -
> -static inline void guest_free(QGuestAllocator *allocator, uint64_t addr)
> -{
> -    allocator->free(allocator, addr);
> -}
> +uint64_t guest_alloc(QGuestAllocator *allocator, size_t size);
> +void guest_free(QGuestAllocator *allocator, uint64_t addr);
>
>   #endif
>

-- 
—js

  parent reply	other threads:[~2014-10-22 16:34 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-10-18  9:24 [Qemu-devel] [PATCH] libqos: Convert malloc-pc allocator to a generic allocator Marc Marí
2014-10-22 16:01 ` Stefan Hajnoczi
2014-10-22 16:33 ` John Snow [this message]
2014-10-22 21:09   ` Marc Marí
2014-10-23 22:49 ` John Snow
2014-10-24  9:00   ` Marc Marí
2014-10-24 15:02     ` John Snow

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5447DC61.50005@redhat.com \
    --to=jsnow@redhat.com \
    --cc=marc.mari.barcelo@gmail.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).