From: "Alex Bennée" <alex.bennee@linaro.org>
To: "Emilio G. Cota" <cota@braap.org>
Cc: mttcg@listserver.greensocs.com, mark.burton@greensocs.com,
a.rigo@virtualopensystems.com, qemu-devel@nongnu.org,
guillaume.delbergue@greensocs.com, pbonzini@redhat.com,
Frederic Konrad <fred.konrad@greensocs.com>
Subject: Re: [Qemu-devel] [RFC 15/38] radix-tree: add generic lockless radix tree module
Date: Thu, 10 Sep 2015 15:25:50 +0100 [thread overview]
Message-ID: <87wpvy8i6p.fsf@linaro.org> (raw)
In-Reply-To: <1440375847-17603-16-git-send-email-cota@braap.org>
Emilio G. Cota <cota@braap.org> writes:
> This will be used by atomic instruction emulation code.
If we are adding utility functions into the code base like this (which I
can see being useful) we should at least add some documentation with
example calling conventions to docs/
Have you any performance numbers comparing the efficiency of the radix
approach to a "dumb" implementation?
>
> Signed-off-by: Emilio G. Cota <cota@braap.org>
> ---
> include/qemu/radix-tree.h | 29 ++++++++++++++++++
> util/Makefile.objs | 2 +-
> util/radix-tree.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 105 insertions(+), 1 deletion(-)
> create mode 100644 include/qemu/radix-tree.h
> create mode 100644 util/radix-tree.c
>
> diff --git a/include/qemu/radix-tree.h b/include/qemu/radix-tree.h
> new file mode 100644
> index 0000000..a4e1f97
> --- /dev/null
> +++ b/include/qemu/radix-tree.h
> @@ -0,0 +1,29 @@
> +#ifndef RADIX_TREE_H
> +#define RADIX_TREE_H
> +
> +#include <stddef.h>
> +
> +typedef struct QemuRadixNode QemuRadixNode;
> +typedef struct QemuRadixTree QemuRadixTree;
> +
> +struct QemuRadixNode {
> + void *slots[0];
> +};
> +
> +struct QemuRadixTree {
> + QemuRadixNode *root;
> + int radix;
> + int max_height;
> +};
> +
> +void qemu_radix_tree_init(QemuRadixTree *tree, int bits, int radix);
> +void *qemu_radix_tree_find_alloc(QemuRadixTree *tree, unsigned long index,
> + void *(*create)(unsigned long),
> + void (*delete)(void *));
> +
> +static inline void *qemu_radix_tree_find(QemuRadixTree *t, unsigned long index)
> +{
> + return qemu_radix_tree_find_alloc(t, index, NULL, NULL);
> +}
> +
> +#endif /* RADIX_TREE_H */
> diff --git a/util/Makefile.objs b/util/Makefile.objs
> index 114d657..6b18d3d 100644
> --- a/util/Makefile.objs
> +++ b/util/Makefile.objs
> @@ -1,4 +1,4 @@
> -util-obj-y = osdep.o cutils.o unicode.o qemu-timer-common.o
> +util-obj-y = osdep.o cutils.o unicode.o qemu-timer-common.o radix-tree.o
> util-obj-$(CONFIG_WIN32) += oslib-win32.o qemu-thread-win32.o event_notifier-win32.o
> util-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o event_notifier-posix.o qemu-openpty.o
> util-obj-y += envlist.o path.o module.o
> diff --git a/util/radix-tree.c b/util/radix-tree.c
> new file mode 100644
> index 0000000..69eff29
> --- /dev/null
> +++ b/util/radix-tree.c
> @@ -0,0 +1,75 @@
> +/*
> + * radix-tree.c
> + * Non-blocking radix tree.
> + *
> + * Features:
> + * - Concurrent lookups and inserts.
> + * - No support for deletions.
> + *
> + * Conventions:
> + * - Height is counted starting from 0 at the bottom.
> + * - The index is used from left to right, i.e. MSBs are used first. This way
> + * nearby addresses land in nearby slots, minimising cache/TLB misses.
> + */
> +#include <glib.h>
> +
> +#include "qemu/radix-tree.h"
> +#include "qemu/atomic.h"
> +#include "qemu/bitops.h"
> +#include "qemu/osdep.h"
> +
> +typedef struct QemuRadixNode QemuRadixNode;
> +
> +void *qemu_radix_tree_find_alloc(QemuRadixTree *tree, unsigned long index,
> + void *(*create)(unsigned long),
> + void (*delete)(void *))
> +{
> + QemuRadixNode *parent;
> + QemuRadixNode *node = tree->root;
> + void **slot;
> + int n_slots = BIT(tree->radix);
> + int level = tree->max_height - 1;
> + int shift = (level - 1) * tree->radix;
> +
> + do {
> + parent = node;
> + slot = parent->slots + ((index >> shift) & (n_slots - 1));
> + node = atomic_read(slot);
> + smp_read_barrier_depends();
> + if (node == NULL) {
> + void *old;
> + void *new;
> +
> + if (!create) {
> + return NULL;
> + }
> +
> + if (level == 1) {
> + node = create(index);
> + } else {
> + node = g_malloc0(sizeof(*node) + sizeof(void *) * n_slots);
> + }
> + new = node;
> + /* atomic_cmpxchg is type-safe so we cannot use 'node' here */
> + old = atomic_cmpxchg(slot, NULL, new);
> + if (old) {
> + if (level == 1) {
> + delete(node);
> + } else {
> + g_free(node);
> + }
> + node = old;
> + }
> + }
> + shift -= tree->radix;
> + level--;
> + } while (level > 0);
> + return node;
> +}
> +
> +void qemu_radix_tree_init(QemuRadixTree *tree, int bits, int radix)
> +{
> + tree->radix = radix;
> + tree->max_height = 1 + DIV_ROUND_UP(bits, radix);
> + tree->root = g_malloc0(sizeof(*tree->root) + sizeof(void *) * BIT(radix));
> +}
--
Alex Bennée
next prev parent reply other threads:[~2015-09-10 14:26 UTC|newest]
Thread overview: 110+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-08-24 0:23 [Qemu-devel] [RFC 00/38] MTTCG: i386, user+system mode Emilio G. Cota
2015-08-24 0:23 ` [Qemu-devel] [RFC 01/38] cpu-exec: add missing mmap_lock in tb_find_slow Emilio G. Cota
2015-09-07 15:33 ` Alex Bennée
2015-08-24 0:23 ` [Qemu-devel] [RFC 02/38] hw/i386/kvmvapic: add missing include of tcg.h Emilio G. Cota
2015-09-07 15:49 ` Alex Bennée
2015-09-07 16:11 ` Paolo Bonzini
2015-08-24 0:23 ` [Qemu-devel] [RFC 03/38] cpu-exec: set current_cpu at cpu_exec() Emilio G. Cota
2015-08-24 1:03 ` Paolo Bonzini
2015-08-25 0:41 ` [Qemu-devel] [PATCH 1/4] cpus: add qemu_cpu_thread_init_common() to avoid code duplication Emilio G. Cota
2015-08-25 0:41 ` [Qemu-devel] [PATCH 2/4] linux-user: add helper to set current_cpu before cpu_loop() Emilio G. Cota
2015-08-25 0:41 ` [Qemu-devel] [PATCH 3/4] linux-user: call rcu_(un)register_thread on thread creation/deletion Emilio G. Cota
2015-08-26 0:22 ` Paolo Bonzini
2015-08-25 0:41 ` [Qemu-devel] [PATCH 4/4] bsd-user: add helper to set current_cpu before cpu_loop() Emilio G. Cota
2015-08-25 18:07 ` Emilio G. Cota
2015-08-24 0:23 ` [Qemu-devel] [RFC 04/38] translate-all: remove volatile from have_tb_lock Emilio G. Cota
2015-09-07 15:50 ` Alex Bennée
2015-09-07 16:12 ` Paolo Bonzini
2015-08-24 0:23 ` [Qemu-devel] [RFC 05/38] thread-posix: inline qemu_spin functions Emilio G. Cota
2015-08-24 1:04 ` Paolo Bonzini
2015-08-25 2:30 ` Emilio G. Cota
2015-08-25 19:30 ` Emilio G. Cota
2015-08-25 22:53 ` Paolo Bonzini
2015-08-24 0:23 ` [Qemu-devel] [RFC 06/38] seqlock: add missing 'inline' to seqlock_read_retry Emilio G. Cota
2015-09-07 15:50 ` Alex Bennée
2015-08-24 0:23 ` [Qemu-devel] [RFC 07/38] seqlock: read sequence number atomically Emilio G. Cota
2015-09-07 15:53 ` Alex Bennée
2015-09-07 16:13 ` Paolo Bonzini
2015-08-24 0:23 ` [Qemu-devel] [RFC 08/38] rcu: init rcu_registry_lock after fork Emilio G. Cota
2015-09-08 17:34 ` Alex Bennée
2015-09-08 19:03 ` Emilio G. Cota
2015-09-09 9:35 ` Alex Bennée
2015-08-24 0:23 ` [Qemu-devel] [RFC 09/38] rcu: fix comment with s/rcu_gp_lock/rcu_registry_lock/ Emilio G. Cota
2015-09-10 11:18 ` Alex Bennée
2015-08-24 0:23 ` [Qemu-devel] [RFC 10/38] translate-all: remove obsolete comment about l1_map Emilio G. Cota
2015-09-10 11:59 ` Alex Bennée
2015-08-24 0:23 ` [Qemu-devel] [RFC 11/38] qemu-thread: handle spurious futex_wait wakeups Emilio G. Cota
2015-09-10 13:22 ` Alex Bennée
2015-09-10 17:46 ` Emilio G. Cota
2015-08-24 0:23 ` [Qemu-devel] [RFC 12/38] linux-user: call rcu_(un)register_thread on pthread_(exit|create) Emilio G. Cota
2015-08-25 0:45 ` Emilio G. Cota
2015-08-24 0:23 ` [Qemu-devel] [RFC 13/38] cputlb: add physical address to CPUTLBEntry Emilio G. Cota
2015-09-10 13:49 ` Alex Bennée
2015-09-10 17:50 ` Emilio G. Cota
2015-09-21 5:01 ` Paolo Bonzini
2015-08-24 0:23 ` [Qemu-devel] [RFC 14/38] softmmu: add helpers to get ld/st physical addresses Emilio G. Cota
2015-08-24 2:02 ` Paolo Bonzini
2015-08-25 2:47 ` Emilio G. Cota
2015-08-24 0:23 ` [Qemu-devel] [RFC 15/38] radix-tree: add generic lockless radix tree module Emilio G. Cota
2015-09-10 14:25 ` Alex Bennée [this message]
2015-09-10 18:00 ` Emilio G. Cota
2015-08-24 0:23 ` [Qemu-devel] [RFC 16/38] aie: add module for Atomic Instruction Emulation Emilio G. Cota
2015-08-24 0:23 ` [Qemu-devel] [RFC 17/38] aie: add target helpers Emilio G. Cota
2015-09-17 15:14 ` Alex Bennée
2015-09-21 5:18 ` Paolo Bonzini
2015-09-21 20:59 ` Alex Bennée
2015-08-24 0:23 ` [Qemu-devel] [RFC 18/38] tcg: add fences Emilio G. Cota
2015-09-10 15:28 ` Alex Bennée
2015-08-24 0:23 ` [Qemu-devel] [RFC 19/38] tcg: add tcg_gen_smp_rmb() Emilio G. Cota
2015-09-10 16:01 ` Alex Bennée
2015-09-10 18:05 ` Emilio G. Cota
2015-08-24 0:23 ` [Qemu-devel] [RFC 20/38] tcg/i386: implement fences Emilio G. Cota
2015-08-24 1:32 ` Paolo Bonzini
2015-08-25 3:02 ` Emilio G. Cota
2015-08-25 22:55 ` Paolo Bonzini
2015-08-24 0:23 ` [Qemu-devel] [RFC 21/38] target-i386: emulate atomic instructions + barriers using AIE Emilio G. Cota
2015-09-17 15:30 ` Alex Bennée
2015-08-24 0:23 ` [Qemu-devel] [RFC 22/38] cpu: update interrupt_request atomically Emilio G. Cota
2015-08-24 1:09 ` Paolo Bonzini
2015-08-25 20:36 ` Emilio G. Cota
2015-08-25 22:52 ` Paolo Bonzini
2015-08-24 0:23 ` [Qemu-devel] [RFC 23/38] cpu-exec: grab iothread lock during interrupt handling Emilio G. Cota
2015-09-09 10:13 ` Paolo Bonzini
2015-08-24 0:23 ` [Qemu-devel] [RFC 24/38] cpu-exec: reset mmap_lock after exiting the CPU loop Emilio G. Cota
2015-08-24 2:01 ` Paolo Bonzini
2015-08-25 21:16 ` Emilio G. Cota
2015-08-24 0:23 ` [Qemu-devel] [RFC 25/38] cpu: add barriers around cpu->tcg_exit_req Emilio G. Cota
2015-08-24 2:01 ` Paolo Bonzini
2015-08-24 0:23 ` [Qemu-devel] [RFC 26/38] cpu: protect tb_jmp_cache with seqlock Emilio G. Cota
2015-08-24 1:14 ` Paolo Bonzini
2015-08-25 21:46 ` Emilio G. Cota
2015-08-25 22:49 ` Paolo Bonzini
2015-09-04 8:50 ` Paolo Bonzini
2015-09-04 10:04 ` Paolo Bonzini
2015-08-24 0:23 ` [Qemu-devel] [RFC 27/38] cpu-exec: convert tb_invalidated_flag into a per-TB flag Emilio G. Cota
2015-08-24 0:23 ` [Qemu-devel] [RFC 28/38] cpu-exec: use RCU to perform lockless TB lookups Emilio G. Cota
2015-08-24 0:23 ` [Qemu-devel] [RFC 29/38] tcg: export have_tb_lock Emilio G. Cota
2015-08-24 0:23 ` [Qemu-devel] [RFC 30/38] translate-all: add tb_lock assertions Emilio G. Cota
2015-08-24 0:24 ` [Qemu-devel] [RFC 31/38] cpu: protect l1_map with tb_lock in full-system mode Emilio G. Cota
2015-08-24 1:07 ` Paolo Bonzini
2015-08-25 21:54 ` Emilio G. Cota
2015-08-24 0:24 ` [Qemu-devel] [RFC 32/38] cpu list: convert to RCU QLIST Emilio G. Cota
2015-08-24 0:24 ` [Qemu-devel] [RFC 33/38] cpu: introduce cpu_tcg_sched_work to run work while other CPUs sleep Emilio G. Cota
2015-08-24 1:24 ` Paolo Bonzini
2015-08-25 22:18 ` Emilio G. Cota
2015-08-24 0:24 ` [Qemu-devel] [RFC 34/38] translate-all: use tcg_sched_work for tb_flush Emilio G. Cota
2015-08-24 0:24 ` [Qemu-devel] [RFC 35/38] cputlb: use cpu_tcg_sched_work for tlb_flush_all Emilio G. Cota
2015-08-24 1:29 ` Paolo Bonzini
2015-08-25 22:31 ` Emilio G. Cota
2015-08-26 0:25 ` Paolo Bonzini
2015-09-01 16:10 ` Alex Bennée
2015-09-01 19:38 ` Emilio G. Cota
2015-09-01 20:18 ` Peter Maydell
2015-08-24 0:24 ` [Qemu-devel] [RFC 36/38] cputlb: use tcg_sched_work for tlb_flush_page_all Emilio G. Cota
2015-08-24 0:24 ` [Qemu-devel] [RFC 37/38] cpus: remove async_run_safe_work_on_cpu Emilio G. Cota
2015-08-24 0:24 ` [Qemu-devel] [RFC 38/38] Revert "target-i386: yield to another VCPU on PAUSE" Emilio G. Cota
2015-08-24 1:29 ` Paolo Bonzini
2015-08-24 2:01 ` [Qemu-devel] [RFC 00/38] MTTCG: i386, user+system mode Paolo Bonzini
2015-08-25 22:36 ` Emilio G. Cota
2015-08-24 16:08 ` Artyom Tarasenko
2015-08-24 20:16 ` Emilio G. Cota
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=87wpvy8i6p.fsf@linaro.org \
--to=alex.bennee@linaro.org \
--cc=a.rigo@virtualopensystems.com \
--cc=cota@braap.org \
--cc=fred.konrad@greensocs.com \
--cc=guillaume.delbergue@greensocs.com \
--cc=mark.burton@greensocs.com \
--cc=mttcg@listserver.greensocs.com \
--cc=pbonzini@redhat.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.