Commit 61b8cef1 authored by Emilio G. Cota's avatar Emilio G. Cota Committed by Richard Henderson
Browse files

qht: require a default comparison function



qht_lookup now uses the default cmp function. qht_lookup_custom is defined
to retain the old behaviour, that is a cmp function is explicitly provided.

qht_insert will gain use of the default cmp in the next patch.

Note that we move qht_lookup_custom's @func to be the last argument,
which makes the new qht_lookup as simple as possible.
Instead of this (i.e. keeping @func 2nd):
0000000000010750 <qht_lookup>:
   10750:       89 d1                   mov    %edx,%ecx
   10752:       48 89 f2                mov    %rsi,%rdx
   10755:       48 8b 77 08             mov    0x8(%rdi),%rsi
   10759:       e9 22 ff ff ff          jmpq   10680 <qht_lookup_custom>
   1075e:       66 90                   xchg   %ax,%ax

We get:
0000000000010740 <qht_lookup>:
   10740:       48 8b 4f 08             mov    0x8(%rdi),%rcx
   10744:       e9 37 ff ff ff          jmpq   10680 <qht_lookup_custom>
   10749:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)

Reviewed-by: default avatarRichard Henderson <richard.henderson@linaro.org>
Reviewed-by: default avatarAlex Bennée <alex.bennee@linaro.org>
Signed-off-by: default avatarEmilio G. Cota <cota@braap.org>
Signed-off-by: default avatarRichard Henderson <richard.henderson@linaro.org>
parent 1019242a
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -295,7 +295,7 @@ struct tb_desc {
    uint32_t trace_vcpu_dstate;
};

static bool tb_cmp(const void *p, const void *d)
static bool tb_lookup_cmp(const void *p, const void *d)
{
    const TranslationBlock *tb = p;
    const struct tb_desc *desc = d;
@@ -340,7 +340,7 @@ TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc,
    phys_pc = get_page_addr_code(desc.env, pc);
    desc.phys_page1 = phys_pc & TARGET_PAGE_MASK;
    h = tb_hash_func(phys_pc, pc, flags, cf_mask, *cpu->trace_dstate);
    return qht_lookup(&tb_ctx.htable, tb_cmp, &desc, h);
    return qht_lookup_custom(&tb_ctx.htable, &desc, h, tb_lookup_cmp);
}

void tb_set_jmp_target(TranslationBlock *tb, int n, uintptr_t addr)
+15 −1
Original line number Diff line number Diff line
@@ -782,11 +782,25 @@ static inline void code_gen_alloc(size_t tb_size)
    qemu_mutex_init(&tb_ctx.tb_lock);
}

static bool tb_cmp(const void *ap, const void *bp)
{
    const TranslationBlock *a = ap;
    const TranslationBlock *b = bp;

    return a->pc == b->pc &&
        a->cs_base == b->cs_base &&
        a->flags == b->flags &&
        (tb_cflags(a) & CF_HASH_MASK) == (tb_cflags(b) & CF_HASH_MASK) &&
        a->trace_vcpu_dstate == b->trace_vcpu_dstate &&
        a->page_addr[0] == b->page_addr[0] &&
        a->page_addr[1] == b->page_addr[1];
}

static void tb_htable_init(void)
{
    unsigned int mode = QHT_MODE_AUTO_RESIZE;

    qht_init(&tb_ctx.htable, CODE_GEN_HTABLE_SIZE, mode);
    qht_init(&tb_ctx.htable, tb_cmp, CODE_GEN_HTABLE_SIZE, mode);
}

/* Must be called before using the QEMU cpus. 'tb_size' is the size
+20 −5
Original line number Diff line number Diff line
@@ -11,8 +11,11 @@
#include "qemu/thread.h"
#include "qemu/qdist.h"

typedef bool (*qht_cmp_func_t)(const void *a, const void *b);

struct qht {
    struct qht_map *map;
    qht_cmp_func_t cmp;
    QemuMutex lock; /* serializes setters of ht->map */
    unsigned int mode;
};
@@ -47,10 +50,12 @@ typedef void (*qht_iter_func_t)(struct qht *ht, void *p, uint32_t h, void *up);
/**
 * qht_init - Initialize a QHT
 * @ht: QHT to be initialized
 * @cmp: default comparison function. Cannot be NULL.
 * @n_elems: number of entries the hash table should be optimized for.
 * @mode: bitmask with OR'ed QHT_MODE_*
 */
void qht_init(struct qht *ht, size_t n_elems, unsigned int mode);
void qht_init(struct qht *ht, qht_cmp_func_t cmp, size_t n_elems,
              unsigned int mode);

/**
 * qht_destroy - destroy a previously initialized QHT
@@ -78,11 +83,11 @@ void qht_destroy(struct qht *ht);
bool qht_insert(struct qht *ht, void *p, uint32_t hash);

/**
 * qht_lookup - Look up a pointer in a QHT
 * qht_lookup_custom - Look up a pointer using a custom comparison function.
 * @ht: QHT to be looked up
 * @func: function to compare existing pointers against @userp
 * @userp: pointer to pass to @func
 * @hash: hash of the pointer to be looked up
 * @func: function to compare existing pointers against @userp
 *
 * Needs to be called under an RCU read-critical section.
 *
@@ -94,8 +99,18 @@ bool qht_insert(struct qht *ht, void *p, uint32_t hash);
 * Returns the corresponding pointer when a match is found.
 * Returns NULL otherwise.
 */
void *qht_lookup(struct qht *ht, qht_lookup_func_t func, const void *userp,
                 uint32_t hash);
void *qht_lookup_custom(struct qht *ht, const void *userp, uint32_t hash,
                        qht_lookup_func_t func);

/**
 * qht_lookup - Look up a pointer in a QHT
 * @ht: QHT to be looked up
 * @userp: pointer to pass to the comparison function
 * @hash: hash of the pointer to be looked up
 *
 * Calls qht_lookup_custom() using @ht's default comparison function.
 */
void *qht_lookup(struct qht *ht, const void *userp, uint32_t hash);

/**
 * qht_remove - remove a pointer from the hash table
+7 −7
Original line number Diff line number Diff line
@@ -93,10 +93,10 @@ static void usage_complete(int argc, char *argv[])
    exit(-1);
}

static bool is_equal(const void *obj, const void *userp)
static bool is_equal(const void *ap, const void *bp)
{
    const long *a = obj;
    const long *b = userp;
    const long *a = ap;
    const long *b = bp;

    return *a == *b;
}
@@ -150,7 +150,7 @@ static void do_rw(struct thread_info *info)

        p = &keys[info->r & (lookup_range - 1)];
        hash = h(*p);
        read = qht_lookup(&ht, is_equal, p, hash);
        read = qht_lookup(&ht, p, hash);
        if (read) {
            stats->rd++;
        } else {
@@ -162,7 +162,7 @@ static void do_rw(struct thread_info *info)
        if (info->write_op) {
            bool written = false;

            if (qht_lookup(&ht, is_equal, p, hash) == NULL) {
            if (qht_lookup(&ht, p, hash) == NULL) {
                written = qht_insert(&ht, p, hash);
            }
            if (written) {
@@ -173,7 +173,7 @@ static void do_rw(struct thread_info *info)
        } else {
            bool removed = false;

            if (qht_lookup(&ht, is_equal, p, hash)) {
            if (qht_lookup(&ht, p, hash)) {
                removed = qht_remove(&ht, p, hash);
            }
            if (removed) {
@@ -308,7 +308,7 @@ static void htable_init(void)
    }

    /* initialize the hash table */
    qht_init(&ht, qht_n_elems, qht_mode);
    qht_init(&ht, is_equal, qht_n_elems, qht_mode);
    assert(init_size <= init_range);

    pr_params();
+10 −5
Original line number Diff line number Diff line
@@ -13,10 +13,10 @@
static struct qht ht;
static int32_t arr[N * 2];

static bool is_equal(const void *obj, const void *userp)
static bool is_equal(const void *ap, const void *bp)
{
    const int32_t *a = obj;
    const int32_t *b = userp;
    const int32_t *a = ap;
    const int32_t *b = bp;

    return *a == *b;
}
@@ -60,7 +60,12 @@ static void check(int a, int b, bool expected)

        val = i;
        hash = i;
        p = qht_lookup(&ht, is_equal, &val, hash);
        /* test both lookup variants; results should be the same */
        if (i % 2) {
            p = qht_lookup(&ht, &val, hash);
        } else {
            p = qht_lookup_custom(&ht, &val, hash, is_equal);
        }
        g_assert_true(!!p == expected);
    }
    rcu_read_unlock();
@@ -102,7 +107,7 @@ static void qht_do_test(unsigned int mode, size_t init_entries)
    /* under KVM we might fetch stats from an uninitialized qht */
    check_n(0);

    qht_init(&ht, 0, mode);
    qht_init(&ht, is_equal, 0, mode);

    check_n(0);
    insert(0, N);
Loading