Commit 07f426c3 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20180926' into staging



Queued tcg patches

# gpg: Signature made Wed 26 Sep 2018 19:27:22 BST
# gpg:                using RSA key 64DF38E8AF7E215F
# gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>"
# Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A  05C0 64DF 38E8 AF7E 215F

* remotes/rth/tags/pull-tcg-20180926:
  tcg/i386: fix vector operations on 32-bit hosts
  qht-bench: add -p flag to precompute hash values
  qht: constify arguments to some internal functions
  qht: constify qht_statistics_init
  qht: constify qht_lookup
  qht: fix comment in qht_bucket_remove_entry
  qht: drop ht argument from qht iterators
  test-qht: speed up + test qht_resize
  test-qht: test deletion of the last entry in a bucket
  test-qht: test removal of non-existent entries
  test-qht: test qht_iter_remove
  qht: add qht_iter_remove
  qht: remove unused map param from qht_remove__locked

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 042938f4 93bf9a42
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -1282,8 +1282,7 @@ void tb_flush(CPUState *cpu)
 */
#ifdef CONFIG_USER_ONLY

static void
do_tb_invalidate_check(struct qht *ht, void *p, uint32_t hash, void *userp)
static void do_tb_invalidate_check(void *p, uint32_t hash, void *userp)
{
    TranslationBlock *tb = p;
    target_ulong addr = *(target_ulong *)userp;
@@ -1304,8 +1303,7 @@ static void tb_invalidate_check(target_ulong address)
    qht_iter(&tb_ctx.htable, do_tb_invalidate_check, &address);
}

static void
do_tb_page_check(struct qht *ht, void *p, uint32_t hash, void *userp)
static void do_tb_page_check(void *p, uint32_t hash, void *userp)
{
    TranslationBlock *tb = p;
    int flags1, flags2;
+22 −4
Original line number Diff line number Diff line
@@ -43,7 +43,8 @@ struct qht_stats {
};

typedef bool (*qht_lookup_func_t)(const void *obj, const void *userp);
typedef void (*qht_iter_func_t)(struct qht *ht, void *p, uint32_t h, void *up);
typedef void (*qht_iter_func_t)(void *p, uint32_t h, void *up);
typedef bool (*qht_iter_bool_func_t)(void *p, uint32_t h, void *up);

#define QHT_MODE_AUTO_RESIZE 0x1 /* auto-resize when heavily loaded */
#define QHT_MODE_RAW_MUTEXES 0x2 /* bypass the profiler (QSP) */
@@ -103,7 +104,7 @@ bool qht_insert(struct qht *ht, void *p, uint32_t hash, void **existing);
 * Returns the corresponding pointer when a match is found.
 * Returns NULL otherwise.
 */
void *qht_lookup_custom(struct qht *ht, const void *userp, uint32_t hash,
void *qht_lookup_custom(const struct qht *ht, const void *userp, uint32_t hash,
                        qht_lookup_func_t func);

/**
@@ -114,7 +115,7 @@ void *qht_lookup_custom(struct qht *ht, const void *userp, uint32_t hash,
 *
 * Calls qht_lookup_custom() using @ht's default comparison function.
 */
void *qht_lookup(struct qht *ht, const void *userp, uint32_t hash);
void *qht_lookup(const struct qht *ht, const void *userp, uint32_t hash);

/**
 * qht_remove - remove a pointer from the hash table
@@ -179,9 +180,26 @@ bool qht_resize(struct qht *ht, size_t n_elems);
 *
 * Each time it is called, user-provided @func is passed a pointer-hash pair,
 * plus @userp.
 *
 * Note: @ht cannot be accessed from @func
 * See also: qht_iter_remove()
 */
void qht_iter(struct qht *ht, qht_iter_func_t func, void *userp);

/**
 * qht_iter_remove - Iterate over a QHT, optionally removing entries
 * @ht: QHT to be iterated over
 * @func: function to be called for each entry in QHT
 * @userp: additional pointer to be passed to @func
 *
 * Each time it is called, user-provided @func is passed a pointer-hash pair,
 * plus @userp. If @func returns true, the pointer-hash pair is removed.
 *
 * Note: @ht cannot be accessed from @func
 * See also: qht_iter()
 */
void qht_iter_remove(struct qht *ht, qht_iter_bool_func_t func, void *userp);

/**
 * qht_statistics_init - Gather statistics from a QHT
 * @ht: QHT to gather statistics from
@@ -193,7 +211,7 @@ void qht_iter(struct qht *ht, qht_iter_func_t func, void *userp);
 * When done with @stats, pass the struct to qht_statistics_destroy().
 * Failing to do this will leak memory.
 */
void qht_statistics_init(struct qht *ht, struct qht_stats *stats);
void qht_statistics_init(const struct qht *ht, struct qht_stats *stats);

/**
 * qht_statistics_destroy - Destroy a &struct qht_stats
+0 −4
Original line number Diff line number Diff line
@@ -302,11 +302,7 @@ static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
    return 0;
}

#if TCG_TARGET_REG_BITS == 64
# define LOWREGMASK(x)	((x) & 7)
#else
# define LOWREGMASK(x)	(x)
#endif

#define P_EXT		0x100		/* 0x0f opcode prefix */
#define P_EXT38         0x200           /* 0x0f 0x38 opcode prefix */
+20 −6
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ static unsigned long resize_delay = 1000;
static double resize_rate; /* 0.0 to 1.0 */
static unsigned int n_rz_threads = 1;
static QemuThread *rz_threads;
static bool precompute_hash;

static double update_rate; /* 0.0 to 1.0 */
static uint64_t update_threshold;
@@ -101,11 +102,18 @@ static bool is_equal(const void *ap, const void *bp)
    return *a == *b;
}

static inline uint32_t h(unsigned long v)
static uint32_t h(unsigned long v)
{
    return tb_hash_func7(v, 0, 0, 0, 0);
}

static uint32_t hval(unsigned long v)
{
    return v;
}

static uint32_t (*hfunc)(unsigned long v) = h;

/*
 * From: https://en.wikipedia.org/wiki/Xorshift
 * This is faster than rand_r(), and gives us a wider range (RAND_MAX is only
@@ -149,7 +157,7 @@ static void do_rw(struct thread_info *info)
        bool read;

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

@@ -289,7 +297,9 @@ static void htable_init(void)
    /* avoid allocating memory later by allocating all the keys now */
    keys = g_malloc(sizeof(*keys) * n);
    for (i = 0; i < n; i++) {
        keys[i] = populate_offset + i;
        long val = populate_offset + i;

        keys[i] = precompute_hash ? h(val) : hval(val);
    }

    /* some sanity checks */
@@ -321,7 +331,7 @@ static void htable_init(void)

            r = xorshift64star(r);
            p = &keys[r & (init_range - 1)];
            hash = h(*p);
            hash = hfunc(*p);
            if (qht_insert(&ht, p, hash, NULL)) {
                break;
            }
@@ -412,7 +422,7 @@ static void parse_args(int argc, char *argv[])
    int c;

    for (;;) {
        c = getopt(argc, argv, "d:D:g:k:K:l:hn:N:o:r:Rs:S:u:");
        c = getopt(argc, argv, "d:D:g:k:K:l:hn:N:o:pr:Rs:S:u:");
        if (c < 0) {
            break;
        }
@@ -451,6 +461,10 @@ static void parse_args(int argc, char *argv[])
        case 'o':
            populate_offset = atol(optarg);
            break;
        case 'p':
            precompute_hash = true;
            hfunc = hval;
            break;
        case 'r':
            update_range = pow2ceil(atol(optarg));
            break;
+88 −5
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ static void insert(int a, int b)
    }
}

static void rm(int init, int end)
static void do_rm(int init, int end, bool exist)
{
    int i;

@@ -49,10 +49,24 @@ static void rm(int init, int end)
        uint32_t hash;

        hash = arr[i];
        if (exist) {
            g_assert_true(qht_remove(&ht, &arr[i], hash));
        } else {
            g_assert_false(qht_remove(&ht, &arr[i], hash));
        }
    }
}

static void rm(int init, int end)
{
    do_rm(init, end, true);
}

static void rm_nonexist(int init, int end)
{
    do_rm(init, end, false);
}

static void check(int a, int b, bool expected)
{
    struct qht_stats stats;
@@ -84,7 +98,7 @@ static void check(int a, int b, bool expected)
    qht_statistics_destroy(&stats);
}

static void count_func(struct qht *ht, void *p, uint32_t hash, void *userp)
static void count_func(void *p, uint32_t hash, void *userp)
{
    unsigned int *curr = userp;

@@ -108,14 +122,79 @@ static void iter_check(unsigned int count)
    g_assert_cmpuint(curr, ==, count);
}

static void sum_func(void *p, uint32_t hash, void *userp)
{
    uint32_t *sum = userp;
    uint32_t a = *(uint32_t *)p;

    *sum += a;
}

static void iter_sum_check(unsigned int expected)
{
    unsigned int sum = 0;

    qht_iter(&ht, sum_func, &sum);
    g_assert_cmpuint(sum, ==, expected);
}

static bool rm_mod_func(void *p, uint32_t hash, void *userp)
{
    uint32_t a = *(uint32_t *)p;
    unsigned int mod = *(unsigned int *)userp;

    return a % mod == 0;
}

static void iter_rm_mod(unsigned int mod)
{
    qht_iter_remove(&ht, rm_mod_func, &mod);
}

static void iter_rm_mod_check(unsigned int mod)
{
    unsigned int expected = 0;
    unsigned int i;

    for (i = 0; i < N; i++) {
        if (i % mod == 0) {
            continue;
        }
        expected += i;
    }
    iter_sum_check(expected);
}

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, is_equal, 0, mode);
    rm_nonexist(0, 4);
    /*
     * Test that we successfully delete the last element in a bucket.
     * This is a hard-to-reach code path when resizing is on, but without
     * resizing we can easily hit it if init_entries <= 1.
     * Given that the number of elements per bucket can be 4 or 6 depending on
     * the host's pointer size, test the removal of the 4th and 6th elements.
     */
    insert(0, 4);
    rm_nonexist(5, 6);
    rm(3, 4);
    check_n(3);
    insert(3, 6);
    rm(5, 6);
    check_n(5);
    rm_nonexist(7, 8);
    iter_rm_mod(1);

    if (!(mode & QHT_MODE_AUTO_RESIZE)) {
        qht_resize(&ht, init_entries * 4 + 4);
    }

    check_n(0);
    rm_nonexist(0, 10);
    insert(0, N);
    check(0, N, true);
    check_n(N);
@@ -138,8 +217,12 @@ static void qht_do_test(unsigned int mode, size_t init_entries)
    insert(10, 150);
    check_n(N);

    rm(1, 2);
    check_n(N - 1);
    qht_reset(&ht);
    insert(0, N);
    rm_nonexist(N, N + 32);
    iter_rm_mod(10);
    iter_rm_mod_check(10);
    check_n(N * 9 / 10);
    qht_reset_size(&ht, 0);
    check_n(0);
    check(0, N, false);
Loading