Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
steam
systemd
Commits
a56f19c4
Commit
a56f19c4
authored
Apr 14, 2013
by
Lennart Poettering
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
kdbus: generare bloom filters properly for messages we send
parent
2404302e
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
615 additions
and
14 deletions
+615
-14
Makefile.am
Makefile.am
+6
-2
src/libsystemd-bus/bus-bloom.c
src/libsystemd-bus/bus-bloom.c
+93
-0
src/libsystemd-bus/bus-bloom.h
src/libsystemd-bus/bus-bloom.h
+30
-0
src/libsystemd-bus/bus-internal.c
src/libsystemd-bus/bus-internal.c
+13
-0
src/libsystemd-bus/bus-internal.h
src/libsystemd-bus/bus-internal.h
+1
-2
src/libsystemd-bus/bus-kernel.c
src/libsystemd-bus/bus-kernel.c
+84
-9
src/libsystemd-bus/test-bus-kernel.c
src/libsystemd-bus/test-bus-kernel.c
+1
-1
src/shared/MurmurHash3.c
src/shared/MurmurHash3.c
+349
-0
src/shared/MurmurHash3.h
src/shared/MurmurHash3.h
+38
-0
No files found.
Makefile.am
View file @
a56f19c4
...
...
@@ -680,7 +680,9 @@ libsystemd_shared_la_SOURCES = \
src/shared/calendarspec.h
\
src/shared/fileio.c
\
src/shared/fileio.h
\
src/shared/output-mode.h
src/shared/output-mode.h
\
src/shared/MurmurHash3.c
\
src/shared/MurmurHash3.h
#-------------------------------------------------------------------------------
noinst_LTLIBRARIES
+=
\
...
...
@@ -1711,7 +1713,9 @@ libsystemd_bus_la_SOURCES = \
src/libsystemd-bus/bus-type.c
\
src/libsystemd-bus/bus-type.h
\
src/libsystemd-bus/bus-match.c
\
src/libsystemd-bus/bus-match.h
src/libsystemd-bus/bus-match.h
\
src/libsystemd-bus/bus-bloom.c
\
src/libsystemd-bus/bus-bloom.h
libsystemd_bus_la_LIBADD
=
\
libsystemd-id128-internal.la
\
...
...
src/libsystemd-bus/bus-bloom.c
0 → 100644
View file @
a56f19c4
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2013 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "util.h"
#include "MurmurHash3.h"
#include "bus-bloom.h"
static
inline
void
set_bit
(
uint64_t
filter
[],
unsigned
b
)
{
filter
[
b
>>
6
]
|=
1ULL
<<
(
b
&
63
);
}
void
bloom_add_data
(
uint64_t
filter
[
BLOOM_SIZE
/
8
],
const
void
*
data
,
size_t
n
)
{
uint16_t
hash
[
8
];
unsigned
k
=
0
;
/*
* Our bloom filter has the following parameters:
*
* m=512 (bits in the filter)
* k=8 (hash functions)
*
* We calculate a single 128bit MurmurHash value of which we
* use 8 parts of 9 bits as individual hash functions.
*
*/
MurmurHash3_x64_128
(
data
,
n
,
0
,
hash
);
assert_cc
(
BLOOM_SIZE
*
8
==
512
);
for
(
k
=
0
;
k
<
ELEMENTSOF
(
hash
);
k
++
)
set_bit
(
filter
,
hash
[
k
]
&
511
);
}
void
bloom_add_pair
(
uint64_t
filter
[
BLOOM_SIZE
/
8
],
const
char
*
a
,
const
char
*
b
)
{
size_t
n
;
char
*
c
;
assert
(
filter
);
assert
(
a
);
assert
(
b
);
n
=
strlen
(
a
)
+
1
+
strlen
(
b
);
c
=
alloca
(
n
+
1
);
strcpy
(
stpcpy
(
stpcpy
(
c
,
a
),
":"
),
b
);
bloom_add_data
(
filter
,
c
,
n
);
}
void
bloom_add_prefixes
(
uint64_t
filter
[
BLOOM_SIZE
/
8
],
const
char
*
a
,
const
char
*
b
,
char
sep
)
{
size_t
n
;
char
*
c
,
*
p
;
assert
(
filter
);
assert
(
a
);
assert
(
b
);
n
=
strlen
(
a
)
+
1
+
strlen
(
b
);
c
=
alloca
(
n
+
1
);
p
=
stpcpy
(
stpcpy
(
c
,
a
),
":"
);
strcpy
(
p
,
b
);
for
(;;)
{
char
*
e
;
e
=
strrchr
(
p
,
sep
);
if
(
!
e
||
e
==
p
)
break
;
*
e
=
0
;
bloom_add_data
(
filter
,
c
,
e
-
c
);
}
}
src/libsystemd-bus/bus-bloom.h
0 → 100644
View file @
a56f19c4
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
#pragma once
/***
This file is part of systemd.
Copyright 2013 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <sys/types.h>
#define BLOOM_SIZE 64
void
bloom_add_data
(
uint64_t
filter
[
BLOOM_SIZE
/
8
],
const
void
*
data
,
size_t
n
);
void
bloom_add_pair
(
uint64_t
filter
[
BLOOM_SIZE
/
8
],
const
char
*
a
,
const
char
*
b
);
void
bloom_add_prefixes
(
uint64_t
filter
[
BLOOM_SIZE
/
8
],
const
char
*
a
,
const
char
*
b
,
char
sep
);
src/libsystemd-bus/bus-internal.c
View file @
a56f19c4
...
...
@@ -241,3 +241,16 @@ int bus_message_type_from_string(const char *s, uint8_t *u) {
return
0
;
}
const
char
*
bus_message_type_to_string
(
uint8_t
u
)
{
if
(
u
==
SD_BUS_MESSAGE_TYPE_SIGNAL
)
return
"signal"
;
else
if
(
u
==
SD_BUS_MESSAGE_TYPE_METHOD_CALL
)
return
"method_call"
;
else
if
(
u
==
SD_BUS_MESSAGE_TYPE_METHOD_ERROR
)
return
"error"
;
else
if
(
u
==
SD_BUS_MESSAGE_TYPE_METHOD_RETURN
)
return
"method_return"
;
else
return
NULL
;
}
src/libsystemd-bus/bus-internal.h
View file @
a56f19c4
...
...
@@ -150,8 +150,6 @@ struct sd_bus {
uint64_t
hello_serial
;
unsigned
iteration_counter
;
uint64_t
bloom_size
;
};
static
inline
void
bus_unrefp
(
sd_bus
**
b
)
{
...
...
@@ -191,6 +189,7 @@ bool namespace_simple_pattern(const char *pattern, const char *value);
bool
path_simple_pattern
(
const
char
*
pattern
,
const
char
*
value
);
int
bus_message_type_from_string
(
const
char
*
s
,
uint8_t
*
u
);
const
char
*
bus_message_type_to_string
(
uint8_t
u
);
#define error_name_is_valid interface_name_is_valid
...
...
src/libsystemd-bus/bus-kernel.c
View file @
a56f19c4
...
...
@@ -30,6 +30,7 @@
#include "bus-internal.h"
#include "bus-message.h"
#include "bus-kernel.h"
#include "bus-bloom.h"
#define KDBUS_MSG_FOREACH_DATA(d, k) \
for ((d) = (k)->data; \
...
...
@@ -80,17 +81,83 @@ static void append_destination(struct kdbus_msg_data **d, const char *s, size_t
*
d
=
(
struct
kdbus_msg_data
*
)
((
uint8_t
*
)
*
d
+
(
*
d
)
->
size
);
}
static
void
append_bloom
(
struct
kdbus_msg_data
**
d
,
const
void
*
p
,
size_t
length
)
{
static
void
*
append_bloom
(
struct
kdbus_msg_data
**
d
,
size_t
length
)
{
void
*
r
;
assert
(
d
);
assert
(
p
);
*
d
=
ALIGN8_PTR
(
*
d
);
(
*
d
)
->
size
=
offsetof
(
struct
kdbus_msg_data
,
data
)
+
length
;
(
*
d
)
->
type
=
KDBUS_MSG_BLOOM
;
memcpy
(
(
*
d
)
->
data
,
p
,
length
)
;
r
=
(
*
d
)
->
data
;
*
d
=
(
struct
kdbus_msg_data
*
)
((
uint8_t
*
)
*
d
+
(
*
d
)
->
size
);
return
r
;
}
static
int
bus_message_setup_bloom
(
sd_bus_message
*
m
,
void
*
bloom
)
{
unsigned
i
;
int
r
;
assert
(
m
);
assert
(
bloom
);
memset
(
bloom
,
0
,
BLOOM_SIZE
);
bloom_add_pair
(
bloom
,
"message-type"
,
bus_message_type_to_string
(
m
->
header
->
type
));
if
(
m
->
interface
)
bloom_add_pair
(
bloom
,
"interface"
,
m
->
interface
);
if
(
m
->
member
)
bloom_add_pair
(
bloom
,
"member"
,
m
->
member
);
if
(
m
->
path
)
{
bloom_add_pair
(
bloom
,
"path"
,
m
->
path
);
bloom_add_prefixes
(
bloom
,
"path-slash-prefix"
,
m
->
path
,
'/'
);
}
r
=
sd_bus_message_rewind
(
m
,
true
);
if
(
r
<
0
)
return
r
;
for
(
i
=
0
;
i
<
64
;
i
++
)
{
char
type
;
const
char
*
t
;
char
buf
[
sizeof
(
"arg"
)
-
1
+
2
+
sizeof
(
"-slash-prefix"
)];
char
*
e
;
r
=
sd_bus_message_peek_type
(
m
,
&
type
,
NULL
);
if
(
r
<
0
)
return
r
;
if
(
type
!=
SD_BUS_TYPE_STRING
&&
type
!=
SD_BUS_TYPE_OBJECT_PATH
&&
type
!=
SD_BUS_TYPE_SIGNATURE
)
break
;
r
=
sd_bus_message_read_basic
(
m
,
type
,
&
t
);
if
(
r
<
0
)
return
r
;
e
=
stpcpy
(
buf
,
"arg"
);
if
(
i
<
10
)
*
(
e
++
)
=
'0'
+
i
;
else
{
*
(
e
++
)
=
'0'
+
(
i
/
10
);
*
(
e
++
)
=
'0'
+
(
i
%
10
);
}
*
e
=
0
;
bloom_add_pair
(
bloom
,
buf
,
t
);
strcpy
(
e
,
"-dot-prefix"
);
bloom_add_prefixes
(
bloom
,
buf
,
t
,
'.'
);
strcpy
(
e
,
"-slash-prefix"
);
bloom_add_prefixes
(
bloom
,
buf
,
t
,
'/'
);
}
return
0
;
}
static
int
bus_message_setup_kmsg
(
sd_bus
*
b
,
sd_bus_message
*
m
)
{
...
...
@@ -122,7 +189,7 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
sz
+=
3
*
ALIGN8
(
offsetof
(
struct
kdbus_msg_data
,
vec
)
+
sizeof
(
struct
kdbus_vec
));
/* Add space for bloom filter */
sz
+=
ALIGN8
(
offsetof
(
struct
kdbus_msg_data
,
data
)
+
b
->
bloom_size
);
sz
+=
ALIGN8
(
offsetof
(
struct
kdbus_msg_data
,
data
)
+
BLOOM_SIZE
);
/* Add in well-known destination header */
if
(
well_known
)
{
...
...
@@ -164,9 +231,13 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
void
*
p
;
/* For now, let's add a mask all bloom filter */
p
=
alloca
(
b
->
bloom_size
);
memset
(
p
,
0xFF
,
b
->
bloom_size
);
append_bloom
(
&
d
,
p
,
b
->
bloom_size
);
p
=
append_bloom
(
&
d
,
BLOOM_SIZE
);
r
=
bus_message_setup_bloom
(
m
,
p
);
if
(
r
<
0
)
{
free
(
m
->
kdbus
);
m
->
kdbus
=
NULL
;
return
-
r
;
}
}
m
->
kdbus
->
size
=
(
uint8_t
*
)
d
-
(
uint8_t
*
)
m
->
kdbus
;
...
...
@@ -207,10 +278,12 @@ int bus_kernel_take_fd(sd_bus *b) {
hello
.
conn_flags
>
0xFFFFFFFFULL
)
return
-
ENOTSUP
;
if
(
hello
.
bloom_size
!=
BLOOM_SIZE
)
return
-
ENOTSUP
;
if
(
asprintf
(
&
b
->
unique_name
,
":1.%llu"
,
(
unsigned
long
long
)
hello
.
id
)
<
0
)
return
-
ENOMEM
;
b
->
bloom_size
=
hello
.
bloom_size
;
b
->
is_kernel
=
true
;
b
->
bus_client
=
true
;
...
...
@@ -479,7 +552,9 @@ int bus_kernel_create(const char *name, char **s) {
make
->
size
=
offsetof
(
struct
kdbus_cmd_bus_make
,
name
)
+
strlen
(
make
->
name
)
+
1
;
make
->
flags
=
KDBUS_ACCESS_WORLD
|
KDBUS_POLICY_OPEN
;
make
->
bus_flags
=
0
;
make
->
bloom_size
=
16
;
make
->
bloom_size
=
BLOOM_SIZE
;
assert_cc
(
BLOOM_SIZE
%
8
==
0
);
p
=
strjoin
(
"/dev/kdbus/"
,
make
->
name
,
"/bus"
,
NULL
);
if
(
!
p
)
...
...
src/libsystemd-bus/test-bus-kernel.c
View file @
a56f19c4
...
...
@@ -71,7 +71,7 @@ int main(int argc, char *argv[]) {
printf
(
"unique b: %s
\n
"
,
ub
);
r
=
sd_bus_emit_signal
(
a
,
"/foo"
,
"waldo.com"
,
"Piep"
,
"s"
,
"I am a string"
);
r
=
sd_bus_emit_signal
(
a
,
"/foo
/bar/waldo
"
,
"waldo.com"
,
"Piep"
,
"s
ss
"
,
"I am a string"
,
"/this/is/a/path"
,
"and.this.a.domain.name"
);
assert_se
(
r
>=
0
);
r
=
sd_bus_process
(
b
,
&
m
);
...
...
src/shared/MurmurHash3.c
0 → 100644
View file @
a56f19c4
//-----------------------------------------------------------------------------
// MurmurHash3 was written by Austin Appleby, and is placed in the public
// domain. The author hereby disclaims copyright to this source code.
// Note - The x86 and x64 versions do _not_ produce the same results, as the
// algorithms are optimized for their respective platforms. You can still
// compile and run any of them on any platform, but your performance with the
// non-native version will be less than optimal.
#include "MurmurHash3.h"
//-----------------------------------------------------------------------------
// Platform-specific functions and macros
// Microsoft Visual Studio
#if defined(_MSC_VER)
#define FORCE_INLINE __forceinline
#include <stdlib.h>
#define ROTL32(x,y) _rotl(x,y)
#define ROTL64(x,y) _rotl64(x,y)
#define BIG_CONSTANT(x) (x)
// Other compilers
#else // defined(_MSC_VER)
#define FORCE_INLINE __attribute__((always_inline))
static
inline
uint32_t
rotl32
(
uint32_t
x
,
int8_t
r
)
{
return
(
x
<<
r
)
|
(
x
>>
(
32
-
r
));
}
static
inline
uint64_t
rotl64
(
uint64_t
x
,
int8_t
r
)
{
return
(
x
<<
r
)
|
(
x
>>
(
64
-
r
));
}
#define ROTL32(x,y) rotl32(x,y)
#define ROTL64(x,y) rotl64(x,y)
#define BIG_CONSTANT(x) (x##LLU)
#endif // !defined(_MSC_VER)
//-----------------------------------------------------------------------------
// Block read - if your platform needs to do endian-swapping or can only
// handle aligned reads, do the conversion here
static
FORCE_INLINE
uint32_t
getblock32
(
const
uint32_t
*
p
,
int
i
)
{
return
p
[
i
];
}
static
FORCE_INLINE
uint64_t
getblock64
(
const
uint64_t
*
p
,
int
i
)
{
return
p
[
i
];
}
//-----------------------------------------------------------------------------
// Finalization mix - force all bits of a hash block to avalanche
static
FORCE_INLINE
uint32_t
fmix32
(
uint32_t
h
)
{
h
^=
h
>>
16
;
h
*=
0x85ebca6b
;
h
^=
h
>>
13
;
h
*=
0xc2b2ae35
;
h
^=
h
>>
16
;
return
h
;
}
//----------
static
FORCE_INLINE
uint64_t
fmix64
(
uint64_t
k
)
{
k
^=
k
>>
33
;
k
*=
BIG_CONSTANT
(
0xff51afd7ed558ccd
);
k
^=
k
>>
33
;
k
*=
BIG_CONSTANT
(
0xc4ceb9fe1a85ec53
);
k
^=
k
>>
33
;
return
k
;
}
//-----------------------------------------------------------------------------
void
MurmurHash3_x86_32
(
const
void
*
key
,
size_t
len
,
uint32_t
seed
,
void
*
out
)
{
const
uint8_t
*
data
=
(
const
uint8_t
*
)
key
;
const
int
nblocks
=
len
/
4
;
uint32_t
h1
=
seed
;
const
uint32_t
c1
=
0xcc9e2d51
;
const
uint32_t
c2
=
0x1b873593
;
const
uint8_t
*
tail
;
uint32_t
k1
;
//----------
// body
const
uint32_t
*
blocks
=
(
const
uint32_t
*
)(
data
+
nblocks
*
4
);
for
(
int
i
=
-
nblocks
;
i
;
i
++
)
{
k1
=
getblock32
(
blocks
,
i
);
k1
*=
c1
;
k1
=
ROTL32
(
k1
,
15
);
k1
*=
c2
;
h1
^=
k1
;
h1
=
ROTL32
(
h1
,
13
);
h1
=
h1
*
5
+
0xe6546b64
;
}
//----------
// tail
tail
=
(
const
uint8_t
*
)(
data
+
nblocks
*
4
);
k1
=
0
;
switch
(
len
&
3
)
{
case
3
:
k1
^=
tail
[
2
]
<<
16
;
case
2
:
k1
^=
tail
[
1
]
<<
8
;
case
1
:
k1
^=
tail
[
0
];
k1
*=
c1
;
k1
=
ROTL32
(
k1
,
15
);
k1
*=
c2
;
h1
^=
k1
;
};
//----------
// finalization
h1
^=
len
;
h1
=
fmix32
(
h1
);
*
(
uint32_t
*
)
out
=
h1
;
}
//-----------------------------------------------------------------------------
void
MurmurHash3_x86_128
(
const
void
*
key
,
const
size_t
len
,
uint32_t
seed
,
void
*
out
)
{
const
uint8_t
*
data
=
(
const
uint8_t
*
)
key
;
const
int
nblocks
=
len
/
16
;
uint32_t
h1
=
seed
;
uint32_t
h2
=
seed
;
uint32_t
h3
=
seed
;
uint32_t
h4
=
seed
;
const
uint32_t
c1
=
0x239b961b
;
const
uint32_t
c2
=
0xab0e9789
;
const
uint32_t
c3
=
0x38b34ae5
;
const
uint32_t
c4
=
0xa1e38b93
;
const
uint8_t
*
tail
;
uint32_t
k1
;
uint32_t
k2
;
uint32_t
k3
;
uint32_t
k4
;
//----------
// body
const
uint32_t
*
blocks
=
(
const
uint32_t
*
)(
data
+
nblocks
*
16
);
for
(
int
i
=
-
nblocks
;
i
;
i
++
)
{
k1
=
getblock32
(
blocks
,
i
*
4
+
0
);
k2
=
getblock32
(
blocks
,
i
*
4
+
1
);
k3
=
getblock32
(
blocks
,
i
*
4
+
2
);
k4
=
getblock32
(
blocks
,
i
*
4
+
3
);
k1
*=
c1
;
k1
=
ROTL32
(
k1
,
15
);
k1
*=
c2
;
h1
^=
k1
;
h1
=
ROTL32
(
h1
,
19
);
h1
+=
h2
;
h1
=
h1
*
5
+
0x561ccd1b
;
k2
*=
c2
;
k2
=
ROTL32
(
k2
,
16
);
k2
*=
c3
;
h2
^=
k2
;
h2
=
ROTL32
(
h2
,
17
);
h2
+=
h3
;
h2
=
h2
*
5
+
0x0bcaa747
;
k3
*=
c3
;
k3
=
ROTL32
(
k3
,
17
);
k3
*=
c4
;
h3
^=
k3
;
h3
=
ROTL32
(
h3
,
15
);
h3
+=
h4
;
h3
=
h3
*
5
+
0x96cd1c35
;
k4
*=
c4
;
k4
=
ROTL32
(
k4
,
18
);
k4
*=
c1
;
h4
^=
k4
;
h4
=
ROTL32
(
h4
,
13
);
h4
+=
h1
;
h4
=
h4
*
5
+
0x32ac3b17
;
}
//----------
// tail
tail
=
(
const
uint8_t
*
)(
data
+
nblocks
*
16
);
k1
=
0
;
k2
=
0
;
k3
=
0
;
k4
=
0
;
switch
(
len
&
15
)
{
case
15
:
k4
^=
tail
[
14
]
<<
16
;
case
14
:
k4
^=
tail
[
13
]
<<
8
;
case
13
:
k4
^=
tail
[
12
]
<<
0
;
k4
*=
c4
;
k4
=
ROTL32
(
k4
,
18
);
k4
*=
c1
;
h4
^=
k4
;
case
12
:
k3
^=
tail
[
11
]
<<
24
;
case
11
:
k3
^=
tail
[
10
]
<<
16
;
case
10
:
k3
^=
tail
[
9
]
<<
8
;
case
9
:
k3
^=
tail
[
8
]
<<
0
;
k3
*=
c3
;
k3
=
ROTL32
(
k3
,
17
);
k3
*=
c4
;
h3
^=
k3
;
case
8
:
k2
^=
tail
[
7
]
<<
24
;
case
7
:
k2
^=
tail
[
6
]
<<
16
;
case
6
:
k2
^=
tail
[
5
]
<<
8
;
case
5
:
k2
^=
tail
[
4
]
<<
0
;
k2
*=
c2
;
k2
=
ROTL32
(
k2
,
16
);
k2
*=
c3
;
h2
^=
k2
;
case
4
:
k1
^=
tail
[
3
]
<<
24
;
case
3
:
k1
^=
tail
[
2
]
<<
16
;
case
2
:
k1
^=
tail
[
1
]
<<
8
;
case
1
:
k1
^=
tail
[
0
]
<<
0
;
k1
*=
c1
;
k1
=
ROTL32
(
k1
,
15
);
k1
*=
c2
;
h1
^=
k1
;
};
//----------
// finalization
h1
^=
len
;
h2
^=
len
;
h3
^=
len
;
h4
^=
len
;
h1
+=
h2
;
h1
+=
h3
;
h1
+=
h4
;
h2
+=
h1
;
h3
+=
h1
;
h4
+=
h1
;
h1
=
fmix32
(
h1
);
h2
=
fmix32
(
h2
);
h3
=
fmix32
(
h3
);
h4
=
fmix32
(
h4
);
h1
+=
h2
;
h1
+=
h3
;
h1
+=
h4
;
h2
+=
h1
;
h3
+=
h1
;
h4
+=
h1
;
((
uint32_t
*
)
out
)[
0
]
=
h1
;
((
uint32_t
*
)
out
)[
1
]
=
h2
;
((
uint32_t
*
)
out
)[
2
]
=
h3
;
((
uint32_t
*
)
out
)[
3
]
=
h4
;
}
//-----------------------------------------------------------------------------
void
MurmurHash3_x64_128
(
const
void
*
key
,
const
size_t
len
,
const
uint32_t
seed
,
void
*
out
)
{
const
uint8_t
*
data
=
(
const
uint8_t
*
)
key
;
const
int
nblocks
=
len
/
16
;
uint64_t
h1
=
seed
;
uint64_t
h2
=
seed
;
const
uint64_t
c1
=
BIG_CONSTANT
(
0x87c37b91114253d5
);
const
uint64_t
c2
=
BIG_CONSTANT
(
0x4cf5ad432745937f
);
const
uint8_t
*
tail
;
uint64_t
k1
;
uint64_t
k2
;
//----------
// body