qemu/include/qemu/qht.h
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2016, Emilio G. Cota <cota@braap.org>
   3 *
   4 * License: GNU GPL, version 2 or later.
   5 *   See the COPYING file in the top-level directory.
   6 */
   7#ifndef QEMU_QHT_H
   8#define QEMU_QHT_H
   9
  10#include "qemu/seqlock.h"
  11#include "qemu/thread.h"
  12#include "qemu/qdist.h"
  13
  14typedef bool (*qht_cmp_func_t)(const void *a, const void *b);
  15
  16struct qht {
  17    struct qht_map *map;
  18    qht_cmp_func_t cmp;
  19    QemuMutex lock; /* serializes setters of ht->map */
  20    unsigned int mode;
  21};
  22
  23/**
  24 * struct qht_stats - Statistics of a QHT
  25 * @head_buckets: number of head buckets
  26 * @used_head_buckets: number of non-empty head buckets
  27 * @entries: total number of entries
  28 * @chain: frequency distribution representing the number of buckets in each
  29 *         chain, excluding empty chains.
  30 * @occupancy: frequency distribution representing chain occupancy rate.
  31 *             Valid range: from 0.0 (empty) to 1.0 (full occupancy).
  32 *
  33 * An entry is a pointer-hash pair.
  34 * Each bucket can host several entries.
  35 * Chains are chains of buckets, whose first link is always a head bucket.
  36 */
  37struct qht_stats {
  38    size_t head_buckets;
  39    size_t used_head_buckets;
  40    size_t entries;
  41    struct qdist chain;
  42    struct qdist occupancy;
  43};
  44
  45typedef bool (*qht_lookup_func_t)(const void *obj, const void *userp);
  46typedef void (*qht_iter_func_t)(void *p, uint32_t h, void *up);
  47typedef bool (*qht_iter_bool_func_t)(void *p, uint32_t h, void *up);
  48
  49#define QHT_MODE_AUTO_RESIZE 0x1 /* auto-resize when heavily loaded */
  50#define QHT_MODE_RAW_MUTEXES 0x2 /* bypass the profiler (QSP) */
  51
  52/**
  53 * qht_init - Initialize a QHT
  54 * @ht: QHT to be initialized
  55 * @cmp: default comparison function. Cannot be NULL.
  56 * @n_elems: number of entries the hash table should be optimized for.
  57 * @mode: bitmask with OR'ed QHT_MODE_*
  58 */
  59void qht_init(struct qht *ht, qht_cmp_func_t cmp, size_t n_elems,
  60              unsigned int mode);
  61
  62/**
  63 * qht_destroy - destroy a previously initialized QHT
  64 * @ht: QHT to be destroyed
  65 *
  66 * Call only when there are no readers/writers left.
  67 */
  68void qht_destroy(struct qht *ht);
  69
  70/**
  71 * qht_insert - Insert a pointer into the hash table
  72 * @ht: QHT to insert to
  73 * @p: pointer to be inserted
  74 * @hash: hash corresponding to @p
  75 * @existing: address where the pointer to an existing entry can be copied to
  76 *
  77 * Attempting to insert a NULL @p is a bug.
  78 * Inserting the same pointer @p with different @hash values is a bug.
  79 *
  80 * In case of successful operation, smp_wmb() is implied before the pointer is
  81 * inserted into the hash table.
  82 *
  83 * Returns true on success.
  84 * Returns false if there is an existing entry in the table that is equivalent
  85 * (i.e. ht->cmp matches and the hash is the same) to @p-@h. If @existing
  86 * is !NULL, a pointer to this existing entry is copied to it.
  87 */
  88bool qht_insert(struct qht *ht, void *p, uint32_t hash, void **existing);
  89
  90/**
  91 * qht_lookup_custom - Look up a pointer using a custom comparison function.
  92 * @ht: QHT to be looked up
  93 * @userp: pointer to pass to @func
  94 * @hash: hash of the pointer to be looked up
  95 * @func: function to compare existing pointers against @userp
  96 *
  97 * Needs to be called under an RCU read-critical section.
  98 *
  99 * smp_read_barrier_depends() is implied before the call to @func.
 100 *
 101 * The user-provided @func compares pointers in QHT against @userp.
 102 * If the function returns true, a match has been found.
 103 *
 104 * Returns the corresponding pointer when a match is found.
 105 * Returns NULL otherwise.
 106 */
 107void *qht_lookup_custom(const struct qht *ht, const void *userp, uint32_t hash,
 108                        qht_lookup_func_t func);
 109
 110/**
 111 * qht_lookup - Look up a pointer in a QHT
 112 * @ht: QHT to be looked up
 113 * @userp: pointer to pass to the comparison function
 114 * @hash: hash of the pointer to be looked up
 115 *
 116 * Calls qht_lookup_custom() using @ht's default comparison function.
 117 */
 118void *qht_lookup(const struct qht *ht, const void *userp, uint32_t hash);
 119
 120/**
 121 * qht_remove - remove a pointer from the hash table
 122 * @ht: QHT to remove from
 123 * @p: pointer to be removed
 124 * @hash: hash corresponding to @p
 125 *
 126 * Attempting to remove a NULL @p is a bug.
 127 *
 128 * Just-removed @p pointers cannot be immediately freed; they need to remain
 129 * valid until the end of the RCU grace period in which qht_remove() is called.
 130 * This guarantees that concurrent lookups will always compare against valid
 131 * data.
 132 *
 133 * Returns true on success.
 134 * Returns false if the @p-@hash pair was not found.
 135 */
 136bool qht_remove(struct qht *ht, const void *p, uint32_t hash);
 137
 138/**
 139 * qht_reset - reset a QHT
 140 * @ht: QHT to be reset
 141 *
 142 * All entries in the hash table are reset. No resizing is performed.
 143 *
 144 * If concurrent readers may exist, the objects pointed to by the hash table
 145 * must remain valid for the existing RCU grace period -- see qht_remove().
 146 * See also: qht_reset_size()
 147 */
 148void qht_reset(struct qht *ht);
 149
 150/**
 151 * qht_reset_size - reset and resize a QHT
 152 * @ht: QHT to be reset and resized
 153 * @n_elems: number of entries the resized hash table should be optimized for.
 154 *
 155 * Returns true if the resize was necessary and therefore performed.
 156 * Returns false otherwise.
 157 *
 158 * If concurrent readers may exist, the objects pointed to by the hash table
 159 * must remain valid for the existing RCU grace period -- see qht_remove().
 160 * See also: qht_reset(), qht_resize().
 161 */
 162bool qht_reset_size(struct qht *ht, size_t n_elems);
 163
 164/**
 165 * qht_resize - resize a QHT
 166 * @ht: QHT to be resized
 167 * @n_elems: number of entries the resized hash table should be optimized for
 168 *
 169 * Returns true on success.
 170 * Returns false if the resize was not necessary and therefore not performed.
 171 * See also: qht_reset_size().
 172 */
 173bool qht_resize(struct qht *ht, size_t n_elems);
 174
 175/**
 176 * qht_iter - Iterate over a QHT
 177 * @ht: QHT to be iterated over
 178 * @func: function to be called for each entry in QHT
 179 * @userp: additional pointer to be passed to @func
 180 *
 181 * Each time it is called, user-provided @func is passed a pointer-hash pair,
 182 * plus @userp.
 183 *
 184 * Note: @ht cannot be accessed from @func
 185 * See also: qht_iter_remove()
 186 */
 187void qht_iter(struct qht *ht, qht_iter_func_t func, void *userp);
 188
 189/**
 190 * qht_iter_remove - Iterate over a QHT, optionally removing entries
 191 * @ht: QHT to be iterated over
 192 * @func: function to be called for each entry in QHT
 193 * @userp: additional pointer to be passed to @func
 194 *
 195 * Each time it is called, user-provided @func is passed a pointer-hash pair,
 196 * plus @userp. If @func returns true, the pointer-hash pair is removed.
 197 *
 198 * Note: @ht cannot be accessed from @func
 199 * See also: qht_iter()
 200 */
 201void qht_iter_remove(struct qht *ht, qht_iter_bool_func_t func, void *userp);
 202
 203/**
 204 * qht_statistics_init - Gather statistics from a QHT
 205 * @ht: QHT to gather statistics from
 206 * @stats: pointer to a &struct qht_stats to be filled in
 207 *
 208 * Does NOT need to be called under an RCU read-critical section,
 209 * since it does not dereference any pointers stored in the hash table.
 210 *
 211 * When done with @stats, pass the struct to qht_statistics_destroy().
 212 * Failing to do this will leak memory.
 213 */
 214void qht_statistics_init(const struct qht *ht, struct qht_stats *stats);
 215
 216/**
 217 * qht_statistics_destroy - Destroy a &struct qht_stats
 218 * @stats: &struct qht_stats to be destroyed
 219 *
 220 * See also: qht_statistics_init().
 221 */
 222void qht_statistics_destroy(struct qht_stats *stats);
 223
 224#endif /* QEMU_QHT_H */
 225