YaGL: Replace AVL trees with hashes 04/12904/1
authorStanislav Vorobiov <s.vorobiov@samsung.com>
Mon, 25 Nov 2013 14:53:49 +0000 (18:53 +0400)
committerStanislav Vorobiov <s.vorobiov@samsung.com>
Mon, 25 Nov 2013 14:53:49 +0000 (18:53 +0400)
The number of OpenGL objects and/or shader
program locations can be really large in
case of heavy graphics applications, so object
lookup time matters. Using hash tables is more
appropriate since they have much less lookup
time. The difference can be seen when running
Doom3, AVL lookup function was hot in perf report

Change-Id: I46121ecd8d8c0d392fe6f3aa4aba0c96a90280ae

hw/yagl/Makefile.objs
hw/yagl/yagl_apis/gles/yagl_gles_api_ps.c
hw/yagl/yagl_apis/gles/yagl_gles_api_ps.h
hw/yagl/yagl_avl.c [deleted file]
hw/yagl/yagl_avl.h [deleted file]
hw/yagl/yagl_object_map.c
hw/yagl/yagl_object_map.h

index 39434fc..2453ae9 100644 (file)
@@ -12,7 +12,6 @@ obj-y += yagl_handle_gen.o
 obj-y += yagl_dyn_lib.o
 obj-y += yagl_api.o
 obj-y += yagl_vector.o
-obj-y += yagl_avl.o
 obj-y += yagl_transport.o
 obj-y += yagl_egl_backend.o
 obj-y += yagl_eglb_display.o
index 7af3622..2f2245f 100644 (file)
 #include "yagl_gles_api_ps.h"
 #include "yagl_process.h"
 #include "yagl_thread.h"
-#include "yagl_avl.h"
-
-struct yagl_location
-{
-    uint32_t location;
-
-    GLint actual_location;
-};
-
-static int yagl_location_compare(const void *avl_a,
-                                 const void *avl_b,
-                                 void *avl_param)
-{
-    const struct yagl_location *a = avl_a;
-    const struct yagl_location *b = avl_b;
-
-    if (a->location < b->location) {
-        return -1;
-    } else if (a->location > b->location) {
-        return 1;
-    } else {
-        return 0;
-    }
-}
-
-static void yagl_location_destroy(void *avl_item, void *avl_param)
-{
-    g_free(avl_item);
-}
 
 void yagl_gles_api_ps_init(struct yagl_gles_api_ps *gles_api_ps,
                            struct yagl_gles_driver *driver)
 {
     gles_api_ps->driver = driver;
-    gles_api_ps->locations = yagl_avl_create(&yagl_location_compare,
-                                             NULL,
-                                             NULL);
+    gles_api_ps->locations = g_hash_table_new_full(g_direct_hash,
+                                                   g_direct_equal,
+                                                   NULL,
+                                                   NULL);
+
     assert(gles_api_ps->locations);
 }
 
 void yagl_gles_api_ps_cleanup(struct yagl_gles_api_ps *gles_api_ps)
 {
-    yagl_avl_destroy(gles_api_ps->locations, &yagl_location_destroy);
+    g_hash_table_destroy(gles_api_ps->locations);
 }
 
 void yagl_gles_api_ps_add_location(struct yagl_gles_api_ps *gles_api_ps,
                                    uint32_t location,
                                    GLint actual_location)
 {
-    struct yagl_location *item = g_malloc0(sizeof(struct yagl_location));
+    guint size = g_hash_table_size(gles_api_ps->locations);
 
-    item->location = location;
-    item->actual_location = actual_location;
+    g_hash_table_insert(gles_api_ps->locations,
+                        GUINT_TO_POINTER(location),
+                        GINT_TO_POINTER(actual_location));
 
-    yagl_avl_assert_insert(gles_api_ps->locations, item);
+    assert(g_hash_table_size(gles_api_ps->locations) > size);
 }
 
 GLint yagl_gles_api_ps_translate_location(struct yagl_gles_api_ps *gles_api_ps,
                                           GLboolean tl,
                                           uint32_t location)
 {
-    struct yagl_location *item;
-    struct yagl_location dummy;
+    gpointer key, item;
 
     if (!tl) {
         return location;
     }
 
-    dummy.location = location;
-
-    item = yagl_avl_find(gles_api_ps->locations, &dummy);
-
-    if (item) {
-        return item->actual_location;
+    if (g_hash_table_lookup_extended(gles_api_ps->locations,
+                                     GUINT_TO_POINTER(location),
+                                     &key,
+                                     &item))
+    {
+        return GPOINTER_TO_INT(item);
     } else {
         assert(0);
         return -1;
@@ -114,12 +87,9 @@ GLint yagl_gles_api_ps_translate_location(struct yagl_gles_api_ps *gles_api_ps,
 void yagl_gles_api_ps_remove_location(struct yagl_gles_api_ps *gles_api_ps,
                                       uint32_t location)
 {
-    void *item;
-    struct yagl_location dummy;
-
-    dummy.location = location;
+    guint size = g_hash_table_size(gles_api_ps->locations);
 
-    item = yagl_avl_assert_delete(gles_api_ps->locations, &dummy);
+    g_hash_table_remove(gles_api_ps->locations, GUINT_TO_POINTER(location));
 
-    yagl_location_destroy(item, gles_api_ps->locations->avl_param);
+    assert(g_hash_table_size(gles_api_ps->locations) < size);
 }
index 50ac2bb..f5716b3 100644 (file)
@@ -31,9 +31,9 @@
 #define _QEMU_YAGL_GLES_API_PS_H
 
 #include "yagl_api.h"
+#include <glib.h>
 
 struct yagl_gles_driver;
-struct yagl_avl_table;
 
 struct yagl_gles_api_ps
 {
@@ -41,7 +41,7 @@ struct yagl_gles_api_ps
 
     struct yagl_gles_driver *driver;
 
-    struct yagl_avl_table *locations;
+    GHashTable *locations;
 };
 
 void yagl_gles_api_ps_init(struct yagl_gles_api_ps *gles_api_ps,
diff --git a/hw/yagl/yagl_avl.c b/hw/yagl/yagl_avl.c
deleted file mode 100644 (file)
index 0c19a3a..0000000
+++ /dev/null
@@ -1,873 +0,0 @@
-/*
- * yagl
- *
- * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact:
- * Stanislav Vorobiov <s.vorobiov@samsung.com>
- * Jinhyung Jo <jinhyung.jo@samsung.com>
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *
- * Contributors:
- * - S-Core Co., Ltd
- *
- */
-
-/*
- * AVL tree implementation from libavl project.
- */
-
-#include "yagl_avl.h"
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/*
- * Creates and returns a new table
- * with comparison function |compare| using parameter |param|
- * and memory allocator |allocator|.
- * Returns |NULL| if memory allocation failed.
- */
-struct yagl_avl_table *yagl_avl_create(yagl_avl_comparison_func *compare,
-    void *param,
-    struct yagl_libavl_allocator *allocator)
-{
-    struct yagl_avl_table *tree;
-
-    assert(compare != NULL);
-
-    if (allocator == NULL) {
-        allocator = &yagl_avl_allocator_default;
-    }
-
-    tree = allocator->libavl_malloc(allocator, sizeof(*tree));
-    if (tree == NULL) {
-        return NULL;
-    }
-
-    tree->avl_root = NULL;
-    tree->avl_compare = compare;
-    tree->avl_param = param;
-    tree->avl_alloc = allocator;
-    tree->avl_count = 0;
-    tree->avl_generation = 0;
-
-    return tree;
-}
-
-/*
- * Search |tree| for an item matching |item|, and return it if found.
- * Otherwise return |NULL|.
- */
-void *yagl_avl_find(const struct yagl_avl_table *tree, const void *item)
-{
-    const struct yagl_avl_node *p;
-
-    assert(tree != NULL && item != NULL);
-    for (p = tree->avl_root; p != NULL;) {
-        int cmp = tree->avl_compare(item, p->avl_data, tree->avl_param);
-
-        if (cmp < 0) {
-            p = p->avl_link[0];
-        } else if (cmp > 0) {
-            p = p->avl_link[1];
-        } else {
-            return p->avl_data;
-        }
-    }
-
-    return NULL;
-}
-
-/*
- * Inserts |item| into |tree| and returns a pointer to |item|'s address.
- * If a duplicate item is found in the tree,
- * returns a pointer to the duplicate without inserting |item|.
- * Returns |NULL| in case of memory allocation failure.
- */
-void **yagl_avl_probe(struct yagl_avl_table *tree, void *item)
-{
-    struct yagl_avl_node *y, *z; /* Top node to update balance factor, and parent. */
-    struct yagl_avl_node *p, *q; /* Iterator, and parent. */
-    struct yagl_avl_node *n; /* Newly inserted node. */
-    struct yagl_avl_node *w; /* New root of rebalanced subtree. */
-    int dir; /* Direction to descend. */
-
-    unsigned char da[YAGL_AVL_MAX_HEIGHT]; /* Cached comparison results. */
-    int k = 0; /* Number of cached results. */
-
-    assert(tree != NULL && item != NULL);
-
-    z = (struct yagl_avl_node *) &tree->avl_root;
-    y = tree->avl_root;
-    dir = 0;
-    for (q = z, p = y; p != NULL; q = p, p = p->avl_link[dir]) {
-        int cmp = tree->avl_compare(item, p->avl_data, tree->avl_param);
-        if (cmp == 0) {
-            return &p->avl_data;
-        }
-
-        if (p->avl_balance != 0) {
-            z = q, y = p, k = 0;
-        }
-        da[k++] = dir = cmp > 0;
-    }
-
-    n = q->avl_link[dir] = tree->avl_alloc->libavl_malloc(tree->avl_alloc,
-        sizeof(*n));
-    if (n == NULL) {
-        return NULL;
-    }
-
-    tree->avl_count++;
-    n->avl_data = item;
-    n->avl_link[0] = n->avl_link[1] = NULL;
-    n->avl_balance = 0;
-    if (y == NULL) {
-        return &n->avl_data;
-    }
-
-    for (p = y, k = 0; p != n; p = p->avl_link[da[k]], k++) {
-        if (da[k] == 0) {
-            p->avl_balance--;
-        } else {
-            p->avl_balance++;
-        }
-    }
-
-    if (y->avl_balance == -2) {
-        struct yagl_avl_node *x = y->avl_link[0];
-        if (x->avl_balance == -1) {
-            w = x;
-            y->avl_link[0] = x->avl_link[1];
-            x->avl_link[1] = y;
-            x->avl_balance = y->avl_balance = 0;
-        } else {
-            assert(x->avl_balance == 1);
-            w = x->avl_link[1];
-            x->avl_link[1] = w->avl_link[0];
-            w->avl_link[0] = x;
-            y->avl_link[0] = w->avl_link[1];
-            w->avl_link[1] = y;
-            if (w->avl_balance == -1) {
-                x->avl_balance = 0, y->avl_balance = 1;
-            } else if (w->avl_balance == 0) {
-                x->avl_balance = y->avl_balance = 0;
-            } else {
-                x->avl_balance = -1, y->avl_balance = 0;
-            }
-            w->avl_balance = 0;
-        }
-    } else if (y->avl_balance == 2) {
-        struct yagl_avl_node *x = y->avl_link[1];
-        if (x->avl_balance == 1) {
-            w = x;
-            y->avl_link[1] = x->avl_link[0];
-            x->avl_link[0] = y;
-            x->avl_balance = y->avl_balance = 0;
-        } else {
-            assert(x->avl_balance == -1);
-            w = x->avl_link[0];
-            x->avl_link[0] = w->avl_link[1];
-            w->avl_link[1] = x;
-            y->avl_link[1] = w->avl_link[0];
-            w->avl_link[0] = y;
-            if (w->avl_balance == 1) {
-                x->avl_balance = 0, y->avl_balance = -1;
-            } else if (w->avl_balance == 0) {
-                x->avl_balance = y->avl_balance = 0;
-            } else {
-                x->avl_balance = 1, y->avl_balance = 0;
-            }
-            w->avl_balance = 0;
-        }
-    } else {
-        return &n->avl_data;
-    }
-    z->avl_link[y != z->avl_link[0]] = w;
-
-    tree->avl_generation++;
-    return &n->avl_data;
-}
-
-/*
- * Inserts |item| into |table|.
- * Returns |NULL| if |item| was successfully inserted
- * or if a memory allocation error occurred.
- * Otherwise, returns the duplicate item.
- */
-void *yagl_avl_insert(struct yagl_avl_table *table, void *item)
-{
-    void **p = yagl_avl_probe(table, item);
-    return p == NULL || *p == item ? NULL : *p;
-}
-
-/*
- * Inserts |item| into |table|, replacing any duplicate item.
- * Returns |NULL| if |item| was inserted without replacing a duplicate,
- * or if a memory allocation error occurred.
- * Otherwise, returns the item that was replaced.
- */
-void *yagl_avl_replace(struct yagl_avl_table *table, void *item)
-{
-    void **p = yagl_avl_probe(table, item);
-    if (p == NULL || *p == item) {
-        return NULL;
-    } else {
-        void *r = *p;
-        *p = item;
-        return r;
-    }
-}
-
-/*
- * Deletes from |tree| and returns an item matching |item|.
- * Returns a null pointer if no matching item found.
- */
-void *yagl_avl_delete(struct yagl_avl_table *tree, const void *item)
-{
-    /* Stack of nodes. */
-    struct yagl_avl_node *pa[YAGL_AVL_MAX_HEIGHT]; /* Nodes. */
-    unsigned char da[YAGL_AVL_MAX_HEIGHT]; /* |avl_link[]| indexes. */
-    int k; /* Stack pointer. */
-
-    struct yagl_avl_node *p; /* Traverses tree to find node to delete. */
-    int cmp; /* Result of comparison between |item| and |p|. */
-
-    assert(tree != NULL && item != NULL);
-
-    k = 0;
-    p = (struct yagl_avl_node *) &tree->avl_root;
-    for (cmp = -1; cmp != 0;
-        cmp = tree->avl_compare(item, p->avl_data, tree->avl_param)) {
-        int dir = cmp > 0;
-
-        pa[k] = p;
-        da[k++] = dir;
-
-        p = p->avl_link[dir];
-        if (p == NULL) {
-            return NULL;
-        }
-    }
-    item = p->avl_data;
-
-    if (p->avl_link[1] == NULL) {
-        pa[k - 1]->avl_link[da[k - 1]] = p->avl_link[0];
-    } else {
-        struct yagl_avl_node *r = p->avl_link[1];
-        if (r->avl_link[0] == NULL) {
-            r->avl_link[0] = p->avl_link[0];
-            r->avl_balance = p->avl_balance;
-            pa[k - 1]->avl_link[da[k - 1]] = r;
-            da[k] = 1;
-            pa[k++] = r;
-        } else {
-            struct yagl_avl_node *s;
-            int j = k++;
-
-            for (;;) {
-                da[k] = 0;
-                pa[k++] = r;
-                s = r->avl_link[0];
-                if (s->avl_link[0] == NULL) {
-                    break;
-                }
-
-                r = s;
-            }
-
-            s->avl_link[0] = p->avl_link[0];
-            r->avl_link[0] = s->avl_link[1];
-            s->avl_link[1] = p->avl_link[1];
-            s->avl_balance = p->avl_balance;
-
-            pa[j - 1]->avl_link[da[j - 1]] = s;
-            da[j] = 1;
-            pa[j] = s;
-        }
-    }
-
-    tree->avl_alloc->libavl_free(tree->avl_alloc, p);
-
-    assert(k > 0);
-    while (--k > 0) {
-        struct yagl_avl_node *y = pa[k];
-
-        if (da[k] == 0) {
-            y->avl_balance++;
-            if (y->avl_balance == 1) {
-                break;
-            } else if (y->avl_balance == 2) {
-                struct yagl_avl_node *x = y->avl_link[1];
-                if (x->avl_balance == -1) {
-                    struct yagl_avl_node *w;
-                    assert(x->avl_balance == -1);
-                    w = x->avl_link[0];
-                    x->avl_link[0] = w->avl_link[1];
-                    w->avl_link[1] = x;
-                    y->avl_link[1] = w->avl_link[0];
-                    w->avl_link[0] = y;
-                    if (w->avl_balance == 1) {
-                        x->avl_balance = 0, y->avl_balance = -1;
-                    } else if (w->avl_balance == 0) {
-                        x->avl_balance = y->avl_balance = 0;
-                    } else {
-                        x->avl_balance = 1, y->avl_balance = 0;
-                    }
-                    w->avl_balance = 0;
-                    pa[k - 1]->avl_link[da[k - 1]] = w;
-                } else {
-                    y->avl_link[1] = x->avl_link[0];
-                    x->avl_link[0] = y;
-                    pa[k - 1]->avl_link[da[k - 1]] = x;
-                    if (x->avl_balance == 0) {
-                        x->avl_balance = -1;
-                        y->avl_balance = 1;
-                        break;
-                    } else {
-                        x->avl_balance = y->avl_balance = 0;
-                    }
-                }
-            }
-        } else {
-            y->avl_balance--;
-            if (y->avl_balance == -1) {
-                break;
-            } else if (y->avl_balance == -2) {
-                struct yagl_avl_node *x = y->avl_link[0];
-                if (x->avl_balance == 1) {
-                    struct yagl_avl_node *w;
-                    assert(x->avl_balance == 1);
-                    w = x->avl_link[1];
-                    x->avl_link[1] = w->avl_link[0];
-                    w->avl_link[0] = x;
-                    y->avl_link[0] = w->avl_link[1];
-                    w->avl_link[1] = y;
-                    if (w->avl_balance == -1) {
-                        x->avl_balance = 0, y->avl_balance = 1;
-                    } else if (w->avl_balance == 0) {
-                        x->avl_balance = y->avl_balance = 0;
-                    } else {
-                        x->avl_balance = -1, y->avl_balance = 0;
-                    }
-                    w->avl_balance = 0;
-                    pa[k - 1]->avl_link[da[k - 1]] = w;
-                } else {
-                    y->avl_link[0] = x->avl_link[1];
-                    x->avl_link[1] = y;
-                    pa[k - 1]->avl_link[da[k - 1]] = x;
-                    if (x->avl_balance == 0) {
-                        x->avl_balance = 1;
-                        y->avl_balance = -1;
-                        break;
-                    } else {
-                        x->avl_balance = y->avl_balance = 0;
-                    }
-                }
-            }
-        }
-    }
-
-    tree->avl_count--;
-    tree->avl_generation++;
-    return (void *) item;
-}
-
-/*
- * Refreshes the stack of parent pointers in |trav|
- * and updates its generation number.
- */
-static void yagl_trav_refresh(struct yagl_avl_traverser *trav)
-{
-    assert(trav != NULL);
-
-    trav->avl_generation = trav->avl_table->avl_generation;
-
-    if (trav->avl_node != NULL) {
-        yagl_avl_comparison_func *cmp = trav->avl_table->avl_compare;
-        void *param = trav->avl_table->avl_param;
-        struct yagl_avl_node *node = trav->avl_node;
-        struct yagl_avl_node *i;
-
-        trav->avl_height = 0;
-        for (i = trav->avl_table->avl_root; i != node;) {
-            assert(trav->avl_height < YAGL_AVL_MAX_HEIGHT);
-            assert(i != NULL);
-
-            trav->avl_stack[trav->avl_height++] = i;
-            i = i->avl_link[cmp(node->avl_data, i->avl_data, param) > 0];
-        }
-    }
-}
-
-/*
- * Initializes |trav| for use with |tree|
- * and selects the null node.
- */
-void yagl_avl_t_init(struct yagl_avl_traverser *trav,
-                     struct yagl_avl_table *tree)
-{
-    trav->avl_table = tree;
-    trav->avl_node = NULL;
-    trav->avl_height = 0;
-    trav->avl_generation = tree->avl_generation;
-}
-
-/*
- * Initializes |trav| for |tree|
- * and selects and returns a pointer to its least-valued item.
- * Returns |NULL| if |tree| contains no nodes.
- */
-void *yagl_avl_t_first(struct yagl_avl_traverser *trav,
-                       struct yagl_avl_table *tree)
-{
-    struct yagl_avl_node *x;
-
-    assert(tree != NULL && trav != NULL);
-
-    trav->avl_table = tree;
-    trav->avl_height = 0;
-    trav->avl_generation = tree->avl_generation;
-
-    x = tree->avl_root;
-    if (x != NULL) {
-        while (x->avl_link[0] != NULL) {
-            assert(trav->avl_height < YAGL_AVL_MAX_HEIGHT);
-            trav->avl_stack[trav->avl_height++] = x;
-            x = x->avl_link[0];
-        }
-    }
-    trav->avl_node = x;
-
-    return x != NULL ? x->avl_data : NULL;
-}
-
-/*
- * Initializes |trav| for |tree|
- * and selects and returns a pointer to its greatest-valued item.
- * Returns |NULL| if |tree| contains no nodes.
- */
-void *yagl_avl_t_last(struct yagl_avl_traverser *trav,
-                      struct yagl_avl_table *tree)
-{
-    struct yagl_avl_node *x;
-
-    assert(tree != NULL && trav != NULL);
-
-    trav->avl_table = tree;
-    trav->avl_height = 0;
-    trav->avl_generation = tree->avl_generation;
-
-    x = tree->avl_root;
-    if (x != NULL) {
-        while (x->avl_link[1] != NULL) {
-            assert(trav->avl_height < YAGL_AVL_MAX_HEIGHT);
-            trav->avl_stack[trav->avl_height++] = x;
-            x = x->avl_link[1];
-        }
-    }
-    trav->avl_node = x;
-
-    return x != NULL ? x->avl_data : NULL;
-}
-
-/*
- * Searches for |item| in |tree|.
- * If found, initializes |trav| to the item found and returns the item
- * as well.
- * If there is no matching item, initializes |trav| to the null item
- * and returns |NULL|.
- */
-void *yagl_avl_t_find(struct yagl_avl_traverser *trav,
-                      struct yagl_avl_table *tree, void *item)
-{
-    struct yagl_avl_node *p, *q;
-
-    assert(trav != NULL && tree != NULL && item != NULL);
-    trav->avl_table = tree;
-    trav->avl_height = 0;
-    trav->avl_generation = tree->avl_generation;
-    for (p = tree->avl_root; p != NULL; p = q) {
-        int cmp = tree->avl_compare(item, p->avl_data, tree->avl_param);
-
-        if (cmp < 0) {
-            q = p->avl_link[0];
-        } else if (cmp > 0) {
-            q = p->avl_link[1];
-        } else {
-            trav->avl_node = p;
-            return p->avl_data;
-        }
-
-        assert(trav->avl_height < YAGL_AVL_MAX_HEIGHT);
-        trav->avl_stack[trav->avl_height++] = p;
-    }
-
-    trav->avl_height = 0;
-    trav->avl_node = NULL;
-    return NULL;
-}
-
-/*
- * Attempts to insert |item| into |tree|.
- * If |item| is inserted successfully, it is returned and |trav| is
- * initialized to its location.
- * If a duplicate is found, it is returned and |trav| is initialized to
- * its location.  No replacement of the item occurs.
- * If a memory allocation failure occurs, |NULL| is returned and |trav|
- * is initialized to the null item.
- */
-void
-*yagl_avl_t_insert(struct yagl_avl_traverser *trav,
-                   struct yagl_avl_table *tree, void *item)
-{
-    void **p;
-
-    assert(trav != NULL && tree != NULL && item != NULL);
-
-    p = yagl_avl_probe(tree, item);
-    if (p != NULL) {
-        trav->avl_table = tree;
-        trav->avl_node = ((struct yagl_avl_node *) ((char *) p
-            - offsetof(struct yagl_avl_node, avl_data)));
-        trav->avl_generation = tree->avl_generation - 1;
-        return *p;
-    } else {
-        yagl_avl_t_init(trav, tree);
-        return NULL;
-    }
-}
-
-/* Initializes |trav| to have the same current node as |src|. */
-void *yagl_avl_t_copy(struct yagl_avl_traverser *trav,
-                      const struct yagl_avl_traverser *src)
-{
-    assert(trav != NULL && src != NULL);
-
-    if (trav != src) {
-        trav->avl_table = src->avl_table;
-        trav->avl_node = src->avl_node;
-        trav->avl_generation = src->avl_generation;
-        if (trav->avl_generation == trav->avl_table->avl_generation) {
-            trav->avl_height = src->avl_height;
-            memcpy(trav->avl_stack, (const void *) src->avl_stack,
-                sizeof(*trav->avl_stack) * trav->avl_height);
-        }
-    }
-
-    return trav->avl_node != NULL ? trav->avl_node->avl_data : NULL;
-}
-
-/*
- * Returns the next data item in inorder
- * within the tree being traversed with |trav|,
- * or if there are no more data items returns |NULL|.
- */
-void *yagl_avl_t_next(struct yagl_avl_traverser *trav)
-{
-    struct yagl_avl_node *x;
-
-    assert(trav != NULL);
-
-    if (trav->avl_generation != trav->avl_table->avl_generation) {
-        yagl_trav_refresh(trav);
-    }
-
-    x = trav->avl_node;
-    if (x == NULL) {
-        return yagl_avl_t_first(trav, trav->avl_table);
-    } else if (x->avl_link[1] != NULL) {
-        assert(trav->avl_height < YAGL_AVL_MAX_HEIGHT);
-        trav->avl_stack[trav->avl_height++] = x;
-        x = x->avl_link[1];
-
-        while (x->avl_link[0] != NULL) {
-            assert(trav->avl_height < YAGL_AVL_MAX_HEIGHT);
-            trav->avl_stack[trav->avl_height++] = x;
-            x = x->avl_link[0];
-        }
-    } else {
-        struct yagl_avl_node *y;
-
-        do {
-            if (trav->avl_height == 0) {
-                trav->avl_node = NULL;
-                return NULL;
-            }
-
-            y = x;
-            x = trav->avl_stack[--trav->avl_height];
-        } while (y == x->avl_link[1]);
-    }
-    trav->avl_node = x;
-
-    return x->avl_data;
-}
-
-/*
- * Returns the previous data item in inorder
- * within the tree being traversed with |trav|,
- * or if there are no more data items returns |NULL|.
- */
-void *yagl_avl_t_prev(struct yagl_avl_traverser *trav)
-{
-    struct yagl_avl_node *x;
-
-    assert(trav != NULL);
-
-    if (trav->avl_generation != trav->avl_table->avl_generation) {
-        yagl_trav_refresh(trav);
-    }
-
-    x = trav->avl_node;
-    if (x == NULL) {
-        return yagl_avl_t_last(trav, trav->avl_table);
-    } else if (x->avl_link[0] != NULL) {
-        assert(trav->avl_height < YAGL_AVL_MAX_HEIGHT);
-        trav->avl_stack[trav->avl_height++] = x;
-        x = x->avl_link[0];
-
-        while (x->avl_link[1] != NULL) {
-            assert(trav->avl_height < YAGL_AVL_MAX_HEIGHT);
-            trav->avl_stack[trav->avl_height++] = x;
-            x = x->avl_link[1];
-        }
-    } else {
-        struct yagl_avl_node *y;
-
-        do {
-            if (trav->avl_height == 0) {
-                trav->avl_node = NULL;
-                return NULL;
-            }
-
-            y = x;
-            x = trav->avl_stack[--trav->avl_height];
-        } while (y == x->avl_link[0]);
-    }
-    trav->avl_node = x;
-
-    return x->avl_data;
-}
-
-/* Returns |trav|'s current item. */
-void *yagl_avl_t_cur(struct yagl_avl_traverser *trav)
-{
-    assert(trav != NULL);
-
-    return trav->avl_node != NULL ? trav->avl_node->avl_data : NULL;
-}
-
-/*
- * Replaces the current item in |trav| by |new| and returns the item replaced.
- * |trav| must not have the null item selected.
- * The new item must not upset the ordering of the tree.
- */
-void *yagl_avl_t_replace(struct yagl_avl_traverser *trav, void *new)
-{
-    void *old;
-
-    assert(trav != NULL && trav->avl_node != NULL && new != NULL);
-    old = trav->avl_node->avl_data;
-    trav->avl_node->avl_data = new;
-    return old;
-}
-
-/*
- * Destroys |new| with |avl_destroy (new, destroy)|,
- * first setting right links of nodes in |stack| within |new|
- * to null pointers to avoid touching uninitialized data.
- */
-static void yagl_copy_error_recovery(struct yagl_avl_node **stack, int height,
-    struct yagl_avl_table *new, yagl_avl_item_func *destroy)
-{
-    assert(stack != NULL && height >= 0 && new != NULL);
-
-    for (; height > 2; height -= 2) {
-        stack[height - 1]->avl_link[1] = NULL;
-    }
-    yagl_avl_destroy(new, destroy);
-}
-
-/*
- * Copies |org| to a newly created tree, which is returned.
- * If |copy != NULL|, each data item in |org| is first passed to |copy|,
- * and the return values are inserted into the tree,
- * with |NULL| return values taken as indications of failure.
- * On failure, destroys the partially created new tree,
- * applying |destroy|, if non-null, to each item in the new tree so far,
- * and returns |NULL|.
- * If |allocator != NULL|, it is used for allocation in the new tree.
- * Otherwise, the same allocator used for |org| is used.
- */
-struct yagl_avl_table *yagl_avl_copy(const struct yagl_avl_table *org,
-    yagl_avl_copy_func *copy,
-    yagl_avl_item_func *destroy,
-    struct yagl_libavl_allocator *allocator)
-{
-    struct yagl_avl_node *stack[2 * (YAGL_AVL_MAX_HEIGHT + 1)];
-    int height = 0;
-
-    struct yagl_avl_table *new;
-    const struct yagl_avl_node *x;
-    struct yagl_avl_node *y;
-
-    assert(org != NULL);
-    new = yagl_avl_create(org->avl_compare, org->avl_param,
-        allocator != NULL ? allocator : org->avl_alloc);
-    if (new == NULL) {
-        return NULL;
-    }
-    new->avl_count = org->avl_count;
-    if (new->avl_count == 0) {
-        return new;
-    }
-
-    x = (const struct yagl_avl_node *) &org->avl_root;
-    y = (struct yagl_avl_node *) &new->avl_root;
-    for (;;) {
-        while (x->avl_link[0] != NULL) {
-            assert(height < 2 * (YAGL_AVL_MAX_HEIGHT + 1));
-
-            y->avl_link[0] = new->avl_alloc->libavl_malloc(new->avl_alloc,
-                sizeof(*y->avl_link[0]));
-            if (y->avl_link[0] == NULL) {
-                if (y != (struct yagl_avl_node *) &new->avl_root) {
-                    y->avl_data = NULL;
-                    y->avl_link[1] = NULL;
-                }
-
-                yagl_copy_error_recovery(stack, height, new, destroy);
-                return NULL;
-            }
-
-            stack[height++] = (struct yagl_avl_node *) x;
-            stack[height++] = y;
-            x = x->avl_link[0];
-            y = y->avl_link[0];
-        }
-        y->avl_link[0] = NULL;
-
-        for (;;) {
-            y->avl_balance = x->avl_balance;
-            if (copy == NULL) {
-                y->avl_data = x->avl_data;
-            } else {
-                y->avl_data = copy(x->avl_data, org->avl_param);
-                if (y->avl_data == NULL) {
-                    y->avl_link[1] = NULL;
-                    yagl_copy_error_recovery(stack, height, new, destroy);
-                    return NULL;
-                }
-            }
-
-            if (x->avl_link[1] != NULL) {
-                y->avl_link[1] = new->avl_alloc->libavl_malloc(new->avl_alloc,
-                    sizeof(*y->avl_link[1]));
-                if (y->avl_link[1] == NULL) {
-                    yagl_copy_error_recovery(stack, height, new, destroy);
-                    return NULL;
-                }
-
-                x = x->avl_link[1];
-                y = y->avl_link[1];
-                break;
-            } else {
-                y->avl_link[1] = NULL;
-            }
-
-            if (height <= 2) {
-                return new;
-            }
-
-            y = stack[--height];
-            x = stack[--height];
-        }
-    }
-}
-
-/*
- * Frees storage allocated for |tree|.
- * If |destroy != NULL|, applies it to each data item in inorder.
- */
-void yagl_avl_destroy(struct yagl_avl_table *tree, yagl_avl_item_func *destroy)
-{
-    struct yagl_avl_node *p, *q;
-
-    assert(tree != NULL);
-
-    for (p = tree->avl_root; p != NULL; p = q) {
-        if (p->avl_link[0] == NULL) {
-            q = p->avl_link[1];
-            if (destroy != NULL && p->avl_data != NULL) {
-                destroy(p->avl_data, tree->avl_param);
-            }
-            tree->avl_alloc->libavl_free(tree->avl_alloc, p);
-        } else {
-            q = p->avl_link[0];
-            p->avl_link[0] = q->avl_link[1];
-            q->avl_link[1] = p;
-        }
-    }
-
-    tree->avl_alloc->libavl_free(tree->avl_alloc, tree);
-}
-
-/*
- * Allocates |size| bytes of space using |malloc()|.
- * Returns a null pointer if allocation fails.
- */
-void *yagl_avl_malloc(struct yagl_libavl_allocator *allocator, size_t size)
-{
-    assert(allocator != NULL && size > 0);
-    return g_malloc(size);
-}
-
-/* Frees |block|. */
-void yagl_avl_free(struct yagl_libavl_allocator *allocator, void *block)
-{
-    assert(allocator != NULL && block != NULL);
-    g_free(block);
-}
-
-/* Default memory allocator that uses |g_malloc()| and |g_free()|. */
-struct yagl_libavl_allocator yagl_avl_allocator_default = {
-    yagl_avl_malloc, yagl_avl_free
-};
-
-#undef NDEBUG
-#include <assert.h>
-
-/* Asserts that |avl_insert()| succeeds at inserting |item| into |table|. */
-void (yagl_avl_assert_insert)(struct yagl_avl_table *table, void *item)
-{
-    void **p = yagl_avl_probe(table, item);
-    assert(p != NULL && *p == item);
-}
-
-/*
- * Asserts that |avl_delete()| really removes |item| from |table|,
- * and returns the removed item.
- */
-void *(yagl_avl_assert_delete)(struct yagl_avl_table *table, void *item)
-{
-    void *p = yagl_avl_delete(table, item);
-    assert(p != NULL);
-    return p;
-}
diff --git a/hw/yagl/yagl_avl.h b/hw/yagl/yagl_avl.h
deleted file mode 100644 (file)
index bb605fd..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * yagl
- *
- * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact:
- * Stanislav Vorobiov <s.vorobiov@samsung.com>
- * Jinhyung Jo <jinhyung.jo@samsung.com>
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *
- * Contributors:
- * - S-Core Co., Ltd
- *
- */
-
-/*
- * AVL tree implementation from libavl project.
- */
-
-#ifndef _QEMU_YAGL_AVL_H
-#define _QEMU_YAGL_AVL_H
-
-#include "yagl_types.h"
-
-/* Function types. */
-typedef int yagl_avl_comparison_func(const void */*avl_a*/, const void */*avl_b*/,
-    void */*avl_param*/);
-typedef void yagl_avl_item_func(void */*avl_item*/, void */*avl_param*/);
-typedef void *yagl_avl_copy_func(void */*avl_item*/, void */*avl_param*/);
-
-/* Memory allocator. */
-struct yagl_libavl_allocator
-{
-    void *(*libavl_malloc)(struct yagl_libavl_allocator */*allocator*/,
-                           size_t /*libavl_size*/);
-    void (*libavl_free)(struct yagl_libavl_allocator */*allocator*/,
-                        void */*libavl_block*/);
-};
-
-/* Default memory allocator. */
-extern struct yagl_libavl_allocator yagl_avl_allocator_default;
-void *yagl_avl_malloc(struct yagl_libavl_allocator *allocator, size_t libavl_size);
-void yagl_avl_free(struct yagl_libavl_allocator *allocator, void *libavl_block);
-
-/* Maximum AVL tree height. */
-#define YAGL_AVL_MAX_HEIGHT 92
-
-/* Tree data structure. */
-struct yagl_avl_table
-{
-    struct yagl_avl_node *avl_root; /* Tree's root. */
-    yagl_avl_comparison_func *avl_compare; /* Comparison function. */
-    void *avl_param; /* Extra argument to |avl_compare|. */
-    struct yagl_libavl_allocator *avl_alloc; /* Memory allocator. */
-    size_t avl_count; /* Number of items in tree. */
-    unsigned long avl_generation; /* Generation number. */
-};
-
-/* An AVL tree node. */
-struct yagl_avl_node
-{
-    struct yagl_avl_node *avl_link[2]; /* Subtrees. */
-    void *avl_data; /* Pointer to data. */
-    signed char avl_balance; /* Balance factor. */
-};
-
-/* AVL traverser structure. */
-struct yagl_avl_traverser
-{
-    struct yagl_avl_table *avl_table; /* Tree being traversed. */
-    struct yagl_avl_node *avl_node; /* Current node in tree. */
-    struct yagl_avl_node *avl_stack[YAGL_AVL_MAX_HEIGHT];
-    /* All the nodes above |avl_node|. */
-    size_t avl_height; /* Number of nodes in |avl_parent|. */
-    unsigned long avl_generation; /* Generation number. */
-};
-
-/* Table functions. */
-struct yagl_avl_table *yagl_avl_create(yagl_avl_comparison_func *compare,
-    void *param,
-    struct yagl_libavl_allocator *allocator);
-struct yagl_avl_table *yagl_avl_copy(const struct yagl_avl_table *org,
-    yagl_avl_copy_func *copy,
-    yagl_avl_item_func *destroy, struct yagl_libavl_allocator *allocator);
-void yagl_avl_destroy(struct yagl_avl_table *tree, yagl_avl_item_func *destroy);
-void **yagl_avl_probe(struct yagl_avl_table *tree, void *item);
-void *yagl_avl_insert(struct yagl_avl_table *table, void *item);
-void *yagl_avl_replace(struct yagl_avl_table *table, void *item);
-void *yagl_avl_delete(struct yagl_avl_table *tree, const void *item);
-void *yagl_avl_find(const struct yagl_avl_table *tree, const void *item);
-void yagl_avl_assert_insert(struct yagl_avl_table *table, void *item);
-void *yagl_avl_assert_delete(struct yagl_avl_table *table, void *item);
-
-#define yagl_avl_count(table) ((size_t)(table)->avl_count)
-
-/* Table traverser functions. */
-void yagl_avl_t_init(struct yagl_avl_traverser *trav,
-                     struct yagl_avl_table *tree);
-void *yagl_avl_t_first(struct yagl_avl_traverser *trav,
-                       struct yagl_avl_table *tree);
-void *yagl_avl_t_last(struct yagl_avl_traverser *trav,
-                      struct yagl_avl_table *tree);
-void *yagl_avl_t_find(struct yagl_avl_traverser *trav,
-                      struct yagl_avl_table *tree,
-                      void *item);
-void *yagl_avl_t_insert(struct yagl_avl_traverser *trav,
-                        struct yagl_avl_table *tree,
-                        void *item);
-void *yagl_avl_t_copy(struct yagl_avl_traverser *trav,
-                      const struct yagl_avl_traverser *src);
-void *yagl_avl_t_next(struct yagl_avl_traverser *trav);
-void *yagl_avl_t_prev(struct yagl_avl_traverser *trav);
-void *yagl_avl_t_cur(struct yagl_avl_traverser *trav);
-void *yagl_avl_t_replace(struct yagl_avl_traverser *trav, void *new_item);
-
-#endif
index 40fd897..d8262dc 100644 (file)
  */
 
 #include "yagl_object_map.h"
-#include "yagl_avl.h"
 
-struct yagl_object_map_entry
+static void yagl_object_map_entry_destroy_func(gpointer data)
 {
-    yagl_object_name local_name;
+    struct yagl_object *item = data;
 
-    struct yagl_object *obj;
-};
-
-static int yagl_object_map_entry_comparison_func(const void *avl_a,
-                                                 const void *avl_b,
-                                                 void *avl_param)
-{
-    const struct yagl_object_map_entry *a = avl_a;
-    const struct yagl_object_map_entry *b = avl_b;
-
-    if (a->local_name < b->local_name) {
-        return -1;
-    } else if (a->local_name > b->local_name) {
-        return 1;
-    } else {
-        return 0;
-    }
-}
-
-static void yagl_object_map_entry_destroy_func(void *avl_item, void *avl_param)
-{
-    struct yagl_object_map_entry *item = avl_item;
-
-    item->obj->destroy(item->obj);
-
-    g_free(item);
+    item->destroy(item);
 }
 
 struct yagl_object_map *yagl_object_map_create(void)
 {
     struct yagl_object_map *object_map = g_malloc0(sizeof(struct yagl_object_map));
 
-    object_map->entries = yagl_avl_create(&yagl_object_map_entry_comparison_func,
-                                          object_map,
-                                          NULL);
+    object_map->entries = g_hash_table_new_full(g_direct_hash,
+                                                g_direct_equal,
+                                                NULL,
+                                                &yagl_object_map_entry_destroy_func);
+
     assert(object_map->entries);
 
     return object_map;
@@ -76,7 +52,8 @@ struct yagl_object_map *yagl_object_map_create(void)
 
 void yagl_object_map_destroy(struct yagl_object_map *object_map)
 {
-    yagl_avl_destroy(object_map->entries, &yagl_object_map_entry_destroy_func);
+    g_hash_table_destroy(object_map->entries);
+
     object_map->entries = NULL;
 
     g_free(object_map);
@@ -86,50 +63,38 @@ void yagl_object_map_add(struct yagl_object_map *object_map,
                          yagl_object_name local_name,
                          struct yagl_object *obj)
 {
-    struct yagl_object_map_entry *item =
-        g_malloc0(sizeof(struct yagl_object_map_entry));
+    guint size = g_hash_table_size(object_map->entries);
 
-    item->local_name = local_name;
-    item->obj = obj;
+    g_hash_table_insert(object_map->entries,
+                        GUINT_TO_POINTER(local_name),
+                        obj);
 
-    yagl_avl_assert_insert(object_map->entries, item);
+    assert(g_hash_table_size(object_map->entries) > size);
 }
 
 void yagl_object_map_remove(struct yagl_object_map *object_map,
                             yagl_object_name local_name)
 {
-    void *item;
-    struct yagl_object_map_entry dummy;
-
-    dummy.local_name = local_name;
+    guint size = g_hash_table_size(object_map->entries);
 
-    item = yagl_avl_assert_delete(object_map->entries, &dummy);
+    g_hash_table_remove(object_map->entries, GUINT_TO_POINTER(local_name));
 
-    yagl_object_map_entry_destroy_func(item, object_map->entries->avl_param);
+    assert(g_hash_table_size(object_map->entries) < size);
 }
 
 void yagl_object_map_remove_all(struct yagl_object_map *object_map)
 {
-    yagl_avl_destroy(object_map->entries, &yagl_object_map_entry_destroy_func);
-
-    object_map->entries = yagl_avl_create(&yagl_object_map_entry_comparison_func,
-                                          object_map,
-                                          NULL);
-    assert(object_map->entries);
+    g_hash_table_remove_all(object_map->entries);
 }
 
 yagl_object_name yagl_object_map_get(struct yagl_object_map *object_map,
                                      yagl_object_name local_name)
 {
-    struct yagl_object_map_entry *item;
-    struct yagl_object_map_entry dummy;
-
-    dummy.local_name = local_name;
-
-    item = yagl_avl_find(object_map->entries, &dummy);
+    struct yagl_object *item = g_hash_table_lookup(object_map->entries,
+                                                   GUINT_TO_POINTER(local_name));
 
     if (item) {
-        return item->obj->global_name;
+        return item->global_name;
     } else {
         assert(0);
         return 0;
index cd8ee4a..c4d8c3c 100644 (file)
@@ -31,8 +31,7 @@
 #define _QEMU_YAGL_OBJECT_MAP_H
 
 #include "yagl_types.h"
-
-struct yagl_avl_table;
+#include <glib.h>
 
 struct yagl_object
 {
@@ -43,7 +42,7 @@ struct yagl_object
 
 struct yagl_object_map
 {
-    struct yagl_avl_table *entries;
+    GHashTable *entries;
 };
 
 struct yagl_object_map *yagl_object_map_create(void);