diff options
| author | Quentin Young <qlyoung@nvidia.com> | 2020-09-02 16:02:55 -0400 |
|---|---|---|
| committer | Quentin Young <qlyoung@nvidia.com> | 2020-09-02 16:54:41 -0400 |
| commit | e6464fdc184e4b0a4032286c8fae245dcdb03d8f (patch) | |
| tree | e08ad3607c4046c5f83bc3d32f4f4c914a51559b /lib/hash.c | |
| parent | e9faf4be72294fccd9f7bd21b62473d408c80a37 (diff) | |
lib: remove overflow arithmetic from hash stats
Signed values get converted to unsigned for addition, so when the value
to adjust a stats variable for hash tables was negative this resulted in
overflow arithmetic, which we generally don't want.
Signed-off-by: Quentin Young <qlyoung@nvidia.com>
Diffstat (limited to 'lib/hash.c')
| -rw-r--r-- | lib/hash.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/lib/hash.c b/lib/hash.c index 7f8a237047..85982774ac 100644 --- a/lib/hash.c +++ b/lib/hash.c @@ -77,9 +77,20 @@ void *hash_alloc_intern(void *arg) return arg; } +/* + * ssq = ssq + (new^2 - old^2) + * = ssq + ((new + old) * (new - old)) + */ #define hash_update_ssq(hz, old, new) \ - atomic_fetch_add_explicit(&hz->stats.ssq, (new + old) * (new - old), \ - memory_order_relaxed); + do { \ + int _adjust = (new + old) * (new - old); \ + if (_adjust < 0) \ + atomic_fetch_sub_explicit(&hz->stats.ssq, -_adjust, \ + memory_order_relaxed); \ + else \ + atomic_fetch_add_explicit(&hz->stats.ssq, _adjust, \ + memory_order_relaxed); \ + } while (0) /* Expand hash if the chain length exceeds the threshold. */ static void hash_expand(struct hash *hash) |
