hc
2024-05-10 9999e48639b3cecb08ffb37358bcba3b48161b29
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2019 Facebook
#include <features.h>
 
typedef unsigned int u32;
 
static __always_inline u32 rol32(u32 word, unsigned int shift)
{
   return (word << shift) | (word >> ((-shift) & 31));
}
 
#define __jhash_mix(a, b, c)            \
{                        \
   a -= c;  a ^= rol32(c, 4);  c += b;    \
   b -= a;  b ^= rol32(a, 6);  a += c;    \
   c -= b;  c ^= rol32(b, 8);  b += a;    \
   a -= c;  a ^= rol32(c, 16); c += b;    \
   b -= a;  b ^= rol32(a, 19); a += c;    \
   c -= b;  c ^= rol32(b, 4);  b += a;    \
}
 
#define __jhash_final(a, b, c)            \
{                        \
   c ^= b; c -= rol32(b, 14);        \
   a ^= c; a -= rol32(c, 11);        \
   b ^= a; b -= rol32(a, 25);        \
   c ^= b; c -= rol32(b, 16);        \
   a ^= c; a -= rol32(c, 4);        \
   b ^= a; b -= rol32(a, 14);        \
   c ^= b; c -= rol32(b, 24);        \
}
 
#define JHASH_INITVAL        0xdeadbeef
 
static ATTR
u32 jhash(const void *key, u32 length, u32 initval)
{
   u32 a, b, c;
   const unsigned char *k = key;
 
   a = b = c = JHASH_INITVAL + length + initval;
 
   while (length > 12) {
       a += *(volatile u32 *)(k);
       b += *(volatile u32 *)(k + 4);
       c += *(volatile u32 *)(k + 8);
       __jhash_mix(a, b, c);
       length -= 12;
       k += 12;
   }
   switch (length) {
   case 12: c += (u32)k[11]<<24;
   case 11: c += (u32)k[10]<<16;
   case 10: c += (u32)k[9]<<8;
   case 9:  c += k[8];
   case 8:  b += (u32)k[7]<<24;
   case 7:  b += (u32)k[6]<<16;
   case 6:  b += (u32)k[5]<<8;
   case 5:  b += k[4];
   case 4:  a += (u32)k[3]<<24;
   case 3:  a += (u32)k[2]<<16;
   case 2:  a += (u32)k[1]<<8;
   case 1:  a += k[0];
        c ^= a;
        __jhash_final(a, b, c);
   case 0: /* Nothing left to add */
       break;
   }
 
   return c;
}