summaryrefslogtreecommitdiff
path: root/vendors
diff options
context:
space:
mode:
authorchenzizhan <[email protected]>2023-06-16 10:39:31 +0800
committerchenzizhan <[email protected]>2023-06-16 10:39:31 +0800
commit458f92ffdc1d923246028811ced178b7531ffec0 (patch)
tree61d919efdbbb4281302fa852ad7ce643d8c0c0a7 /vendors
parent48ed7fb72be503c11bdbfab1464742da29e5a22e (diff)
make hdr vendor lib compliable
Diffstat (limited to 'vendors')
-rw-r--r--vendors/hdr/hdr_atomic.h146
-rw-r--r--vendors/hdr/hdr_encoding.c323
-rw-r--r--vendors/hdr/hdr_encoding.h79
-rw-r--r--vendors/hdr/hdr_endian.h116
-rw-r--r--vendors/hdr/hdr_histogram.c (renamed from vendors/hdr_histogram/hdr_histogram.c)524
-rw-r--r--vendors/hdr/hdr_histogram.h (renamed from vendors/hdr_histogram/hdr_histogram.h)113
-rw-r--r--vendors/hdr/hdr_histogram_log.c (renamed from vendors/hdr_histogram/hdr_histogram_log.c)0
-rw-r--r--vendors/hdr/hdr_histogram_log.h (renamed from vendors/hdr_histogram/hdr_histogram_log.h)0
-rw-r--r--vendors/hdr/hdr_malloc.h19
-rw-r--r--vendors/hdr/hdr_tests.h22
-rw-r--r--vendors/hdr/hdr_time.c97
-rw-r--r--vendors/hdr/hdr_time.h47
12 files changed, 1313 insertions, 173 deletions
diff --git a/vendors/hdr/hdr_atomic.h b/vendors/hdr/hdr_atomic.h
new file mode 100644
index 0000000..11b0cbd
--- /dev/null
+++ b/vendors/hdr/hdr_atomic.h
@@ -0,0 +1,146 @@
+/**
+ * hdr_atomic.h
+ * Written by Philip Orwig and released to the public domain,
+ * as explained at http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+#ifndef HDR_ATOMIC_H__
+#define HDR_ATOMIC_H__
+
+
+#if defined(_MSC_VER) && !(defined(__clang__) && (defined(_M_ARM) || defined(_M_ARM64)))
+
+#include <stdint.h>
+#include <intrin.h>
+#include <stdbool.h>
+
+static void __inline * hdr_atomic_load_pointer(void** pointer)
+{
+ _ReadBarrier();
+ return *pointer;
+}
+
+static void hdr_atomic_store_pointer(void** pointer, void* value)
+{
+ _WriteBarrier();
+ *pointer = value;
+}
+
+static int64_t __inline hdr_atomic_load_64(int64_t* field)
+{
+ _ReadBarrier();
+ return *field;
+}
+
+static void __inline hdr_atomic_store_64(int64_t* field, int64_t value)
+{
+ _WriteBarrier();
+ *field = value;
+}
+
+static int64_t __inline hdr_atomic_exchange_64(volatile int64_t* field, int64_t value)
+{
+#if defined(_WIN64)
+ return _InterlockedExchange64(field, value);
+#else
+ int64_t comparand;
+ int64_t initial_value = *field;
+ do
+ {
+ comparand = initial_value;
+ initial_value = _InterlockedCompareExchange64(field, value, comparand);
+ }
+ while (comparand != initial_value);
+
+ return initial_value;
+#endif
+}
+
+static int64_t __inline hdr_atomic_add_fetch_64(volatile int64_t* field, int64_t value)
+{
+#if defined(_WIN64)
+ return _InterlockedExchangeAdd64(field, value) + value;
+#else
+ int64_t comparand;
+ int64_t initial_value = *field;
+ do
+ {
+ comparand = initial_value;
+ initial_value = _InterlockedCompareExchange64(field, comparand + value, comparand);
+ }
+ while (comparand != initial_value);
+
+ return initial_value + value;
+#endif
+}
+
+static bool __inline hdr_atomic_compare_exchange_64(volatile int64_t* field, int64_t* expected, int64_t desired)
+{
+ return *expected == _InterlockedCompareExchange64(field, desired, *expected);
+}
+
+#elif defined(__ATOMIC_SEQ_CST)
+
+#define hdr_atomic_load_pointer(x) __atomic_load_n(x, __ATOMIC_SEQ_CST)
+#define hdr_atomic_store_pointer(f,v) __atomic_store_n(f,v, __ATOMIC_SEQ_CST)
+#define hdr_atomic_load_64(x) __atomic_load_n(x, __ATOMIC_SEQ_CST)
+#define hdr_atomic_store_64(f,v) __atomic_store_n(f,v, __ATOMIC_SEQ_CST)
+#define hdr_atomic_exchange_64(f,i) __atomic_exchange_n(f,i, __ATOMIC_SEQ_CST)
+#define hdr_atomic_add_fetch_64(field, value) __atomic_add_fetch(field, value, __ATOMIC_SEQ_CST)
+#define hdr_atomic_compare_exchange_64(field, expected, desired) __atomic_compare_exchange_n(field, expected, desired, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
+
+#elif defined(__x86_64__)
+
+#include <stdint.h>
+#include <stdbool.h>
+
+static inline void* hdr_atomic_load_pointer(void** pointer)
+{
+ void* p = *pointer;
+ asm volatile ("" ::: "memory");
+ return p;
+}
+
+static inline void hdr_atomic_store_pointer(void** pointer, void* value)
+{
+ asm volatile ("lock; xchgq %0, %1" : "+q" (value), "+m" (*pointer));
+}
+
+static inline int64_t hdr_atomic_load_64(int64_t* field)
+{
+ int64_t i = *field;
+ asm volatile ("" ::: "memory");
+ return i;
+}
+
+static inline void hdr_atomic_store_64(int64_t* field, int64_t value)
+{
+ asm volatile ("lock; xchgq %0, %1" : "+q" (value), "+m" (*field));
+}
+
+static inline int64_t hdr_atomic_exchange_64(volatile int64_t* field, int64_t value)
+{
+ int64_t result = 0;
+ asm volatile ("lock; xchgq %1, %2" : "=r" (result), "+q" (value), "+m" (*field));
+ return result;
+}
+
+static inline int64_t hdr_atomic_add_fetch_64(volatile int64_t* field, int64_t value)
+{
+ return __sync_add_and_fetch(field, value);
+}
+
+static inline bool hdr_atomic_compare_exchange_64(volatile int64_t* field, int64_t* expected, int64_t desired)
+{
+ int64_t original;
+ asm volatile( "lock; cmpxchgq %2, %1" : "=a"(original), "+m"(*field) : "q"(desired), "0"(*expected));
+ return original == *expected;
+}
+
+#else
+
+#error "Unable to determine atomic operations for your platform"
+
+#endif
+
+#endif /* HDR_ATOMIC_H__ */
diff --git a/vendors/hdr/hdr_encoding.c b/vendors/hdr/hdr_encoding.c
new file mode 100644
index 0000000..7e04d9e
--- /dev/null
+++ b/vendors/hdr/hdr_encoding.c
@@ -0,0 +1,323 @@
+/**
+ * hdr_encoding.c
+ * Written by Michael Barker and released to the public domain,
+ * as explained at http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+#include <errno.h>
+#include <stddef.h>
+#include <math.h>
+
+#include "hdr_encoding.h"
+#include "hdr_tests.h"
+
+int zig_zag_encode_i64(uint8_t* buffer, int64_t signed_value)
+{
+ int bytesWritten;
+ int64_t value = signed_value;
+
+// cppcheck-suppress shiftTooManyBitsSigned
+ value = (value << 1) ^ (value >> 63); // cppcheck-suppress[shiftTooManyBitsSigned]
+ if (value >> 7 == 0)
+ {
+ buffer[0] = (uint8_t) value;
+ bytesWritten = 1;
+ }
+ else
+ {
+ buffer[0] = (uint8_t) ((value & 0x7F) | 0x80);
+ if (value >> 14 == 0)
+ {
+ buffer[1] = (uint8_t) (value >> 7);
+ bytesWritten = 2;
+ }
+ else
+ {
+ buffer[1] = (uint8_t) ((value >> 7 | 0x80));
+ if (value >> 21 == 0)
+ {
+ buffer[2] = (uint8_t) (value >> 14);
+ bytesWritten = 3;
+ }
+ else
+ {
+ buffer[2] = (uint8_t) (value >> 14 | 0x80);
+ if (value >> 28 == 0)
+ {
+ buffer[3] = (uint8_t) (value >> 21);
+ bytesWritten = 4;
+ }
+ else
+ {
+ buffer[3] = (uint8_t) (value >> 21 | 0x80);
+ if (value >> 35 == 0)
+ {
+ buffer[4] = (uint8_t) (value >> 28);
+ bytesWritten = 5;
+ }
+ else
+ {
+ buffer[4] = (uint8_t) (value >> 28 | 0x80);
+ if (value >> 42 == 0)
+ {
+ buffer[5] = (uint8_t) (value >> 35);
+ bytesWritten = 6;
+ }
+ else
+ {
+ buffer[5] = (uint8_t) (value >> 35 | 0x80);
+ if (value >> 49 == 0)
+ {
+ buffer[6] = (uint8_t) (value >> 42);
+ bytesWritten = 7;
+ }
+ else
+ {
+ buffer[6] = (uint8_t) (value >> 42 | 0x80);
+ if (value >> 56 == 0)
+ {
+ buffer[7] = (uint8_t) (value >> 49);
+ bytesWritten = 8;
+ }
+ else
+ {
+ buffer[7] = (uint8_t) (value >> 49 | 0x80);
+ buffer[8] = (uint8_t) (value >> 56);
+ bytesWritten = 9;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return bytesWritten;
+}
+
+int zig_zag_decode_i64(const uint8_t* buffer, int64_t* signed_value)
+{
+ uint64_t v = buffer[0];
+ uint64_t value = v & 0x7F;
+ int bytesRead = 1;
+ if ((v & 0x80) != 0)
+ {
+ bytesRead = 2;
+ v = buffer[1];
+ value |= (v & 0x7F) << 7;
+ if ((v & 0x80) != 0)
+ {
+ bytesRead = 3;
+ v = buffer[2];
+ value |= (v & 0x7F) << 14;
+ if ((v & 0x80) != 0)
+ {
+ bytesRead = 4;
+ v = buffer[3];
+ value |= (v & 0x7F) << 21;
+ if ((v & 0x80) != 0)
+ {
+ bytesRead = 5;
+ v = buffer[4];
+ value |= (v & 0x7F) << 28;
+ if ((v & 0x80) != 0)
+ {
+ bytesRead = 6;
+ v = buffer[5];
+ value |= (v & 0x7F) << 35;
+ if ((v & 0x80) != 0)
+ {
+ bytesRead = 7;
+ v = buffer[6];
+ value |= (v & 0x7F) << 42;
+ if ((v & 0x80) != 0)
+ {
+ bytesRead = 8;
+ v = buffer[7];
+ value |= (v & 0x7F) << 49;
+ if ((v & 0x80) != 0)
+ {
+ bytesRead = 9;
+ v = buffer[8];
+ value |= v << 56;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable: 4146) /* C4146: unary minus operator applied to unsigned type, result still unsigned */
+#endif
+ value = (value >> 1) ^ (-(value & 1));
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+ *signed_value = (int64_t) value;
+
+ return bytesRead;
+}
+
+static const char base64_table[] =
+ {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0'
+ };
+
+static char get_base_64(uint32_t _24_bit_value, int shift)
+{
+ uint32_t _6_bit_value = 0x3F & (_24_bit_value >> shift);
+ return base64_table[_6_bit_value];
+}
+
+static int from_base_64(int c)
+{
+ if ('A' <= c && c <= 'Z')
+ {
+ return c - 'A';
+ }
+ else if ('a' <= c && c <= 'z')
+ {
+ return (c - 'a') + 26;
+ }
+ else if ('0' <= c && c <= '9')
+ {
+ return (c - '0') + 52;
+ }
+ else if ('+' == c)
+ {
+ return 62;
+ }
+ else if ('/' == c)
+ {
+ return 63;
+ }
+ else if ('=' == c)
+ {
+ return 0;
+ }
+
+ return EINVAL;
+}
+
+size_t hdr_base64_encoded_len(size_t decoded_size)
+{
+ return (size_t) (ceil(decoded_size / 3.0) * 4.0);
+}
+
+size_t hdr_base64_decoded_len(size_t encoded_size)
+{
+ return (encoded_size / 4) * 3;
+}
+
+static void hdr_base64_encode_block_pad(const uint8_t* input, char* output, size_t pad)
+{
+ uint32_t _24_bit_value = 0;
+
+ switch (pad)
+ {
+ case 2:
+ _24_bit_value = (input[0] << 16) + (input[1] << 8);
+
+ output[0] = get_base_64(_24_bit_value, 18);
+ output[1] = get_base_64(_24_bit_value, 12);
+ output[2] = get_base_64(_24_bit_value, 6);
+ output[3] = '=';
+
+ break;
+
+ case 1:
+ _24_bit_value = (input[0] << 16);
+
+ output[0] = get_base_64(_24_bit_value, 18);
+ output[1] = get_base_64(_24_bit_value, 12);
+ output[2] = '=';
+ output[3] = '=';
+
+ break;
+
+ default:
+ /* No-op */
+ break;
+ }
+}
+
+/**
+ * Assumes that there is 3 input bytes and 4 output chars.
+ */
+void hdr_base64_encode_block(const uint8_t* input, char* output)
+{
+ uint32_t _24_bit_value = (input[0] << 16) + (input[1] << 8) + (input[2]);
+
+ output[0] = get_base_64(_24_bit_value, 18);
+ output[1] = get_base_64(_24_bit_value, 12);
+ output[2] = get_base_64(_24_bit_value, 6);
+ output[3] = get_base_64(_24_bit_value, 0);
+}
+
+int hdr_base64_encode(
+ const uint8_t* input, size_t input_len, char* output, size_t output_len)
+{
+ size_t i, j, remaining;
+
+ if (hdr_base64_encoded_len(input_len) != output_len)
+ {
+ return EINVAL;
+ }
+
+ for (i = 0, j = 0; input_len - i >= 3 && j < output_len; i += 3, j += 4)
+ {
+ hdr_base64_encode_block(&input[i], &output[j]);
+ }
+
+ remaining = input_len - i;
+
+ hdr_base64_encode_block_pad(&input[i], &output[j], remaining);
+
+ return 0;
+}
+
+/**
+ * Assumes that there is 4 input chars available and 3 output chars.
+ */
+void hdr_base64_decode_block(const char* input, uint8_t* output)
+{
+ uint32_t _24_bit_value = 0;
+
+ _24_bit_value |= from_base_64(input[0]) << 18;
+ _24_bit_value |= from_base_64(input[1]) << 12;
+ _24_bit_value |= from_base_64(input[2]) << 6;
+ _24_bit_value |= from_base_64(input[3]);
+
+ output[0] = (uint8_t) ((_24_bit_value >> 16) & 0xFF);
+ output[1] = (uint8_t) ((_24_bit_value >> 8) & 0xFF);
+ output[2] = (uint8_t) ((_24_bit_value) & 0xFF);
+}
+
+int hdr_base64_decode(
+ const char* input, size_t input_len, uint8_t* output, size_t output_len)
+{
+ size_t i, j;
+
+ if (input_len < 4 ||
+ (input_len & 3u) != 0 ||
+ (input_len / 4) * 3 != output_len)
+ {
+ return -EINVAL;
+ }
+
+ for (i = 0, j = 0; i < input_len; i += 4, j += 3)
+ {
+ hdr_base64_decode_block(&input[i], &output[j]);
+ }
+
+ return 0;
+}
diff --git a/vendors/hdr/hdr_encoding.h b/vendors/hdr/hdr_encoding.h
new file mode 100644
index 0000000..95f1db6
--- /dev/null
+++ b/vendors/hdr/hdr_encoding.h
@@ -0,0 +1,79 @@
+/**
+ * hdr_encoding.h
+ * Written by Michael Barker and released to the public domain,
+ * as explained at http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+#ifndef HDR_ENCODING_H
+#define HDR_ENCODING_H
+
+#include <stdint.h>
+
+#define MAX_BYTES_LEB128 9
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Writes a int64_t value to the given buffer in LEB128 ZigZag encoded format
+ *
+ * @param buffer the buffer to write to
+ * @param signed_value the value to write to the buffer
+ * @return the number of bytes written to the buffer
+ */
+int zig_zag_encode_i64(uint8_t* buffer, int64_t signed_value);
+
+/**
+ * Read an LEB128 ZigZag encoded long value from the given buffer
+ *
+ * @param buffer the buffer to read from
+ * @param retVal out value to capture the read value
+ * @return the number of bytes read from the buffer
+ */
+int zig_zag_decode_i64(const uint8_t* buffer, int64_t* signed_value);
+
+/**
+ * Gets the length in bytes of base64 data, given the input size.
+ *
+ * @param decoded_size the size of the unencoded values.
+ * @return the encoded size
+ */
+size_t hdr_base64_encoded_len(size_t decoded_size);
+
+/**
+ * Encode into base64.
+ *
+ * @param input the data to encode
+ * @param input_len the length of the data to encode
+ * @param output the buffer to write the output to
+ * @param output_len the number of bytes to write to the output
+ */
+int hdr_base64_encode(
+ const uint8_t* input, size_t input_len, char* output, size_t output_len);
+
+/**
+ * Gets the length in bytes of decoded base64 data, given the size of the base64 encoded
+ * data.
+ *
+ * @param encoded_size the size of the encoded value.
+ * @return the decoded size
+ */
+size_t hdr_base64_decoded_len(size_t encoded_size);
+
+/**
+ * Decode from base64.
+ *
+ * @param input the base64 encoded data
+ * @param input_len the size in bytes of the endcoded data
+ * @param output the buffer to write the decoded data to
+ * @param output_len the number of bytes to write to the output data
+ */
+int hdr_base64_decode(
+ const char* input, size_t input_len, uint8_t* output, size_t output_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HDR_HISTOGRAM_HDR_ENCODING_H */
diff --git a/vendors/hdr/hdr_endian.h b/vendors/hdr/hdr_endian.h
new file mode 100644
index 0000000..839fdb1
--- /dev/null
+++ b/vendors/hdr/hdr_endian.h
@@ -0,0 +1,116 @@
+/**
+* hdr_time.h
+* Released to the public domain, as explained at http://creativecommons.org/publicdomain/zero/1.0/
+*/
+
+#ifndef HDR_ENDIAN_H__
+#define HDR_ENDIAN_H__
+
+#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__)
+
+# define __WINDOWS__
+
+#endif
+
+#if defined(__linux__) || defined(__CYGWIN__)
+
+# include <endian.h>
+
+#elif defined(__APPLE__)
+
+# include <libkern/OSByteOrder.h>
+
+# define htobe16(x) OSSwapHostToBigInt16(x)
+# define htole16(x) OSSwapHostToLittleInt16(x)
+# define be16toh(x) OSSwapBigToHostInt16(x)
+# define le16toh(x) OSSwapLittleToHostInt16(x)
+
+# define htobe32(x) OSSwapHostToBigInt32(x)
+# define htole32(x) OSSwapHostToLittleInt32(x)
+# define be32toh(x) OSSwapBigToHostInt32(x)
+# define le32toh(x) OSSwapLittleToHostInt32(x)
+
+# define htobe64(x) OSSwapHostToBigInt64(x)
+# define htole64(x) OSSwapHostToLittleInt64(x)
+# define be64toh(x) OSSwapBigToHostInt64(x)
+# define le64toh(x) OSSwapLittleToHostInt64(x)
+
+# define __BYTE_ORDER BYTE_ORDER
+# define __BIG_ENDIAN BIG_ENDIAN
+# define __LITTLE_ENDIAN LITTLE_ENDIAN
+# define __PDP_ENDIAN PDP_ENDIAN
+
+#elif defined(__OpenBSD__)
+
+# include <sys/endian.h>
+
+#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
+
+# include <sys/endian.h>
+
+# define be16toh(x) betoh16(x)
+# define le16toh(x) letoh16(x)
+
+# define be32toh(x) betoh32(x)
+# define le32toh(x) letoh32(x)
+
+# define be64toh(x) betoh64(x)
+# define le64toh(x) letoh64(x)
+
+#elif defined(__WINDOWS__)
+
+# include <winsock2.h>
+
+# if BYTE_ORDER == LITTLE_ENDIAN
+
+# define htobe16(x) htons(x)
+# define htole16(x) (x)
+# define be16toh(x) ntohs(x)
+# define le16toh(x) (x)
+
+# define htobe32(x) htonl(x)
+# define htole32(x) (x)
+# define be32toh(x) ntohl(x)
+# define le32toh(x) (x)
+
+# define htobe64(x) htonll(x)
+# define htole64(x) (x)
+# define be64toh(x) ntohll(x)
+# define le64toh(x) (x)
+
+# elif BYTE_ORDER == BIG_ENDIAN
+
+ /* that would be xbox 360 */
+# define htobe16(x) (x)
+# define htole16(x) __builtin_bswap16(x)
+# define be16toh(x) (x)
+# define le16toh(x) __builtin_bswap16(x)
+
+# define htobe32(x) (x)
+# define htole32(x) __builtin_bswap32(x)
+# define be32toh(x) (x)
+# define le32toh(x) __builtin_bswap32(x)
+
+# define htobe64(x) (x)
+# define htole64(x) __builtin_bswap64(x)
+# define be64toh(x) (x)
+# define le64toh(x) __builtin_bswap64(x)
+
+# else
+
+# error byte order not supported
+
+# endif
+
+# define __BYTE_ORDER BYTE_ORDER
+# define __BIG_ENDIAN BIG_ENDIAN
+# define __LITTLE_ENDIAN LITTLE_ENDIAN
+# define __PDP_ENDIAN PDP_ENDIAN
+
+#else
+
+# error platform not supported
+
+#endif
+
+#endif
diff --git a/vendors/hdr_histogram/hdr_histogram.c b/vendors/hdr/hdr_histogram.c
index e1caaf2..7a4c4fd 100644
--- a/vendors/hdr_histogram/hdr_histogram.c
+++ b/vendors/hdr/hdr_histogram.c
@@ -7,32 +7,40 @@
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
-#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <inttypes.h>
-#include "hdr_histogram.h"
+#include <hdr/hdr_histogram.h>
+#include "hdr_tests.h"
+#include "hdr_atomic.h"
-// ###### ####### ## ## ## ## ######## ######
-// ## ## ## ## ## ## ### ## ## ## ##
-// ## ## ## ## ## #### ## ## ##
-// ## ## ## ## ## ## ## ## ## ######
-// ## ## ## ## ## ## #### ## ##
-// ## ## ## ## ## ## ## ### ## ## ##
-// ###### ####### ####### ## ## ## ######
+#ifndef HDR_MALLOC_INCLUDE
+#define HDR_MALLOC_INCLUDE "hdr_malloc.h"
+#endif
+
+#include HDR_MALLOC_INCLUDE
+
+/* ###### ####### ## ## ## ## ######## ###### */
+/* ## ## ## ## ## ## ### ## ## ## ## */
+/* ## ## ## ## ## #### ## ## ## */
+/* ## ## ## ## ## ## ## ## ## ###### */
+/* ## ## ## ## ## ## #### ## ## */
+/* ## ## ## ## ## ## ## ### ## ## ## */
+/* ###### ####### ####### ## ## ## ###### */
static int32_t normalize_index(const struct hdr_histogram* h, int32_t index)
{
+ int32_t normalized_index;
+ int32_t adjustment = 0;
if (h->normalizing_index_offset == 0)
{
return index;
}
- int32_t normalized_index = index - h->normalizing_index_offset;
- int32_t adjustment = 0;
+ normalized_index = index - h->normalizing_index_offset;
if (normalized_index < 0)
{
@@ -64,19 +72,56 @@ static void counts_inc_normalised(
h->total_count += value;
}
+static void counts_inc_normalised_atomic(
+ struct hdr_histogram* h, int32_t index, int64_t value)
+{
+ int32_t normalised_index = normalize_index(h, index);
+
+ hdr_atomic_add_fetch_64(&h->counts[normalised_index], value);
+ hdr_atomic_add_fetch_64(&h->total_count, value);
+}
+
static void update_min_max(struct hdr_histogram* h, int64_t value)
{
h->min_value = (value < h->min_value && value != 0) ? value : h->min_value;
h->max_value = (value > h->max_value) ? value : h->max_value;
}
-// ## ## ######## #### ## #### ######## ## ##
-// ## ## ## ## ## ## ## ## ##
-// ## ## ## ## ## ## ## ####
-// ## ## ## ## ## ## ## ##
-// ## ## ## ## ## ## ## ##
-// ## ## ## ## ## ## ## ##
-// ####### ## #### ######## #### ## ##
+static void update_min_max_atomic(struct hdr_histogram* h, int64_t value)
+{
+ int64_t current_min_value;
+ int64_t current_max_value;
+ do
+ {
+ current_min_value = hdr_atomic_load_64(&h->min_value);
+
+ if (0 == value || current_min_value <= value)
+ {
+ break;
+ }
+ }
+ while (!hdr_atomic_compare_exchange_64(&h->min_value, &current_min_value, value));
+
+ do
+ {
+ current_max_value = hdr_atomic_load_64(&h->max_value);
+
+ if (value <= current_max_value)
+ {
+ break;
+ }
+ }
+ while (!hdr_atomic_compare_exchange_64(&h->max_value, &current_max_value, value));
+}
+
+
+/* ## ## ######## #### ## #### ######## ## ## */
+/* ## ## ## ## ## ## ## ## ## */
+/* ## ## ## ## ## ## ## #### */
+/* ## ## ## ## ## ## ## ## */
+/* ## ## ## ## ## ## ## ## */
+/* ## ## ## ## ## ## ## ## */
+/* ####### ## #### ######## #### ## ## */
static int64_t power(int64_t base, int64_t exp)
{
@@ -88,19 +133,41 @@ static int64_t power(int64_t base, int64_t exp)
return result;
}
-#if defined(_MSC_VER)
-#pragma intrinsic(_BitScanReverse64)
+#if defined(_MSC_VER) && !(defined(__clang__) && (defined(_M_ARM) || defined(_M_ARM64)))
+# if defined(_WIN64)
+# pragma intrinsic(_BitScanReverse64)
+# else
+# pragma intrinsic(_BitScanReverse)
+# endif
#endif
-static int32_t get_bucket_index(const struct hdr_histogram* h, int64_t value)
+static int32_t count_leading_zeros_64(int64_t value)
{
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) && !(defined(__clang__) && (defined(_M_ARM) || defined(_M_ARM64)))
uint32_t leading_zero = 0;
- _BitScanReverse64(&leading_zero, value | h->sub_bucket_mask);
- int32_t pow2ceiling = 64 - (63 - leading_zero); // smallest power of 2 containing value
+#if defined(_WIN64)
+ _BitScanReverse64(&leading_zero, value);
#else
- int32_t pow2ceiling = 64 - __builtin_clzll(value | h->sub_bucket_mask); // smallest power of 2 containing value
+ uint32_t high = value >> 32;
+ if (_BitScanReverse(&leading_zero, high))
+ {
+ leading_zero += 32;
+ }
+ else
+ {
+ uint32_t low = value & 0x00000000FFFFFFFF;
+ _BitScanReverse(&leading_zero, low);
+ }
#endif
+ return 63 - leading_zero; /* smallest power of 2 containing value */
+#else
+ return __builtin_clzll(value); /* smallest power of 2 containing value */
+#endif
+}
+
+static int32_t get_bucket_index(const struct hdr_histogram* h, int64_t value)
+{
+ int32_t pow2ceiling = 64 - count_leading_zeros_64(value | h->sub_bucket_mask); /* smallest power of 2 containing value */
return pow2ceiling - h->unit_magnitude - (h->sub_bucket_half_count_magnitude + 1);
}
@@ -111,12 +178,12 @@ static int32_t get_sub_bucket_index(int64_t value, int32_t bucket_index, int32_t
static int32_t counts_index(const struct hdr_histogram* h, int32_t bucket_index, int32_t sub_bucket_index)
{
- // Calculate the index for the first entry in the bucket:
- // (The following is the equivalent of ((bucket_index + 1) * subBucketHalfCount) ):
+ /* Calculate the index for the first entry in the bucket: */
+ /* (The following is the equivalent of ((bucket_index + 1) * subBucketHalfCount) ): */
int32_t bucket_base_index = (bucket_index + 1) << h->sub_bucket_half_count_magnitude;
- // Calculate the offset in the bucket:
+ /* Calculate the offset in the bucket: */
int32_t offset_in_bucket = sub_bucket_index - h->sub_bucket_half_count;
- // The following is the equivalent of ((sub_bucket_index - subBucketHalfCount) + bucketBaseIndex;
+ /* The following is the equivalent of ((sub_bucket_index - subBucketHalfCount) + bucketBaseIndex; */
return bucket_base_index + offset_in_bucket;
}
@@ -155,6 +222,15 @@ int64_t hdr_size_of_equivalent_value_range(const struct hdr_histogram* h, int64_
return INT64_C(1) << (h->unit_magnitude + adjusted_bucket);
}
+static int64_t size_of_equivalent_value_range_given_bucket_indices(
+ const struct hdr_histogram *h,
+ int32_t bucket_index,
+ int32_t sub_bucket_index)
+{
+ const int32_t adjusted_bucket = (sub_bucket_index >= h->sub_bucket_count) ? (bucket_index + 1) : bucket_index;
+ return INT64_C(1) << (h->unit_magnitude + adjusted_bucket);
+}
+
static int64_t lowest_equivalent_value(const struct hdr_histogram* h, int64_t value)
{
int32_t bucket_index = get_bucket_index(h, value);
@@ -162,6 +238,14 @@ static int64_t lowest_equivalent_value(const struct hdr_histogram* h, int64_t va
return value_from_index(bucket_index, sub_bucket_index, h->unit_magnitude);
}
+static int64_t lowest_equivalent_value_given_bucket_indices(
+ const struct hdr_histogram *h,
+ int32_t bucket_index,
+ int32_t sub_bucket_index)
+{
+ return value_from_index(bucket_index, sub_bucket_index, h->unit_magnitude);
+}
+
int64_t hdr_next_non_equivalent_value(const struct hdr_histogram *h, int64_t value)
{
return lowest_equivalent_value(h, value) + hdr_size_of_equivalent_value_range(h, value);
@@ -248,40 +332,45 @@ static int32_t buckets_needed_to_cover_value(int64_t value, int32_t sub_bucket_c
return buckets_needed;
}
-// ## ## ######## ## ## ####### ######## ## ##
-// ### ### ## ### ### ## ## ## ## ## ##
-// #### #### ## #### #### ## ## ## ## ####
-// ## ### ## ###### ## ### ## ## ## ######## ##
-// ## ## ## ## ## ## ## ## ## ##
-// ## ## ## ## ## ## ## ## ## ##
-// ## ## ######## ## ## ####### ## ## ##
+/* ## ## ######## ## ## ####### ######## ## ## */
+/* ### ### ## ### ### ## ## ## ## ## ## */
+/* #### #### ## #### #### ## ## ## ## #### */
+/* ## ### ## ###### ## ### ## ## ## ######## ## */
+/* ## ## ## ## ## ## ## ## ## ## */
+/* ## ## ## ## ## ## ## ## ## ## */
+/* ## ## ######## ## ## ####### ## ## ## */
int hdr_calculate_bucket_config(
- int64_t lowest_trackable_value,
+ int64_t lowest_discernible_value,
int64_t highest_trackable_value,
int significant_figures,
struct hdr_histogram_bucket_config* cfg)
{
- if (lowest_trackable_value < 1 ||
- significant_figures < 1 || 5 < significant_figures)
- {
- return EINVAL;
- }
- else if (lowest_trackable_value * 2 > highest_trackable_value)
+ int32_t sub_bucket_count_magnitude;
+ int64_t largest_value_with_single_unit_resolution;
+
+ if (lowest_discernible_value < 1 ||
+ significant_figures < 1 || 5 < significant_figures ||
+ lowest_discernible_value * 2 > highest_trackable_value)
{
return EINVAL;
}
- cfg->lowest_trackable_value = lowest_trackable_value;
+ cfg->lowest_discernible_value = lowest_discernible_value;
cfg->significant_figures = significant_figures;
cfg->highest_trackable_value = highest_trackable_value;
- int64_t largest_value_with_single_unit_resolution = 2 * power(10, significant_figures);
- int32_t sub_bucket_count_magnitude = (int32_t) ceil(log((double)largest_value_with_single_unit_resolution) / log(2));
+ largest_value_with_single_unit_resolution = 2 * power(10, significant_figures);
+ sub_bucket_count_magnitude = (int32_t) ceil(log((double)largest_value_with_single_unit_resolution) / log(2));
cfg->sub_bucket_half_count_magnitude = ((sub_bucket_count_magnitude > 1) ? sub_bucket_count_magnitude : 1) - 1;
- cfg->unit_magnitude = (int32_t) floor(log((double)lowest_trackable_value) / log(2));
+ double unit_magnitude = log((double)lowest_discernible_value) / log(2);
+ if (INT32_MAX < unit_magnitude)
+ {
+ return EINVAL;
+ }
+ cfg->unit_magnitude = (int32_t) unit_magnitude;
cfg->sub_bucket_count = (int32_t) pow(2, (cfg->sub_bucket_half_count_magnitude + 1));
cfg->sub_bucket_half_count = cfg->sub_bucket_count / 2;
cfg->sub_bucket_mask = ((int64_t) cfg->sub_bucket_count - 1) << cfg->unit_magnitude;
@@ -299,7 +388,7 @@ int hdr_calculate_bucket_config(
void hdr_init_preallocated(struct hdr_histogram* h, struct hdr_histogram_bucket_config* cfg)
{
- h->lowest_trackable_value = cfg->lowest_trackable_value;
+ h->lowest_discernible_value = cfg->lowest_discernible_value;
h->highest_trackable_value = cfg->highest_trackable_value;
h->unit_magnitude = (int32_t)cfg->unit_magnitude;
h->significant_figures = (int32_t)cfg->significant_figures;
@@ -317,24 +406,31 @@ void hdr_init_preallocated(struct hdr_histogram* h, struct hdr_histogram_bucket_
}
int hdr_init(
- int64_t lowest_trackable_value,
+ int64_t lowest_discernible_value,
int64_t highest_trackable_value,
int significant_figures,
struct hdr_histogram** result)
{
+ int64_t* counts;
struct hdr_histogram_bucket_config cfg;
+ struct hdr_histogram* histogram;
- int r = hdr_calculate_bucket_config(lowest_trackable_value, highest_trackable_value, significant_figures, &cfg);
+ int r = hdr_calculate_bucket_config(lowest_discernible_value, highest_trackable_value, significant_figures, &cfg);
if (r)
{
return r;
}
- int64_t* counts = calloc((size_t) cfg.counts_len, sizeof(int64_t));
- struct hdr_histogram* histogram = calloc(1, sizeof(struct hdr_histogram));
+ counts = (int64_t*) hdr_calloc((size_t) cfg.counts_len, sizeof(int64_t));
+ if (!counts)
+ {
+ return ENOMEM;
+ }
- if (!counts || !histogram)
+ histogram = (struct hdr_histogram*) hdr_calloc(1, sizeof(struct hdr_histogram));
+ if (!histogram)
{
+ hdr_free(counts);
return ENOMEM;
}
@@ -348,8 +444,10 @@ int hdr_init(
void hdr_close(struct hdr_histogram* h)
{
- free(h->counts);
- free(h);
+ if (h) {
+ hdr_free(h->counts);
+ hdr_free(h);
+ }
}
int hdr_alloc(int64_t highest_trackable_value, int significant_figures, struct hdr_histogram** result)
@@ -357,7 +455,7 @@ int hdr_alloc(int64_t highest_trackable_value, int significant_figures, struct h
return hdr_init(1, highest_trackable_value, significant_figures, result);
}
-// reset a histogram to zero.
+/* reset a histogram to zero. */
void hdr_reset(struct hdr_histogram *h)
{
h->total_count=0;
@@ -371,13 +469,13 @@ size_t hdr_get_memory_size(struct hdr_histogram *h)
return sizeof(struct hdr_histogram) + h->counts_len * sizeof(int64_t);
}
-// ## ## ######## ######## ### ######## ######## ######
-// ## ## ## ## ## ## ## ## ## ## ## ##
-// ## ## ## ## ## ## ## ## ## ## ##
-// ## ## ######## ## ## ## ## ## ###### ######
-// ## ## ## ## ## ######### ## ## ##
-// ## ## ## ## ## ## ## ## ## ## ##
-// ####### ## ######## ## ## ## ######## ######
+/* ## ## ######## ######## ### ######## ######## ###### */
+/* ## ## ## ## ## ## ## ## ## ## ## ## */
+/* ## ## ## ## ## ## ## ## ## ## ## */
+/* ## ## ######## ## ## ## ## ## ###### ###### */
+/* ## ## ## ## ## ######### ## ## ## */
+/* ## ## ## ## ## ## ## ## ## ## ## */
+/* ####### ## ######## ## ## ## ######## ###### */
bool hdr_record_value(struct hdr_histogram* h, int64_t value)
@@ -385,14 +483,21 @@ bool hdr_record_value(struct hdr_histogram* h, int64_t value)
return hdr_record_values(h, value, 1);
}
+bool hdr_record_value_atomic(struct hdr_histogram* h, int64_t value)
+{
+ return hdr_record_values_atomic(h, value, 1);
+}
+
bool hdr_record_values(struct hdr_histogram* h, int64_t value, int64_t count)
{
+ int32_t counts_index;
+
if (value < 0)
{
return false;
}
- int32_t counts_index = counts_index_for(h, value);
+ counts_index = counts_index_for(h, value);
if (counts_index < 0 || h->counts_len <= counts_index)
{
@@ -405,14 +510,42 @@ bool hdr_record_values(struct hdr_histogram* h, int64_t value, int64_t count)
return true;
}
+bool hdr_record_values_atomic(struct hdr_histogram* h, int64_t value, int64_t count)
+{
+ int32_t counts_index;
+
+ if (value < 0)
+ {
+ return false;
+ }
+
+ counts_index = counts_index_for(h, value);
+
+ if (counts_index < 0 || h->counts_len <= counts_index)
+ {
+ return false;
+ }
+
+ counts_inc_normalised_atomic(h, counts_index, count);
+ update_min_max_atomic(h, value);
+
+ return true;
+}
+
bool hdr_record_corrected_value(struct hdr_histogram* h, int64_t value, int64_t expected_interval)
{
return hdr_record_corrected_values(h, value, 1, expected_interval);
}
+bool hdr_record_corrected_value_atomic(struct hdr_histogram* h, int64_t value, int64_t expected_interval)
+{
+ return hdr_record_corrected_values_atomic(h, value, 1, expected_interval);
+}
bool hdr_record_corrected_values(struct hdr_histogram* h, int64_t value, int64_t count, int64_t expected_interval)
{
+ int64_t missing_value;
+
if (!hdr_record_values(h, value, count))
{
return false;
@@ -423,7 +556,7 @@ bool hdr_record_corrected_values(struct hdr_histogram* h, int64_t value, int64_t
return true;
}
- int64_t missing_value = value - expected_interval;
+ missing_value = value - expected_interval;
for (; missing_value >= expected_interval; missing_value -= expected_interval)
{
if (!hdr_record_values(h, missing_value, count))
@@ -435,11 +568,37 @@ bool hdr_record_corrected_values(struct hdr_histogram* h, int64_t value, int64_t
return true;
}
+bool hdr_record_corrected_values_atomic(struct hdr_histogram* h, int64_t value, int64_t count, int64_t expected_interval)
+{
+ int64_t missing_value;
+
+ if (!hdr_record_values_atomic(h, value, count))
+ {
+ return false;
+ }
+
+ if (expected_interval <= 0 || value <= expected_interval)
+ {
+ return true;
+ }
+
+ missing_value = value - expected_interval;
+ for (; missing_value >= expected_interval; missing_value -= expected_interval)
+ {
+ if (!hdr_record_values_atomic(h, missing_value, count))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
int64_t hdr_add(struct hdr_histogram* h, const struct hdr_histogram* from)
{
struct hdr_iter iter;
- hdr_iter_recorded_init(&iter, from);
int64_t dropped = 0;
+ hdr_iter_recorded_init(&iter, from);
while (hdr_iter_next(&iter))
{
@@ -459,8 +618,8 @@ int64_t hdr_add_while_correcting_for_coordinated_omission(
struct hdr_histogram* h, struct hdr_histogram* from, int64_t expected_interval)
{
struct hdr_iter iter;
- hdr_iter_recorded_init(&iter, from);
int64_t dropped = 0;
+ hdr_iter_recorded_init(&iter, from);
while (hdr_iter_next(&iter))
{
@@ -478,13 +637,13 @@ int64_t hdr_add_while_correcting_for_coordinated_omission(
-// ## ## ### ## ## ## ######## ######
-// ## ## ## ## ## ## ## ## ## ##
-// ## ## ## ## ## ## ## ## ##
-// ## ## ## ## ## ## ## ###### ######
-// ## ## ######### ## ## ## ## ##
-// ## ## ## ## ## ## ## ## ## ##
-// ### ## ## ######## ####### ######## ######
+/* ## ## ### ## ## ## ######## ###### */
+/* ## ## ## ## ## ## ## ## ## ## */
+/* ## ## ## ## ## ## ## ## ## */
+/* ## ## ## ## ## ## ## ###### ###### */
+/* ## ## ######### ## ## ## ## ## */
+/* ## ## ## ## ## ## ## ## ## ## */
+/* ### ## ## ######## ####### ######## ###### */
int64_t hdr_max(const struct hdr_histogram* h)
@@ -507,47 +666,89 @@ int64_t hdr_min(const struct hdr_histogram* h)
return non_zero_min(h);
}
-int64_t hdr_value_at_percentile(const struct hdr_histogram* h, double percentile)
+static int64_t get_value_from_idx_up_to_count(const struct hdr_histogram* h, int64_t count_at_percentile)
{
- struct hdr_iter iter;
- hdr_iter_init(&iter, h);
+ int64_t count_to_idx = 0;
+ count_at_percentile = 0 < count_at_percentile ? count_at_percentile : 1;
+ for (int32_t idx = 0; idx < h->counts_len; idx++)
+ {
+ count_to_idx += h->counts[idx];
+ if (count_to_idx >= count_at_percentile)
+ {
+ return hdr_value_at_index(h, idx);
+ }
+ }
+
+ return 0;
+}
+
+
+int64_t hdr_value_at_percentile(const struct hdr_histogram* h, double percentile)
+{
double requested_percentile = percentile < 100.0 ? percentile : 100.0;
int64_t count_at_percentile =
(int64_t) (((requested_percentile / 100) * h->total_count) + 0.5);
- count_at_percentile = count_at_percentile > 1 ? count_at_percentile : 1;
- int64_t total = 0;
+ int64_t value_from_idx = get_value_from_idx_up_to_count(h, count_at_percentile);
+ if (percentile == 0.0)
+ {
+ return lowest_equivalent_value(h, value_from_idx);
+ }
+ return highest_equivalent_value(h, value_from_idx);
+}
- while (hdr_iter_next(&iter))
+int hdr_value_at_percentiles(const struct hdr_histogram *h, const double *percentiles, int64_t *values, size_t length)
+{
+ if (NULL == percentiles || NULL == values)
{
- total += iter.count;
+ return EINVAL;
+ }
- if (total >= count_at_percentile)
+ struct hdr_iter iter;
+ const int64_t total_count = h->total_count;
+ // to avoid allocations we use the values array for intermediate computation
+ // i.e. to store the expected cumulative count at each percentile
+ for (size_t i = 0; i < length; i++)
+ {
+ const double requested_percentile = percentiles[i] < 100.0 ? percentiles[i] : 100.0;
+ const int64_t count_at_percentile =
+ (int64_t) (((requested_percentile / 100) * total_count) + 0.5);
+ values[i] = count_at_percentile > 1 ? count_at_percentile : 1;
+ }
+
+ hdr_iter_init(&iter, h);
+ int64_t total = 0;
+ size_t at_pos = 0;
+ while (hdr_iter_next(&iter) && at_pos < length)
+ {
+ total += iter.count;
+ while (at_pos < length && total >= values[at_pos])
{
- int64_t value_from_index = iter.value;
- return highest_equivalent_value(h, value_from_index);
+ values[at_pos] = highest_equivalent_value(h, iter.value);
+ at_pos++;
}
}
-
return 0;
}
double hdr_mean(const struct hdr_histogram* h)
{
struct hdr_iter iter;
- int64_t total = 0;
+ int64_t total = 0, count = 0;
+ int64_t total_count = h->total_count;
hdr_iter_init(&iter, h);
- while (hdr_iter_next(&iter))
+ while (hdr_iter_next(&iter) && count < total_count)
{
if (0 != iter.count)
{
+ count += iter.count;
total += iter.count * hdr_median_equivalent_value(h, iter.value);
}
}
- return (total * 1.0) / h->total_count;
+ return (total * 1.0) / total_count;
}
double hdr_stddev(const struct hdr_histogram* h)
@@ -591,13 +792,13 @@ int64_t hdr_count_at_index(const struct hdr_histogram* h, int32_t index)
}
-// #### ######## ######## ######## ### ######## ####### ######## ######
-// ## ## ## ## ## ## ## ## ## ## ## ## ## ##
-// ## ## ## ## ## ## ## ## ## ## ## ## ##
-// ## ## ###### ######## ## ## ## ## ## ######## ######
-// ## ## ## ## ## ######### ## ## ## ## ## ##
-// ## ## ## ## ## ## ## ## ## ## ## ## ## ##
-// #### ## ######## ## ## ## ## ## ####### ## ## ######
+/* #### ######## ######## ######## ### ######## ####### ######## ###### */
+/* ## ## ## ## ## ## ## ## ## ## ## ## ## ## */
+/* ## ## ## ## ## ## ## ## ## ## ## ## ## */
+/* ## ## ###### ######## ## ## ## ## ## ######## ###### */
+/* ## ## ## ## ## ######### ## ## ## ## ## ## */
+/* ## ## ## ## ## ## ## ## ## ## ## ## ## ## */
+/* #### ## ######## ## ## ## ## ## ####### ## ## ###### */
static bool has_buckets(struct hdr_iter* iter)
@@ -621,11 +822,16 @@ static bool move_next(struct hdr_iter* iter)
iter->count = counts_get_normalised(iter->h, iter->counts_index);
iter->cumulative_count += iter->count;
-
- iter->value = hdr_value_at_index(iter->h, iter->counts_index);
- iter->highest_equivalent_value = highest_equivalent_value(iter->h, iter->value);
- iter->lowest_equivalent_value = lowest_equivalent_value(iter->h, iter->value);
- iter->median_equivalent_value = hdr_median_equivalent_value(iter->h, iter->value);
+ const int64_t value = hdr_value_at_index(iter->h, iter->counts_index);
+ const int32_t bucket_index = get_bucket_index(iter->h, value);
+ const int32_t sub_bucket_index = get_sub_bucket_index(value, bucket_index, iter->h->unit_magnitude);
+ const int64_t leq = lowest_equivalent_value_given_bucket_indices(iter->h, bucket_index, sub_bucket_index);
+ const int64_t size_of_equivalent_value_range = size_of_equivalent_value_range_given_bucket_indices(
+ iter->h, bucket_index, sub_bucket_index);
+ iter->lowest_equivalent_value = leq;
+ iter->value = value;
+ iter->highest_equivalent_value = leq + size_of_equivalent_value_range - 1;
+ iter->median_equivalent_value = leq + (size_of_equivalent_value_range >> 1);
return true;
}
@@ -646,7 +852,7 @@ static bool next_value_greater_than_reporting_level_upper_bound(
return peek_next_value_from_index(iter) > reporting_level_upper_bound;
}
-static bool _basic_iter_next(struct hdr_iter *iter)
+static bool basic_iter_next(struct hdr_iter *iter)
{
if (!has_next(iter) || iter->counts_index >= iter->h->counts_len)
{
@@ -658,19 +864,19 @@ static bool _basic_iter_next(struct hdr_iter *iter)
return true;
}
-static void _update_iterated_values(struct hdr_iter* iter, int64_t new_value_iterated_to)
+static void update_iterated_values(struct hdr_iter* iter, int64_t new_value_iterated_to)
{
iter->value_iterated_from = iter->value_iterated_to;
iter->value_iterated_to = new_value_iterated_to;
}
-static bool _all_values_iter_next(struct hdr_iter* iter)
+static bool all_values_iter_next(struct hdr_iter* iter)
{
bool result = move_next(iter);
if (result)
{
- _update_iterated_values(iter, iter->value);
+ update_iterated_values(iter, iter->value);
}
return result;
@@ -689,7 +895,7 @@ void hdr_iter_init(struct hdr_iter* iter, const struct hdr_histogram* h)
iter->value_iterated_from = 0;
iter->value_iterated_to = 0;
- iter->_next_fp = _all_values_iter_next;
+ iter->_next_fp = all_values_iter_next;
}
bool hdr_iter_next(struct hdr_iter* iter)
@@ -697,16 +903,18 @@ bool hdr_iter_next(struct hdr_iter* iter)
return iter->_next_fp(iter);
}
-// ######## ######## ######## ###### ######## ## ## ######## #### ## ######## ######
-// ## ## ## ## ## ## ## ## ### ## ## ## ## ## ## ##
-// ## ## ## ## ## ## ## #### ## ## ## ## ## ##
-// ######## ###### ######## ## ###### ## ## ## ## ## ## ###### ######
-// ## ## ## ## ## ## ## #### ## ## ## ## ##
-// ## ## ## ## ## ## ## ## ### ## ## ## ## ## ##
-// ## ######## ## ## ###### ######## ## ## ## #### ######## ######## ######
+/* ######## ######## ######## ###### ######## ## ## ######## #### ## ######## ###### */
+/* ## ## ## ## ## ## ## ## ### ## ## ## ## ## ## ## */
+/* ## ## ## ## ## ## ## #### ## ## ## ## ## ## */
+/* ######## ###### ######## ## ###### ## ## ## ## ## ## ###### ###### */
+/* ## ## ## ## ## ## ## #### ## ## ## ## ## */
+/* ## ## ## ## ## ## ## ## ### ## ## ## ## ## ## */
+/* ## ######## ## ## ###### ######## ## ## ## #### ######## ######## ###### */
-static bool _percentile_iter_next(struct hdr_iter* iter)
+static bool percentile_iter_next(struct hdr_iter* iter)
{
+ int64_t temp, half_distance, percentile_reporting_ticks;
+
struct hdr_iter_percentiles* percentiles = &iter->specifics.percentiles;
if (!has_next(iter))
@@ -722,7 +930,7 @@ static bool _percentile_iter_next(struct hdr_iter* iter)
return true;
}
- if (iter->counts_index == -1 && !_basic_iter_next(iter))
+ if (iter->counts_index == -1 && !basic_iter_next(iter))
{
return false;
}
@@ -733,18 +941,18 @@ static bool _percentile_iter_next(struct hdr_iter* iter)
if (iter->count != 0 &&
percentiles->percentile_to_iterate_to <= current_percentile)
{
- _update_iterated_values(iter, highest_equivalent_value(iter->h, iter->value));
+ update_iterated_values(iter, highest_equivalent_value(iter->h, iter->value));
percentiles->percentile = percentiles->percentile_to_iterate_to;
- int64_t temp = (int64_t)(log(100 / (100.0 - (percentiles->percentile_to_iterate_to))) / log(2)) + 1;
- int64_t half_distance = (int64_t) pow(2, (double) temp);
- int64_t percentile_reporting_ticks = percentiles->ticks_per_half_distance * half_distance;
+ temp = (int64_t)(log(100 / (100.0 - (percentiles->percentile_to_iterate_to))) / log(2)) + 1;
+ half_distance = (int64_t) pow(2, (double) temp);
+ percentile_reporting_ticks = percentiles->ticks_per_half_distance * half_distance;
percentiles->percentile_to_iterate_to += 100.0 / percentile_reporting_ticks;
return true;
}
}
- while (_basic_iter_next(iter));
+ while (basic_iter_next(iter));
return true;
}
@@ -760,7 +968,7 @@ void hdr_iter_percentile_init(struct hdr_iter* iter, const struct hdr_histogram*
iter->specifics.percentiles.percentile_to_iterate_to = 0.0;
iter->specifics.percentiles.percentile = 0.0;
- iter->_next_fp = _percentile_iter_next;
+ iter->_next_fp = percentile_iter_next;
}
static void format_line_string(char* str, size_t len, int significant_figures, format_type format)
@@ -790,22 +998,22 @@ static void format_line_string(char* str, size_t len, int significant_figures, f
}
-// ######## ######## ###### ####### ######## ######## ######## ########
-// ## ## ## ## ## ## ## ## ## ## ## ## ## ##
-// ## ## ## ## ## ## ## ## ## ## ## ## ##
-// ######## ###### ## ## ## ######## ## ## ###### ## ##
-// ## ## ## ## ## ## ## ## ## ## ## ## ##
-// ## ## ## ## ## ## ## ## ## ## ## ## ## ##
-// ## ## ######## ###### ####### ## ## ######## ######## ########
+/* ######## ######## ###### ####### ######## ######## ######## ######## */
+/* ## ## ## ## ## ## ## ## ## ## ## ## ## ## */
+/* ## ## ## ## ## ## ## ## ## ## ## ## ## */
+/* ######## ###### ## ## ## ######## ## ## ###### ## ## */
+/* ## ## ## ## ## ## ## ## ## ## ## ## ## */
+/* ## ## ## ## ## ## ## ## ## ## ## ## ## ## */
+/* ## ## ######## ###### ####### ## ## ######## ######## ######## */
-static bool _recorded_iter_next(struct hdr_iter* iter)
+static bool recorded_iter_next(struct hdr_iter* iter)
{
- while (_basic_iter_next(iter))
+ while (basic_iter_next(iter))
{
if (iter->count != 0)
{
- _update_iterated_values(iter, iter->value);
+ update_iterated_values(iter, iter->value);
iter->specifics.recorded.count_added_in_this_iteration_step = iter->count;
return true;
@@ -821,19 +1029,19 @@ void hdr_iter_recorded_init(struct hdr_iter* iter, const struct hdr_histogram* h
iter->specifics.recorded.count_added_in_this_iteration_step = 0;
- iter->_next_fp = _recorded_iter_next;
+ iter->_next_fp = recorded_iter_next;
}
-// ## #### ## ## ######## ### ########
-// ## ## ### ## ## ## ## ## ##
-// ## ## #### ## ## ## ## ## ##
-// ## ## ## ## ## ###### ## ## ########
-// ## ## ## #### ## ######### ## ##
-// ## ## ## ### ## ## ## ## ##
-// ######## #### ## ## ######## ## ## ## ##
+/* ## #### ## ## ######## ### ######## */
+/* ## ## ### ## ## ## ## ## ## */
+/* ## ## #### ## ## ## ## ## ## */
+/* ## ## ## ## ## ###### ## ## ######## */
+/* ## ## ## #### ## ######### ## ## */
+/* ## ## ## ### ## ## ## ## ## */
+/* ######## #### ## ## ######## ## ## ## ## */
-static bool _iter_linear_next(struct hdr_iter* iter)
+static bool iter_linear_next(struct hdr_iter* iter)
{
struct hdr_iter_linear* linear = &iter->specifics.linear;
@@ -847,7 +1055,7 @@ static bool _iter_linear_next(struct hdr_iter* iter)
{
if (iter->value >= linear->next_value_reporting_level_lowest_equivalent)
{
- _update_iterated_values(iter, linear->next_value_reporting_level);
+ update_iterated_values(iter, linear->next_value_reporting_level);
linear->next_value_reporting_level += linear->value_units_per_bucket;
linear->next_value_reporting_level_lowest_equivalent =
@@ -879,18 +1087,18 @@ void hdr_iter_linear_init(struct hdr_iter* iter, const struct hdr_histogram* h,
iter->specifics.linear.next_value_reporting_level = value_units_per_bucket;
iter->specifics.linear.next_value_reporting_level_lowest_equivalent = lowest_equivalent_value(h, value_units_per_bucket);
- iter->_next_fp = _iter_linear_next;
+ iter->_next_fp = iter_linear_next;
}
-// ## ####### ###### ### ######## #### ######## ## ## ## ## #### ######
-// ## ## ## ## ## ## ## ## ## ## ## ## ## ### ### ## ## ##
-// ## ## ## ## ## ## ## ## ## ## ## ## #### #### ## ##
-// ## ## ## ## #### ## ## ######## ## ## ######### ## ### ## ## ##
-// ## ## ## ## ## ######### ## ## ## ## ## ## ## ## ## ##
-// ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
-// ######## ####### ###### ## ## ## ## #### ## ## ## ## ## #### ######
+/* ## ####### ###### ### ######## #### ######## ## ## ## ## #### ###### */
+/* ## ## ## ## ## ## ## ## ## ## ## ## ## ### ### ## ## ## */
+/* ## ## ## ## ## ## ## ## ## ## ## ## #### #### ## ## */
+/* ## ## ## ## #### ## ## ######## ## ## ######### ## ### ## ## ## */
+/* ## ## ## ## ## ######### ## ## ## ## ## ## ## ## ## ## */
+/* ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## */
+/* ######## ####### ###### ## ## ## ## #### ## ## ## ## ## #### ###### */
-static bool _log_iter_next(struct hdr_iter *iter)
+static bool log_iter_next(struct hdr_iter *iter)
{
struct hdr_iter_log* logarithmic = &iter->specifics.log;
@@ -904,7 +1112,7 @@ static bool _log_iter_next(struct hdr_iter *iter)
{
if (iter->value >= logarithmic->next_value_reporting_level_lowest_equivalent)
{
- _update_iterated_values(iter, logarithmic->next_value_reporting_level);
+ update_iterated_values(iter, logarithmic->next_value_reporting_level);
logarithmic->next_value_reporting_level *= (int64_t)logarithmic->log_base;
logarithmic->next_value_reporting_level_lowest_equivalent = lowest_equivalent_value(iter->h, logarithmic->next_value_reporting_level);
@@ -937,10 +1145,10 @@ void hdr_iter_log_init(
iter->specifics.log.next_value_reporting_level = value_units_first_bucket;
iter->specifics.log.next_value_reporting_level_lowest_equivalent = lowest_equivalent_value(h, value_units_first_bucket);
- iter->_next_fp = _log_iter_next;
+ iter->_next_fp = log_iter_next;
}
-// Printing.
+/* Printing. */
static const char* format_head_string(format_type format)
{
@@ -949,7 +1157,6 @@ static const char* format_head_string(format_type format)
case CSV:
return "%s,%s,%s,%s\n";
case CLASSIC:
- return "%12s %12s %12s %12s\n\n";
default:
return "%12s %12s %12s %12s\n\n";
}
@@ -965,11 +1172,14 @@ int hdr_percentiles_print(
double value_scale, format_type format)
{
char line_format[25];
- format_line_string(line_format, 25, h->significant_figures, format);
- const char* head_format = format_head_string(format);
+ const char* head_format;
int rc = 0;
-
struct hdr_iter iter;
+ struct hdr_iter_percentiles * percentiles;
+
+ format_line_string(line_format, 25, h->significant_figures, format);
+ head_format = format_head_string(format);
+
hdr_iter_percentile_init(&iter, h, ticks_per_half_distance);
if (fprintf(
@@ -980,7 +1190,7 @@ int hdr_percentiles_print(
goto cleanup;
}
- struct hdr_iter_percentiles * percentiles = &iter.specifics.percentiles;
+ percentiles = &iter.specifics.percentiles;
while (hdr_iter_next(&iter))
{
double value = iter.highest_equivalent_value / value_scale;
diff --git a/vendors/hdr_histogram/hdr_histogram.h b/vendors/hdr/hdr_histogram.h
index 14eebdd..59ffe54 100644
--- a/vendors/hdr_histogram/hdr_histogram.h
+++ b/vendors/hdr/hdr_histogram.h
@@ -16,7 +16,7 @@
struct hdr_histogram
{
- int64_t lowest_trackable_value;
+ int64_t lowest_discernible_value;
int64_t highest_trackable_value;
int32_t unit_magnitude;
int32_t significant_figures;
@@ -43,11 +43,10 @@ extern "C" {
*
* Due to the size of the histogram being the result of some reasonably
* involved math on the input parameters this function it is tricky to stack allocate.
- * The histogram is allocated in a single contigious block so can be delete via free,
- * without any structure specific destructor.
+ * The histogram should be released with hdr_close
*
- * @param lowest_trackable_value The smallest possible value to be put into the
- * histogram.
+ * @param lowest_discernible_value The smallest possible value that is distinguishable from 0.
+ * Must be a positive integer that is >= 1. May be internally rounded down to nearest power of 2.
* @param highest_trackable_value The largest possible value to be put into the
* histogram.
* @param significant_figures The level of precision for this histogram, i.e. the number
@@ -55,12 +54,12 @@ extern "C" {
* the results from the histogram will be accurate up to the first three digits. Must
* be a value between 1 and 5 (inclusive).
* @param result Output parameter to capture allocated histogram.
- * @return 0 on success, EINVAL if lowest_trackable_value is < 1 or the
+ * @return 0 on success, EINVAL if lowest_discernible_value is < 1 or the
* significant_figure value is outside of the allowed range, ENOMEM if malloc
* failed.
*/
int hdr_init(
- int64_t lowest_trackable_value,
+ int64_t lowest_discernible_value,
int64_t highest_trackable_value,
int significant_figures,
struct hdr_histogram** result);
@@ -112,6 +111,21 @@ size_t hdr_get_memory_size(struct hdr_histogram* h);
bool hdr_record_value(struct hdr_histogram* h, int64_t value);
/**
+ * Records a value in the histogram, will round this value of to a precision at or better
+ * than the significant_figure specified at construction time.
+ *
+ * Will record this value atomically, however the whole structure may appear inconsistent
+ * when read concurrently with this update. Do NOT mix calls to this method with calls
+ * to non-atomic updates.
+ *
+ * @param h "This" pointer
+ * @param value Value to add to the histogram
+ * @return false if the value is larger than the highest_trackable_value and can't be recorded,
+ * true otherwise.
+ */
+bool hdr_record_value_atomic(struct hdr_histogram* h, int64_t value);
+
+/**
* Records count values in the histogram, will round this value of to a
* precision at or better than the significant_figure specified at construction
* time.
@@ -124,15 +138,31 @@ bool hdr_record_value(struct hdr_histogram* h, int64_t value);
*/
bool hdr_record_values(struct hdr_histogram* h, int64_t value, int64_t count);
+/**
+ * Records count values in the histogram, will round this value of to a
+ * precision at or better than the significant_figure specified at construction
+ * time.
+ *
+ * Will record this value atomically, however the whole structure may appear inconsistent
+ * when read concurrently with this update. Do NOT mix calls to this method with calls
+ * to non-atomic updates.
+ *
+ * @param h "This" pointer
+ * @param value Value to add to the histogram
+ * @param count Number of 'value's to add to the histogram
+ * @return false if any value is larger than the highest_trackable_value and can't be recorded,
+ * true otherwise.
+ */
+bool hdr_record_values_atomic(struct hdr_histogram* h, int64_t value, int64_t count);
/**
* Record a value in the histogram and backfill based on an expected interval.
*
* Records a value in the histogram, will round this value of to a precision at or better
- * than the significant_figure specified at contruction time. This is specifically used
+ * than the significant_figure specified at construction time. This is specifically used
* for recording latency. If the value is larger than the expected_interval then the
* latency recording system has experienced co-ordinated omission. This method fills in the
- * values that would have occured had the client providing the load not been blocked.
+ * values that would have occurred had the client providing the load not been blocked.
* @param h "This" pointer
* @param value Value to add to the histogram
@@ -140,7 +170,29 @@ bool hdr_record_values(struct hdr_histogram* h, int64_t value, int64_t count);
* @return false if the value is larger than the highest_trackable_value and can't be recorded,
* true otherwise.
*/
-bool hdr_record_corrected_value(struct hdr_histogram* h, int64_t value, int64_t expexcted_interval);
+bool hdr_record_corrected_value(struct hdr_histogram* h, int64_t value, int64_t expected_interval);
+
+/**
+ * Record a value in the histogram and backfill based on an expected interval.
+ *
+ * Records a value in the histogram, will round this value of to a precision at or better
+ * than the significant_figure specified at construction time. This is specifically used
+ * for recording latency. If the value is larger than the expected_interval then the
+ * latency recording system has experienced co-ordinated omission. This method fills in the
+ * values that would have occurred had the client providing the load not been blocked.
+ *
+ * Will record this value atomically, however the whole structure may appear inconsistent
+ * when read concurrently with this update. Do NOT mix calls to this method with calls
+ * to non-atomic updates.
+ *
+ * @param h "This" pointer
+ * @param value Value to add to the histogram
+ * @param expected_interval The delay between recording values.
+ * @return false if the value is larger than the highest_trackable_value and can't be recorded,
+ * true otherwise.
+ */
+bool hdr_record_corrected_value_atomic(struct hdr_histogram* h, int64_t value, int64_t expected_interval);
+
/**
* Record a value in the histogram 'count' times. Applies the same correcting logic
* as 'hdr_record_corrected_value'.
@@ -155,9 +207,26 @@ bool hdr_record_corrected_value(struct hdr_histogram* h, int64_t value, int64_t
bool hdr_record_corrected_values(struct hdr_histogram* h, int64_t value, int64_t count, int64_t expected_interval);
/**
+ * Record a value in the histogram 'count' times. Applies the same correcting logic
+ * as 'hdr_record_corrected_value'.
+ *
+ * Will record this value atomically, however the whole structure may appear inconsistent
+ * when read concurrently with this update. Do NOT mix calls to this method with calls
+ * to non-atomic updates.
+ *
+ * @param h "This" pointer
+ * @param value Value to add to the histogram
+ * @param count Number of 'value's to add to the histogram
+ * @param expected_interval The delay between recording values.
+ * @return false if the value is larger than the highest_trackable_value and can't be recorded,
+ * true otherwise.
+ */
+bool hdr_record_corrected_values_atomic(struct hdr_histogram* h, int64_t value, int64_t count, int64_t expected_interval);
+
+/**
* Adds all of the values from 'from' to 'this' histogram. Will return the
* number of values that are dropped when copying. Values will be dropped
- * if they around outside of h.lowest_trackable_value and
+ * if they around outside of h.lowest_discernible_value and
* h.highest_trackable_value.
*
* @param h "This" pointer
@@ -169,7 +238,7 @@ int64_t hdr_add(struct hdr_histogram* h, const struct hdr_histogram* from);
/**
* Adds all of the values from 'from' to 'this' histogram. Will return the
* number of values that are dropped when copying. Values will be dropped
- * if they around outside of h.lowest_trackable_value and
+ * if they around outside of h.lowest_discernible_value and
* h.highest_trackable_value.
*
* @param h "This" pointer
@@ -204,6 +273,18 @@ int64_t hdr_max(const struct hdr_histogram* h);
int64_t hdr_value_at_percentile(const struct hdr_histogram* h, double percentile);
/**
+ * Get the values at the given percentiles.
+ *
+ * @param h "This" pointer.
+ * @param percentiles The ordered percentiles array to get the values for.
+ * @param length Number of elements in the arrays.
+ * @param values Destination array containing the values at the given percentiles.
+ * The values array should be allocated by the caller.
+ * @return 0 on success, ENOMEM if the provided destination array is null.
+ */
+int hdr_value_at_percentiles(const struct hdr_histogram *h, const double *percentiles, int64_t *values, size_t length);
+
+/**
* Gets the standard deviation for the values in the histogram.
*
* @param h "This" pointer
@@ -300,7 +381,7 @@ struct hdr_iter
/** raw index into the counts array */
int32_t counts_index;
/** snapshot of the length at the time the iterator is created */
- int32_t total_count;
+ int64_t total_count;
/** value directly from array for the current counts_index */
int64_t count;
/** sum of all of the counts up to and including the count at this index */
@@ -396,7 +477,7 @@ int hdr_percentiles_print(
*/
struct hdr_histogram_bucket_config
{
- int64_t lowest_trackable_value;
+ int64_t lowest_discernible_value;
int64_t highest_trackable_value;
int64_t unit_magnitude;
int64_t significant_figures;
@@ -409,7 +490,7 @@ struct hdr_histogram_bucket_config
};
int hdr_calculate_bucket_config(
- int64_t lowest_trackable_value,
+ int64_t lowest_discernible_value,
int64_t highest_trackable_value,
int significant_figures,
struct hdr_histogram_bucket_config* cfg);
@@ -423,7 +504,7 @@ int64_t hdr_next_non_equivalent_value(const struct hdr_histogram* h, int64_t val
int64_t hdr_median_equivalent_value(const struct hdr_histogram* h, int64_t value);
/**
- * Used to reset counters after importing data manuallying into the histogram, used by the logging code
+ * Used to reset counters after importing data manually into the histogram, used by the logging code
* and other custom serialisation tools.
*/
void hdr_reset_internal_counters(struct hdr_histogram* h);
diff --git a/vendors/hdr_histogram/hdr_histogram_log.c b/vendors/hdr/hdr_histogram_log.c
index 06ab81a..06ab81a 100644
--- a/vendors/hdr_histogram/hdr_histogram_log.c
+++ b/vendors/hdr/hdr_histogram_log.c
diff --git a/vendors/hdr_histogram/hdr_histogram_log.h b/vendors/hdr/hdr_histogram_log.h
index c1842b2..c1842b2 100644
--- a/vendors/hdr_histogram/hdr_histogram_log.h
+++ b/vendors/hdr/hdr_histogram_log.h
diff --git a/vendors/hdr/hdr_malloc.h b/vendors/hdr/hdr_malloc.h
new file mode 100644
index 0000000..6fefc68
--- /dev/null
+++ b/vendors/hdr/hdr_malloc.h
@@ -0,0 +1,19 @@
+/**
+ * hdr_malloc.h
+ * Written by Filipe Oliveira and released to the public domain,
+ * as explained at http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Allocator selection.
+ *
+ * This file is used in order to change the HdrHistogram allocator at compile time.
+ * Just define the following defines to what you want to use. Also add
+ * the include of your alternate allocator if needed (not needed in order
+ * to use the default libc allocator). */
+
+#ifndef HDR_MALLOC_H__
+#define HDR_MALLOC_H__
+#define hdr_malloc malloc
+#define hdr_calloc calloc
+#define hdr_realloc realloc
+#define hdr_free free
+#endif
diff --git a/vendors/hdr/hdr_tests.h b/vendors/hdr/hdr_tests.h
new file mode 100644
index 0000000..5cc65a0
--- /dev/null
+++ b/vendors/hdr/hdr_tests.h
@@ -0,0 +1,22 @@
+#ifndef HDR_TESTS_H
+#define HDR_TESTS_H
+
+/* These are functions used in tests and are not intended for normal usage. */
+
+#include <hdr/hdr_histogram.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int32_t counts_index_for(const struct hdr_histogram* h, int64_t value);
+int hdr_encode_compressed(struct hdr_histogram* h, uint8_t** compressed_histogram, size_t* compressed_len);
+int hdr_decode_compressed(uint8_t* buffer, size_t length, struct hdr_histogram** histogram);
+void hdr_base64_decode_block(const char* input, uint8_t* output);
+void hdr_base64_encode_block(const uint8_t* input, char* output);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/vendors/hdr/hdr_time.c b/vendors/hdr/hdr_time.c
new file mode 100644
index 0000000..feebb56
--- /dev/null
+++ b/vendors/hdr/hdr_time.c
@@ -0,0 +1,97 @@
+/**
+* hdr_time.h
+* Written by Michael Barker and Philip Orwig and released to the public domain,
+* as explained at http://creativecommons.org/publicdomain/zero/1.0/
+*/
+
+#include <math.h>
+
+#include <hdr/hdr_time.h>
+
+#if defined(_WIN32) || defined(_WIN64)
+
+#if !defined(WIN32_LEAN_AND_MEAN)
+#define WIN32_LEAN_AND_MEAN
+#endif
+
+#include <windows.h>
+
+static int s_clockPeriodSet = 0;
+static double s_clockPeriod = 1.0;
+
+void hdr_gettime(hdr_timespec* t)
+{
+ LARGE_INTEGER num;
+ /* if this is distasteful, we can add in an hdr_time_init() */
+ if (!s_clockPeriodSet)
+ {
+ QueryPerformanceFrequency(&num);
+ s_clockPeriod = 1.0 / (double) num.QuadPart;
+ s_clockPeriodSet = 1;
+ }
+
+ QueryPerformanceCounter(&num);
+ double seconds = num.QuadPart * s_clockPeriod;
+ double integral;
+ double remainder = modf(seconds, &integral);
+
+ t->tv_sec = (long) integral;
+ t->tv_nsec = (long) (remainder * 1000000000);
+}
+
+#elif defined(__APPLE__)
+
+#include <mach/clock.h>
+#include <mach/mach.h>
+
+
+void hdr_gettime(hdr_timespec* ts)
+{
+ clock_serv_t cclock;
+ mach_timespec_t mts;
+ host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
+ clock_get_time(cclock, &mts);
+ mach_port_deallocate(mach_task_self(), cclock);
+ ts->tv_sec = mts.tv_sec;
+ ts->tv_nsec = mts.tv_nsec;
+}
+
+
+void hdr_getnow(hdr_timespec* ts)
+{
+ hdr_gettime(ts);
+}
+
+#elif defined(__linux__) || defined(__CYGWIN__) || defined(__OpenBSD__)
+
+
+void hdr_gettime(hdr_timespec* t)
+{
+ clock_gettime(CLOCK_MONOTONIC, (struct timespec*)t);
+}
+
+void hdr_getnow(hdr_timespec* t)
+{
+ clock_gettime(CLOCK_REALTIME, (struct timespec*)t);
+}
+
+#else
+
+#warning "Platform not supported\n"
+
+#endif
+
+double hdr_timespec_as_double(const hdr_timespec* t)
+{
+ double d = t->tv_sec;
+ return d + (t->tv_nsec / 1000000000.0);
+}
+
+void hdr_timespec_from_double(hdr_timespec* t, double value)
+{
+ int seconds = (int) value;
+ int milliseconds = (int) round((value - seconds) * 1000);
+
+ t->tv_sec = seconds;
+ t->tv_nsec = milliseconds * 1000000;
+}
diff --git a/vendors/hdr/hdr_time.h b/vendors/hdr/hdr_time.h
new file mode 100644
index 0000000..3bdeec1
--- /dev/null
+++ b/vendors/hdr/hdr_time.h
@@ -0,0 +1,47 @@
+/**
+ * hdr_time.h
+ * Written by Michael Barker and released to the public domain,
+ * as explained at http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+#ifndef HDR_TIME_H__
+#define HDR_TIME_H__
+
+#include <time.h>
+
+#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
+
+typedef struct hdr_timespec
+{
+ long tv_sec;
+ long tv_nsec;
+} hdr_timespec;
+
+#else
+
+typedef struct timespec hdr_timespec;
+
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(_MSC_VER)
+void hdr_gettime(hdr_timespec* t);
+#else
+void hdr_gettime(hdr_timespec* t);
+#endif
+
+void hdr_getnow(hdr_timespec* t);
+
+double hdr_timespec_as_double(const hdr_timespec* t);
+
+/* Assumes only millisecond accuracy. */
+void hdr_timespec_from_double(hdr_timespec* t, double value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif