Compare commits

..

1 Commits

Author SHA1 Message Date
Aydın Mercan
523b9a2196 add isc/bit.h
The `<isc/bit.h>` header is a GNU C11 compatible version of C23's
`<stdbit.h>`.

It currently uses either `<stdbit.h>` or the equivilent compiler
builtins. However, the generic `__builtin_ctzg` and `__builtin_ctlz`
builtins are not available in every compiler version and thus falls
back to manually selecting from type.

Furthermore, the ctz fallback has been removed since `__builtin_ctzll`
has been used for a while directly without any compilation issues from
users. Thus, we can also require `__builtin_ctz`.
2025-03-21 21:59:17 +03:00
11 changed files with 280 additions and 131 deletions

View File

@@ -1027,21 +1027,6 @@ AC_LINK_IFELSE(
[AC_MSG_RESULT([no])
])
#
# Check for __builtin_clz
#
AC_MSG_CHECKING([compiler support for __builtin_clz])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[]],
[[return (__builtin_clz(0xff) == 24 ? 1 : 0);]]
)],
[AC_MSG_RESULT([yes])
AC_DEFINE(HAVE_BUILTIN_CLZ, 1, [Define to 1 if the compiler supports __builtin_clz.])
],
[AC_MSG_RESULT([no])]
)
#
# Check for __builtin_*_overflow
#
@@ -1083,6 +1068,80 @@ AC_LINK_IFELSE(
[AC_MSG_RESULT([no])
])
#
# Check for builtin bit utilities
#
AC_MSG_CHECKING([compiler support for __builtin_popcountg()])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[]],
[[return (__builtin_popcountg(1U << 8 | 1U) == 2 ? 1 : 0);]]
)],
[AC_MSG_RESULT([yes])
AC_DEFINE([HAVE_BUILTIN_POPCOUNTG], [1], [define if the compiler supports __builtin_popcountg().])
],
[AC_MSG_RESULT([no])
AC_MSG_CHECKING([compiler support for __builtin_popcount, __builting_popcountl, __builtin_popcountll()])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[]],
[[return (__builtin_popcount(1 << 8 | 1) + __builtin_popcountl(1 << 8 | 1) + __builtin_popcountl(1 << 8 | 1));]]
)],
[AC_MSG_RESULT([yes])
],
[AC_MSG_RESULT([no])
AC_MSG_FAILURE([__builtin_popcountg or __builting_popcount* functions are required, please fix your toolchain.])
])
])
AC_MSG_CHECKING([compiler support for __builtin_clzg()])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <stdint.h>]],
[[return (__builtin_clzg((uint32_t)0xff) == 24 ? 1 : 0);]]
)],
[AC_MSG_RESULT([yes])
AC_DEFINE([HAVE_BUILTIN_CLZG], [1], [define if the compiler supports __builtin_clzg().])
],
[AC_MSG_RESULT([no])
AC_MSG_CHECKING([compiler support for __builtin_clz, __builting_clzl, __builtin_clzll()])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[]],
[[return (__builtin_clz(1 << 8 | 1) + __builtin_clzl(1 << 8 | 1) + __builtin_clzl(1 << 8 | 1));]]
)],
[AC_MSG_RESULT([yes])
],
[AC_MSG_RESULT([no])
AC_MSG_FAILURE([__builtin_clzg or __builting_clz* functions are required, please fix your toolchain.])
])
])
AC_MSG_CHECKING([compiler support for __builtin_ctzg()])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <stdint.h>]],
[[return (__builtin_ctzg((uint32_t)0xff) == 24 ? 1 : 0);]]
)],
[AC_MSG_RESULT([yes])
AC_DEFINE([HAVE_BUILTIN_CTZG], [1], [define if the compiler supports __builtin_ctzg().])
],
[AC_MSG_RESULT([no])
AC_MSG_CHECKING([compiler support for __builtin_ctz, __builting_ctzl, __builtin_ctzll()])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[]],
[[return (__builtin_ctz(1 << 8 | 1) + __builtin_ctzl(1 << 8 | 1) + __builtin_ctzl(1 << 8 | 1));]]
)],
[AC_MSG_RESULT([yes])
],
[AC_MSG_RESULT([no])
AC_MSG_FAILURE([__builtin_ctzg or __builting_ctz* functions are required, please fix your toolchain.])
])
])
#
# Activate dnstap?
#

View File

@@ -19,6 +19,8 @@
#pragma once
#include <isc/bit.h>
#include <dns/qp.h>
/***********************************************************************
@@ -736,7 +738,7 @@ static inline dns_qpweight_t
branch_count_bitmap_before(dns_qpnode_t *n, dns_qpshift_t bit) {
uint64_t mask = (1ULL << bit) - 1 - TAG_MASK;
uint64_t bitmap = branch_index(n) & mask;
return (dns_qpweight_t)__builtin_popcountll(bitmap);
return (dns_qpweight_t)ISC_POPCOUNT(bitmap);
}
/*

View File

@@ -19,6 +19,7 @@
#include <stdlib.h>
#include <isc/async.h>
#include <isc/bit.h>
#include <isc/buffer.h>
#include <isc/log.h>
#include <isc/loop.h>
@@ -1074,45 +1075,6 @@ name2data(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
(void)dns_name_concatenate(&tmp_name, dns_rootname, trig_name);
}
#ifndef HAVE_BUILTIN_CLZ
/**
* \brief Count Leading Zeros: Find the location of the left-most set
* bit.
*/
static unsigned int
clz(dns_rpz_cidr_word_t w) {
unsigned int bit;
bit = DNS_RPZ_CIDR_WORD_BITS - 1;
if ((w & 0xffff0000) != 0) {
w >>= 16;
bit -= 16;
}
if ((w & 0xff00) != 0) {
w >>= 8;
bit -= 8;
}
if ((w & 0xf0) != 0) {
w >>= 4;
bit -= 4;
}
if ((w & 0xc) != 0) {
w >>= 2;
bit -= 2;
}
if ((w & 2) != 0) {
--bit;
}
return bit;
}
#endif /* ifndef HAVE_BUILTIN_CLZ */
/*
* Find the first differing bit in two keys (IP addresses).
*/
@@ -1132,11 +1094,7 @@ diff_keys(const dns_rpz_cidr_key_t *key1, dns_rpz_prefix_t prefix1,
for (i = 0; bit < maxbit; i++, bit += DNS_RPZ_CIDR_WORD_BITS) {
delta = key1->w[i] ^ key2->w[i];
if (delta != 0) {
#ifdef HAVE_BUILTIN_CLZ
bit += __builtin_clz(delta);
#else /* ifdef HAVE_BUILTIN_CLZ */
bit += clz(delta);
#endif /* ifdef HAVE_BUILTIN_CLZ */
bit += ISC_LEADING_ZEROS(delta);
break;
}
}

View File

@@ -398,7 +398,8 @@ fetch_callback_dnskey(void *arg) {
dns_fetchresponse_t *resp = (dns_fetchresponse_t *)arg;
dns_validator_t *val = resp->arg;
dns_rdataset_t *rdataset = &val->frdataset;
isc_result_t result = resp->result;
isc_result_t eresult = resp->result;
isc_result_t result;
/* Free resources which are not of interest. */
if (resp->node != NULL) {
@@ -420,7 +421,7 @@ fetch_callback_dnskey(void *arg) {
goto cleanup;
}
switch (result) {
switch (eresult) {
case ISC_R_SUCCESS:
case DNS_R_NCACHENXRRSET:
/*
@@ -428,13 +429,13 @@ fetch_callback_dnskey(void *arg) {
* RRset or a NODATA response.
*/
validator_log(val, ISC_LOG_DEBUG(3), "%s with trust %s",
result == ISC_R_SUCCESS ? "keyset"
: "NCACHENXRRSET",
eresult == ISC_R_SUCCESS ? "keyset"
: "NCACHENXRRSET",
dns_trust_totext(rdataset->trust));
/*
* Only extract the dst key if the keyset exists and is secure.
*/
if (result == ISC_R_SUCCESS &&
if (eresult == ISC_R_SUCCESS &&
rdataset->trust >= dns_trust_secure)
{
result = validate_helper_run(val,
@@ -446,7 +447,7 @@ fetch_callback_dnskey(void *arg) {
default:
validator_log(val, ISC_LOG_DEBUG(3),
"fetch_callback_dnskey: got %s",
isc_result_totext(result));
isc_result_totext(eresult));
result = DNS_R_BROKENCHAIN;
}
@@ -465,7 +466,8 @@ fetch_callback_ds(void *arg) {
dns_fetchresponse_t *resp = (dns_fetchresponse_t *)arg;
dns_validator_t *val = resp->arg;
dns_rdataset_t *rdataset = &val->frdataset;
isc_result_t result = resp->result;
isc_result_t eresult = resp->result;
isc_result_t result;
bool trustchain;
/*
@@ -495,7 +497,7 @@ fetch_callback_ds(void *arg) {
}
if (trustchain) {
switch (result) {
switch (eresult) {
case ISC_R_SUCCESS:
/*
* We looked for a DS record as part of
@@ -518,18 +520,18 @@ fetch_callback_ds(void *arg) {
*/
validator_log(val, ISC_LOG_DEBUG(3),
"falling back to insecurity proof (%s)",
isc_result_totext(result));
isc_result_totext(eresult));
result = proveunsecure(val, false, false);
break;
default:
validator_log(val, ISC_LOG_DEBUG(3),
"fetch_callback_ds: got %s",
isc_result_totext(result));
isc_result_totext(eresult));
result = DNS_R_BROKENCHAIN;
break;
}
} else {
switch (result) {
switch (eresult) {
case DNS_R_NXDOMAIN:
case DNS_R_NCACHENXDOMAIN:
/*
@@ -552,7 +554,7 @@ fetch_callback_ds(void *arg) {
case DNS_R_NXRRSET:
case DNS_R_NCACHENXRRSET:
if (isdelegation(resp->foundname, &val->frdataset,
result))
eresult))
{
/*
* Failed to find a DS while trying to prove
@@ -573,7 +575,7 @@ fetch_callback_ds(void *arg) {
default:
validator_log(val, ISC_LOG_DEBUG(3),
"fetch_callback_ds: got %s",
isc_result_totext(result));
isc_result_totext(eresult));
result = DNS_R_BROKENCHAIN;
}
}
@@ -595,8 +597,7 @@ validator_callback_dnskey(void *arg) {
dns_validator_t *val = subvalidator->parent;
isc_result_t result = subvalidator->result;
dns_validator_shutdown(subvalidator);
dns_validator_detach(&val->subvalidator);
val->subvalidator = NULL;
if (CANCELED(val) || CANCELING(val)) {
result = ISC_R_CANCELED;
@@ -633,6 +634,9 @@ validator_callback_dnskey(void *arg) {
}
cleanup:
dns_validator_detach(&subvalidator->parent);
dns_validator_shutdown(subvalidator);
dns_validator_detach(&subvalidator);
validate_async_done(val, result);
}
@@ -647,8 +651,7 @@ validator_callback_ds(void *arg) {
dns_validator_t *val = subvalidator->parent;
isc_result_t result = subvalidator->result;
dns_validator_shutdown(val->subvalidator);
dns_validator_detach(&val->subvalidator);
val->subvalidator = NULL;
if (CANCELED(val) || CANCELING(val)) {
result = ISC_R_CANCELED;
@@ -693,6 +696,9 @@ validator_callback_ds(void *arg) {
}
cleanup:
dns_validator_detach(&subvalidator->parent);
dns_validator_shutdown(subvalidator);
dns_validator_detach(&subvalidator);
validate_async_done(val, result);
}
@@ -705,12 +711,12 @@ static void
validator_callback_cname(void *arg) {
dns_validator_t *subvalidator = (dns_validator_t *)arg;
dns_validator_t *val = subvalidator->parent;
isc_result_t result = subvalidator->result;
isc_result_t result;
isc_result_t eresult = subvalidator->result;
INSIST((val->attributes & VALATTR_INSECURITY) != 0);
dns_validator_shutdown(val->subvalidator);
dns_validator_detach(&val->subvalidator);
val->subvalidator = NULL;
if (CANCELED(val) || CANCELING(val)) {
result = ISC_R_CANCELED;
@@ -718,21 +724,24 @@ validator_callback_cname(void *arg) {
}
validator_log(val, ISC_LOG_DEBUG(3), "in validator_callback_cname");
if (result == ISC_R_SUCCESS) {
if (eresult == ISC_R_SUCCESS) {
validator_log(val, ISC_LOG_DEBUG(3), "cname with trust %s",
dns_trust_totext(val->frdataset.trust));
result = proveunsecure(val, false, true);
} else {
if (result != DNS_R_BROKENCHAIN) {
if (eresult != DNS_R_BROKENCHAIN) {
expire_rdatasets(val);
}
validator_log(val, ISC_LOG_DEBUG(3),
"validator_callback_cname: got %s",
isc_result_totext(result));
isc_result_totext(eresult));
result = DNS_R_BROKENCHAIN;
}
cleanup:
dns_validator_detach(&subvalidator->parent);
dns_validator_shutdown(subvalidator);
dns_validator_detach(&subvalidator);
validate_async_done(val, result);
}
@@ -747,13 +756,12 @@ static void
validator_callback_nsec(void *arg) {
dns_validator_t *subvalidator = (dns_validator_t *)arg;
dns_validator_t *val = subvalidator->parent;
dns_name_t *name = subvalidator->name;
dns_rdataset_t *rdataset = subvalidator->rdataset;
isc_result_t result = subvalidator->result;
isc_result_t result;
isc_result_t eresult = subvalidator->result;
bool exists, data;
dns_validator_shutdown(subvalidator);
dns_validator_detach(&val->subvalidator);
val->subvalidator = NULL;
if (CANCELED(val) || CANCELING(val)) {
result = ISC_R_CANCELED;
@@ -761,7 +769,7 @@ validator_callback_nsec(void *arg) {
}
validator_log(val, ISC_LOG_DEBUG(3), "in validator_callback_nsec");
if (result == ISC_R_SUCCESS) {
if (eresult == ISC_R_SUCCESS) {
dns_name_t **proofs = val->proofs;
dns_name_t *wild = dns_fixedname_name(&val->wild);
@@ -769,7 +777,8 @@ validator_callback_nsec(void *arg) {
rdataset->trust == dns_trust_secure &&
(NEEDNODATA(val) || NEEDNOQNAME(val)) &&
!FOUNDNODATA(val) && !FOUNDNOQNAME(val) &&
dns_nsec_noexistnodata(val->type, val->name, name, rdataset,
dns_nsec_noexistnodata(val->type, val->name,
subvalidator->name, rdataset,
&exists, &data, wild, validator_log,
val) == ISC_R_SUCCESS)
{
@@ -777,7 +786,7 @@ validator_callback_nsec(void *arg) {
val->attributes |= VALATTR_FOUNDNODATA;
if (NEEDNODATA(val)) {
proofs[DNS_VALIDATOR_NODATAPROOF] =
name;
subvalidator->name;
}
}
if (!exists) {
@@ -806,7 +815,7 @@ validator_callback_nsec(void *arg) {
*/
if (NEEDNOQNAME(val)) {
proofs[DNS_VALIDATOR_NOQNAMEPROOF] =
name;
subvalidator->name;
}
}
}
@@ -815,10 +824,11 @@ validator_callback_nsec(void *arg) {
} else {
validator_log(val, ISC_LOG_DEBUG(3),
"validator_callback_nsec: got %s",
isc_result_totext(result));
switch (result) {
isc_result_totext(eresult));
switch (eresult) {
case ISC_R_CANCELED:
case ISC_R_SHUTTINGDOWN:
result = eresult;
break;
case DNS_R_BROKENCHAIN:
val->authfail++;
@@ -829,6 +839,9 @@ validator_callback_nsec(void *arg) {
}
cleanup:
dns_validator_detach(&subvalidator->parent);
dns_validator_shutdown(subvalidator);
dns_validator_detach(&subvalidator);
validate_async_done(val, result);
}
@@ -1781,11 +1794,6 @@ static void
resume_answer(void *arg) {
dns_validator_t *val = arg;
if (CANCELED(val) || CANCELING(val)) {
validate_async_done(val, ISC_R_CANCELED);
return;
}
val->resume = true;
validate_answer_iter_start(val);
}
@@ -3499,9 +3507,6 @@ destroy_validator(dns_validator_t *val) {
REQUIRE(val->subvalidator == NULL);
val->magic = 0;
if (val->parent != NULL) {
dns_validator_detach(&val->parent);
}
if (val->key != NULL) {
dst_key_free(&val->key);
}

View File

@@ -13,6 +13,7 @@ libisc_la_HEADERS = \
include/isc/barrier.h \
include/isc/base32.h \
include/isc/base64.h \
include/isc/bit.h \
include/isc/buffer.h \
include/isc/commandline.h \
include/isc/counter.h \

View File

@@ -21,6 +21,7 @@
#include <string.h>
#include <isc/atomic.h>
#include <isc/bit.h>
#include <isc/histo.h>
#include <isc/magic.h>
#include <isc/mem.h>
@@ -180,7 +181,7 @@ static inline uint
value_to_key(const isc_histo_t *hg, uint64_t value) {
/* ensure that denormal numbers are all in chunk zero */
uint64_t chunked = value | CHUNKSIZE(hg);
int clz = __builtin_clzll((unsigned long long)(chunked));
int clz = ISC_LEADING_ZEROS(chunked);
/* actually 1 less than the exponent except for denormals */
uint exponent = 63 - hg->sigbits - clz;
/* mantissa has leading bit set except for denormals */

View File

@@ -102,3 +102,9 @@
#else
#define ISC_ATTR_UNUSED __attribute__((__unused__))
#endif
#if __has_c_attribute(always_inline)
#define ISC_ATTR_ALWAYS_INLINE [[gnu::always_inline]]
#else /* __has_c_attribute(always_inline) */
#define ISC_ATTR_ALWAYS_INLINE __attribute__((always_inline))
#endif /* __has_c_attribute(always_inline) */

127
lib/isc/include/isc/bit.h Normal file
View File

@@ -0,0 +1,127 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MPL-2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#pragma once
#include <limits.h>
#include <stdint.h>
#include <isc/attributes.h>
#include <isc/util.h>
#ifndef __has_header
#define __has_header(x) 0
#endif
#if __has_header(<stdbit.h>)
#include <stdbit.h>
#define ISC_POPCOUNT(x) stdc_count_zeros(x)
#define ISC_LEADING_ZEROS(x) stdc_leading_zeros(x)
#define ISC_TRAILING_ZEROS(x) stdc_trailing_zeros(x)
#define ISC_LEADING_ONES(x) stdc_leading_ones(x)
#define ISC_TRAILING_ONES(x) stdc_trailing_ones(x)
#else /* __has_header(<stdbit.h>) */
#ifdef HAVE_BUILTIN_POPCOUNTG
#define ISC_POPCOUNT(x) __builtin_popcountg(x)
#else /* HAVE_BUILTIN_POPCOUNTG */
#define ISC_POPCOUNT(x) \
_Generic((x), \
unsigned int: __builtin_popcount, \
unsigned long: __builtin_popcountl, \
unsigned long long: __builtin_popcountll)(x)
#endif /* HAVE_BUILTIN_POPCOUNTG */
#ifdef HAVE_BUILTIN_CLZG
#define ISC_LEADING_ZEROS(x) __builtin_clzg(x, (int)(sizeof(x) * 8))
#else /* HAVE_BUILTIN_CLZG */
#define ISC_LEADING_ZEROS(x) \
(x == 0) ? (sizeof(x) * 8) \
: _Generic((x), \
unsigned int: __builtin_clz, \
unsigned long: __builtin_clzl, \
unsigned long long: __builtin_clzll)(x)
#endif /* HAVE_BUILTIN_CLZG */
#ifdef HAVE_BUILTIN_CTZG
#define ISC_TRAILING_ZEROS(x) __builtin_ctzg(x)
#else /* HAVE_BUILTIN_CTZG */
#define ISC_TRAILING_ZEROS(x) \
(x == 0) ? (sizeof(x) * 8) \
: _Generic((x), \
unsigned int: __builtin_ctz, \
unsigned long: __builtin_ctzl, \
unsigned long long: __builtin_ctzll)(x)
#endif /* HAVE_BUILTIN_CTZG */
#define ISC_LEADING_ONES(x) ISC_LEADING_ZEROS(~x)
#define ISC_TRAILING_ONES(x) ISC_TRAILING_ZEROS(~x)
#endif /* __has_header(<stdbit.h>) */
#define ISC_ROTATE_LEFT(x, n) \
_Generic((x), \
uint8_t: isc_rotate_left8, \
uint16_t: isc_rotate_left16, \
uint32_t: isc_rotate_left32, \
uint64_t: isc_rotate_left64)(x, n)
#define ISC_ROTATE_RIGHT(x, n) \
_Generic((x), \
uint8_t: isc_rotate_right8, \
uint16_t: isc_rotate_right16, \
uint32_t: isc_rotate_right32, \
uint64_t: isc_rotate_right64)(x, n)
static inline ISC_ATTR_ALWAYS_INLINE uint8_t
isc_rotate_left8(const uint8_t x, uint32_t n) {
return (x << n) | (x >> (8 - n));
}
static inline ISC_ATTR_ALWAYS_INLINE uint16_t
isc_rotate_left16(const uint16_t x, uint32_t n) {
return (x << n) | (x >> (16 - n));
}
static inline ISC_ATTR_ALWAYS_INLINE uint32_t
isc_rotate_left32(const uint32_t x, uint32_t n) {
return (x << n) | (x >> (32 - n));
}
static inline ISC_ATTR_ALWAYS_INLINE uint64_t
isc_rotate_left64(const uint64_t x, uint32_t n) {
return (x << n) | (x >> (64 - n));
}
static inline ISC_ATTR_ALWAYS_INLINE uint8_t
isc_rotate_right8(const uint8_t x, uint32_t n) {
return (x >> n) | (x << (8 - n));
}
static inline ISC_ATTR_ALWAYS_INLINE uint16_t
isc_rotate_right16(const uint16_t x, uint32_t n) {
return (x >> n) | (x << (16 - n));
}
static inline ISC_ATTR_ALWAYS_INLINE uint32_t
isc_rotate_right32(const uint32_t x, uint32_t n) {
return (x >> n) | (x << (32 - n));
}
static inline ISC_ATTR_ALWAYS_INLINE uint64_t
isc_rotate_right64(const uint64_t x, uint32_t n) {
return (x >> n) | (x << (64 - n));
}

View File

@@ -29,17 +29,14 @@
#include <stdint.h>
#include <string.h>
#include <isc/bit.h>
/* The constant K from Rust's fxhash */
#define K 0x9e3779b97f4a7c15ull
static inline size_t
rotate_left(size_t x, unsigned int n) {
return (x << n) | (x >> (sizeof(size_t) * 8 - n));
}
static inline size_t
fx_add_to_hash(size_t hash, size_t i) {
return rotate_left(hash, 5) ^ i * K;
return ISC_ROTATE_LEFT(hash, 5) ^ i * K;
}
/*

View File

@@ -30,6 +30,7 @@
#pragma once
#include <isc/ascii.h>
#include <isc/bit.h>
#include <isc/endian.h>
#include <isc/types.h>
#include <isc/util.h>
@@ -43,14 +44,12 @@
#define cROUNDS 2
#define dROUNDS 4
#define ROTATE64(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
#define HALF_ROUND64(a, b, c, d, s, t) \
a += b; \
c += d; \
b = ROTATE64(b, s) ^ a; \
d = ROTATE64(d, t) ^ c; \
a = ROTATE64(a, 32);
#define HALF_ROUND64(a, b, c, d, s, t) \
a += b; \
c += d; \
b = isc_rotate_left64(b, s) ^ a; \
d = isc_rotate_left64(d, t) ^ c; \
a = isc_rotate_left64(a, 32);
#define FULL_ROUND64(v0, v1, v2, v3) \
HALF_ROUND64(v0, v1, v2, v3, 13, 16); \
@@ -58,14 +57,12 @@
#define SIPROUND FULL_ROUND64
#define ROTATE32(x, b) (uint32_t)(((x) << (b)) | ((x) >> (32 - (b))))
#define HALF_ROUND32(a, b, c, d, s, t) \
a += b; \
c += d; \
b = ROTATE32(b, s) ^ a; \
d = ROTATE32(d, t) ^ c; \
a = ROTATE32(a, 16);
#define HALF_ROUND32(a, b, c, d, s, t) \
a += b; \
c += d; \
b = isc_rotate_left32(b, s) ^ a; \
d = isc_rotate_left32(d, t) ^ c; \
a = isc_rotate_left32(a, 16);
#define FULL_ROUND32(v0, v1, v2, v3) \
HALF_ROUND32(v0, v1, v2, v3, 5, 8); \

View File

@@ -35,6 +35,7 @@
#include <string.h>
#include <unistd.h>
#include <isc/bit.h>
#include <isc/entropy.h>
#include <isc/random.h>
#include <isc/result.h>
@@ -64,16 +65,11 @@
static thread_local bool initialized = false;
static thread_local uint32_t seed[4] = { 0 };
static uint32_t
rotl(const uint32_t x, int k) {
return (x << k) | (x >> (32 - k));
}
static uint32_t
next(void) {
uint32_t result_starstar, t;
result_starstar = rotl(seed[0] * 5, 7) * 9;
result_starstar = isc_rotate_left32(seed[0] * 5, 7) * 9;
t = seed[1] << 9;
seed[2] ^= seed[0];
@@ -83,7 +79,7 @@ next(void) {
seed[2] ^= t;
seed[3] = rotl(seed[3], 11);
seed[3] = isc_rotate_left32(seed[3], 11);
return result_starstar;
}