From c1abada7ba763988904644a7a52995007da1209e Mon Sep 17 00:00:00 2001 From: amir Date: Wed, 11 Mar 2026 17:48:36 +0100 Subject: [PATCH] Updating the LF MPMC queue and replacing DirQueue with it Making the MPMC queue support when producers are consumers at the same time by adding a variable work, mpmc_push_work() that increments work and mpmc_task_done() that decrements work, and if work = 0 calls mpmc_producers_finished() that pushes poinsons to wake up sleeping threads and make them return NULL Replacing DirQueue, a queue growable with realloc with the MPMC queue --- .gitignore | 2 +- base.h | 7 - binaries/changelog.txt | 4 + binaries/file_hasher_v4.0.exe | Bin 0 -> 215040 bytes lf_mpmc.h | 46 -- platform.h | 44 +- platform_windows.c | 125 ++---- xxh_x86dispatch.c | 821 ++++++++++++++++++++++++++++++++++ xxh_x86dispatch.h | 93 ++++ 9 files changed, 980 insertions(+), 162 deletions(-) create mode 100644 binaries/file_hasher_v4.0.exe create mode 100644 xxh_x86dispatch.c create mode 100644 xxh_x86dispatch.h diff --git a/.gitignore b/.gitignore index 4ae4fd8..c15abe7 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,4 @@ file_hasher.rdi file_hasher.exe file_hashes.txt file_list.txt -temp.c +temp_code.c diff --git a/base.h b/base.h index 10dd18a..2ac8251 100644 --- a/base.h +++ b/base.h @@ -29,13 +29,6 @@ #include #endif -#define XXH_VECTOR \ - XXH_AVX2 // not recommanded to compile with gcc see xxhash.h line 4082 - // Must compile with /arch:AVX2 in clang-cl or -mavx2 in clang/gcc -#define XXH_INLINE_ALL -#include "xxhash.c" -#include "xxhash.h" - /* ------------------------------------------------------------ Base types ------------------------------------------------------------ */ diff --git a/binaries/changelog.txt b/binaries/changelog.txt index d464b0c..f346008 100644 --- a/binaries/changelog.txt +++ b/binaries/changelog.txt @@ -37,3 +37,7 @@ Align the MPMC queue to pagesize Getting file size from FindFirstFileA() instead of CreateFileA(), since we already call FindFirstFileA() and it returns the size there is no need to open/close every file to get it's size Replacing Malloc and strdup in scan helper function with FileEntry and path arenas + +Making the MPMC queue support when producers are consumers at the same time by adding a variable work, mpmc_push_work() that increments work and mpmc_task_done() that decrements work, and if work = 0 calls mpmc_producers_finished() that pushes poinsons to wake up sleeping threads and make them return NULL + +Replacing DirQueue, a queue growable with realloc with the MPMC queue diff --git a/binaries/file_hasher_v4.0.exe b/binaries/file_hasher_v4.0.exe new file mode 100644 index 0000000000000000000000000000000000000000..75e93c82d9a9ff853305832508ff5039c7178e02 GIT binary patch literal 215040 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%0D2in`G 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 literal 0 HcmV?d00001 diff --git a/lf_mpmc.h b/lf_mpmc.h index 640b874..0524923 100644 --- a/lf_mpmc.h +++ b/lf_mpmc.h @@ -279,52 +279,6 @@ static void *mpmc_pop(MPMCQueue *q) { return data; } -/* ----------------------------------------------------------- */ -/* TRY POP (non blocking) */ -/* ----------------------------------------------------------- */ -// static b32 mpmc_try_pop(MPMCQueue *q, void **out) { -// -// if (!plat_sem_trywait(&q->items_sem)) -// return false; -// -// MPMCSlot *slot; -// size_t pos; -// -// int spins = 0; -// -// for (;;) { -// -// pos = atomic_load_explicit(&q->head, memory_order_relaxed); -// slot = &q->slots[pos & q->mask]; -// -// size_t seq = atomic_load_explicit(&slot->seq, memory_order_acquire); -// intptr_t diff = (intptr_t)seq - (intptr_t)(pos + 1); -// -// if (likely(diff == 0)) { -// -// if (atomic_compare_exchange_weak_explicit(&q->head, &pos, pos + 1, -// memory_order_relaxed, -// memory_order_relaxed)) -// break; -// -// } else { -// -// if (++spins > 10) { -// SwitchToThread(); -// spins = 0; -// } else { -// cpu_pause(); -// } -// } -// } -// -// *out = slot->data; -// -// atomic_store_explicit(&slot->seq, pos + q->capacity, memory_order_release); -// -// return true; -// } - /* ----------------------------------------------------------- */ /* PUSH POISON */ /* ----------------------------------------------------------- */ diff --git a/platform.h b/platform.h index 088d564..72cf37b 100644 --- a/platform.h +++ b/platform.h @@ -6,6 +6,14 @@ #include "lf_mpmc.h" #include "arena.c" + +#define XXH_VECTOR \ + XXH_AVX2 // not recommanded to compile with gcc see xxhash.h line 4082 + // Must compile with /arch:AVX2 in clang-cl or -mavx2 in clang/gcc +#define XXH_INLINE_ALL +#include "xxhash.c" +#include "xxhash.h" + // ----------------------------- Config ------------------------------------- #define FILE_HASHES_TXT "file_hashes.txt" #define HASH_STRLEN 33 // 128-bit hex (32 chars) + null @@ -45,43 +53,19 @@ static double timer_stop(HiResTimer *t) { (double)g_qpc_freq.QuadPart; } -/* Scan folders */ - -typedef struct DirQueue DirQueue; - -typedef struct DirQueue { - char **items; - size_t count; - size_t cap; - size_t active; - - int stop; - -#if PLATFORM_WINDOWS - CRITICAL_SECTION cs; - CONDITION_VARIABLE cv; -#else - pthread_mutex_t mutex; - pthread_cond_t cond; -#endif -} DirQueue; - -// MPMC Queue - -static MPMCQueue g_dir_queue; -static MPMCQueue g_file_queue; +// Workers context typedef struct { - DirQueue *dir_queue; + u8 num_threads; mem_arena *path_arena; mem_arena *meta_arena; + + MPMCQueue *dir_queue; + MPMCQueue *file_queue; } ScannerContext; typedef struct { mem_arena *arena; + MPMCQueue *file_queue; } WorkerContext; - -// void scan_folder_windows_parallel(const char *base, ScannerContext *ctx); -// void scan_folder_posix_parallel(const char *base, ScannerContext *ctx); -// diff --git a/platform_windows.c b/platform_windows.c index e54312f..68ade97 100644 --- a/platform_windows.c +++ b/platform_windows.c @@ -1,4 +1,3 @@ -#include "arena.h" #include "platform.h" // ----------------------------- Globals ------------------------------------ @@ -104,48 +103,6 @@ void platform_get_file_owner(const char *path, char *out_owner, get_file_owner(path, out_owner, out_owner_size); } -// --------------- parallel directory scanning ---------------- -// Add queue helper functions -static void dirqueue_push(DirQueue *q, const char *path) { - EnterCriticalSection(&q->cs); - - if (q->count + 1 > q->cap) { - q->cap = q->cap ? q->cap * 2 : 1024; - q->items = realloc(q->items, q->cap * sizeof(char *)); - } - - q->items[q->count++] = _strdup(path); - - WakeConditionVariable(&q->cv); - LeaveCriticalSection(&q->cs); -} - -static char *dirqueue_pop(DirQueue *q) { - EnterCriticalSection(&q->cs); - - while (q->count == 0 && q->active > 0) { - SleepConditionVariableCS(&q->cv, &q->cs, INFINITE); - } - - if (q->count == 0 && q->active == 0) { - LeaveCriticalSection(&q->cs); - return NULL; // truly done - } - - char *dir = q->items[--q->count]; - q->active++; - - LeaveCriticalSection(&q->cs); - return dir; -} - -static void dirqueue_done(DirQueue *q) { - EnterCriticalSection(&q->cs); - q->active--; - WakeAllConditionVariable(&q->cv); - LeaveCriticalSection(&q->cs); -} - // ----------------------------- Scan helpers ----------------------------- void scan_folder_windows_parallel(const char *base, ScannerContext *ctx) { char search[MAX_PATHLEN]; @@ -167,7 +124,12 @@ void scan_folder_windows_parallel(const char *base, ScannerContext *ctx) { continue; if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - dirqueue_push(ctx->dir_queue, full); + size_t len = strlen(full) + 1; + + char *dir = arena_push(&ctx->path_arena, len, false); + memcpy(dir, full, len); + + mpmc_push_work(ctx->dir_queue, dir); } else { atomic_fetch_add(&g_files_found, 1); @@ -192,7 +154,7 @@ void scan_folder_windows_parallel(const char *base, ScannerContext *ctx) { fe->size_bytes = ((uint64_t)fd.nFileSizeHigh << 32) | fd.nFileSizeLow; - mpmc_push(&g_file_queue, fe); + mpmc_push(ctx->file_queue, fe); } } while (FindNextFileA(h, &fd)); @@ -203,19 +165,16 @@ void scan_folder_windows_parallel(const char *base, ScannerContext *ctx) { // ------------------------- Scan worker -------------------------------- static DWORD WINAPI scan_worker(LPVOID arg) { ScannerContext *ctx = arg; - DirQueue *q = ctx->dir_queue; for (;;) { - char *dir = dirqueue_pop(q); + char *dir = mpmc_pop(ctx->dir_queue); if (!dir) break; scan_folder_windows_parallel(dir, ctx); - free(dir); - dirqueue_done(q); + mpmc_task_done(ctx->dir_queue, ctx->num_threads); } - return 0; } @@ -252,11 +211,10 @@ static void xxh3_hash_file_stream(const char *path, char *out_hex, BYTE *buf) { static DWORD WINAPI hash_worker(LPVOID arg) { WorkerContext *ctx = (WorkerContext *)arg; - mem_arena *local_arena = ctx->arena; BYTE *buf = (BYTE *)malloc(READ_BLOCK); for (;;) { - FileEntry *fe = mpmc_pop(&g_file_queue); + FileEntry *fe = mpmc_pop(ctx->file_queue); if (!fe) break; @@ -275,12 +233,12 @@ static DWORD WINAPI hash_worker(LPVOID arg) { snprintf(stack_buf, sizeof(stack_buf), "%s\t%s\t%.2f\t%s\t%s\t%s\n", hash, fe->path, size_kib, created, modified, fe->owner); - char *dst = arena_push(&local_arena, len, false); + char *dst = arena_push(&ctx->arena, len, false); memcpy(dst, stack_buf, len); atomic_fetch_add(&g_files_hashed, 1); } - free(buf); + // free(buf); It will be freed by the system when the program exits return 0; } @@ -420,9 +378,7 @@ int main(int argc, char **argv) { folder_count = 1; } - // ------------------------------- // Display selected folders - // ------------------------------- printf("Processing %d folder(s):\n", folder_count); for (int i = 0; i < folder_count; ++i) { printf(" - %s\n", folders[i]); @@ -472,20 +428,13 @@ int main(int argc, char **argv) { size_t num_threads = hw_threads * 2; // ------------------------------- - // Step 1: Scan all folders + // Scanning and hashing // ------------------------------- + MPMCQueue dir_queue; + mpmc_init(&dir_queue, MiB(1)); - mpmc_init(&g_file_queue, MiB(1)); - - DirQueue q; - memset(&q, 0, sizeof(q)); - InitializeCriticalSection(&q.cs); - InitializeConditionVariable(&q.cv); - q.active = 0; - - for (int i = 0; i < folder_count; ++i) { - dirqueue_push(&q, folders[i]); - } + MPMCQueue file_queue; + mpmc_init(&file_queue, MiB(1)); // starting hash threads size_t num_hash_threads = num_threads; @@ -498,6 +447,7 @@ int main(int argc, char **argv) { for (size_t i = 0; i < num_hash_threads; ++i) { workers[i].arena = arena_create(¶ms); + workers[i].file_queue = &file_queue; hash_threads[i] = CreateThread(NULL, 0, hash_worker, &workers[i], 0, NULL); } @@ -514,26 +464,40 @@ int main(int argc, char **argv) { arena_push(&gp_arena, sizeof(HANDLE) * num_scan_threads, true); for (size_t i = 0; i < num_scan_threads; i++) { - - scanners[i].dir_queue = &q; + scanners[i].num_threads = num_scan_threads; scanners[i].path_arena = arena_create(¶ms); scanners[i].meta_arena = arena_create(¶ms); + scanners[i].dir_queue = &dir_queue; + scanners[i].file_queue = &file_queue; + scan_threads[i] = CreateThread(NULL, 0, scan_worker, &scanners[i], 0, NULL); } - WaitForMultipleObjects((DWORD)num_scan_threads, scan_threads, TRUE, INFINITE); + // Initial folder push + for (int i = 0; i < folder_count; i++) { - for (size_t i = 0; i < num_hash_threads; i++) { - mpmc_push(&g_file_queue, NULL); + size_t len = strlen(folders[i]) + 1; + + char *path = arena_push(&scanners[0].path_arena, len, false); + memcpy(path, folders[i], len); + + mpmc_push_work(&dir_queue, path); } - atomic_store(&g_scan_done, 1); + // Stop scan threads + WaitForMultipleObjects((DWORD)num_scan_threads, scan_threads, TRUE, INFINITE); for (size_t i = 0; i < num_scan_threads; ++i) CloseHandle(scan_threads[i]); + for (size_t i = 0; i < num_hash_threads; i++) { + mpmc_push(&file_queue, NULL); + } + + atomic_store(&g_scan_done, 1); + arena_free(&gp_arena, (u8 **)&scan_threads, sizeof(HANDLE) * num_scan_threads); @@ -544,13 +508,13 @@ int main(int argc, char **argv) { printf("Completed scanning in %.2f seconds, found %zu files\n\n", scan_seconds, total_found); - // if no files found + // If no files found if (total_found == 0) { printf("No files found.\n"); return 0; } - // stop hashing threads + // Stop hashing threads WaitForMultipleObjects((DWORD)num_hash_threads, hash_threads, TRUE, INFINITE); for (size_t i = 0; i < num_hash_threads; ++i) @@ -559,10 +523,13 @@ int main(int argc, char **argv) { arena_free(&gp_arena, (u8 **)&hash_threads, sizeof(HANDLE) * num_hash_threads); + // Stop progress printing thread WaitForSingleObject(progress, INFINITE); CloseHandle(progress); - // write file_hashes.txt + // ------------------------------- + // Export file_hashes.txt + // ------------------------------- // FILE *f = fopen(FILE_HASHES_TXT, "wb"); // @@ -591,7 +558,9 @@ int main(int argc, char **argv) { WriteFile(h, arena_base, (DWORD)local_hash_arena->pos, &written, NULL); } - // done time + // ------------------------------- + // Print summary + // ------------------------------- double total_seconds = timer_stop(&total_timer); printf("Completed hashing %zu files\n", total_found); diff --git a/xxh_x86dispatch.c b/xxh_x86dispatch.c new file mode 100644 index 0000000..0c15820 --- /dev/null +++ b/xxh_x86dispatch.c @@ -0,0 +1,821 @@ +/* + * xxHash - Extremely Fast Hash algorithm + * Copyright (C) 2020-2021 Yann Collet + * + * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + + +/*! + * @file xxh_x86dispatch.c + * + * Automatic dispatcher code for the @ref XXH3_family on x86-based targets. + * + * Optional add-on. + * + * **Compile this file with the default flags for your target.** + * Note that compiling with flags like `-mavx*`, `-march=native`, or `/arch:AVX*` + * will make the resulting binary incompatible with cpus not supporting the requested instruction set. + * + * @defgroup dispatch x86 Dispatcher + * @{ + */ + +#if defined (__cplusplus) +extern "C" { +#endif + +#if !(defined(__x86_64__) || defined(__i386__) || defined(_M_IX86) || defined(_M_X64)) +# error "Dispatching is currently only supported on x86 and x86_64." +#endif + +/*! @cond Doxygen ignores this part */ +#ifndef XXH_HAS_INCLUDE +# ifdef __has_include +/* + * Not defined as XXH_HAS_INCLUDE(x) (function-like) because + * this causes segfaults in Apple Clang 4.2 (on Mac OS X 10.7 Lion) + */ +# define XXH_HAS_INCLUDE __has_include +# else +# define XXH_HAS_INCLUDE(x) 0 +# endif +#endif +/*! @endcond */ + +/*! + * @def XXH_DISPATCH_SCALAR + * @brief Enables/dispatching the scalar code path. + * + * If this is defined to 0, SSE2 support is assumed. This reduces code size + * when the scalar path is not needed. + * + * This is automatically defined to 0 when... + * - SSE2 support is enabled in the compiler + * - Targeting x86_64 + * - Targeting Android x86 + * - Targeting macOS + */ +#ifndef XXH_DISPATCH_SCALAR +# if defined(__SSE2__) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2) /* SSE2 on by default */ \ + || defined(__x86_64__) || defined(_M_X64) /* x86_64 */ \ + || defined(__ANDROID__) || defined(__APPLE__) /* Android or macOS */ +# define XXH_DISPATCH_SCALAR 0 /* disable */ +# else +# define XXH_DISPATCH_SCALAR 1 +# endif +#endif +/*! + * @def XXH_DISPATCH_AVX2 + * @brief Enables/disables dispatching for AVX2. + * + * This is automatically detected if it is not defined. + * - GCC 4.7 and later are known to support AVX2, but >4.9 is required for + * to get the AVX2 intrinsics and typedefs without -mavx -mavx2. + * - Visual Studio 2013 Update 2 and later are known to support AVX2. + * - The GCC/Clang internal header `` is detected. While this is + * not allowed to be included directly, it still appears in the builtin + * include path and is detectable with `__has_include`. + * + * @see XXH_AVX2 + */ +#ifndef XXH_DISPATCH_AVX2 +# if (defined(__GNUC__) && (__GNUC__ > 4)) /* GCC 5.0+ */ \ + || (defined(_MSC_VER) && _MSC_VER >= 1900) /* VS 2015+ */ \ + || (defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 180030501) /* VS 2013 Update 2 */ \ + || XXH_HAS_INCLUDE() /* GCC/Clang internal header */ +# define XXH_DISPATCH_AVX2 1 /* enable dispatch towards AVX2 */ +# else +# define XXH_DISPATCH_AVX2 0 +# endif +#endif /* XXH_DISPATCH_AVX2 */ + +/*! + * @def XXH_DISPATCH_AVX512 + * @brief Enables/disables dispatching for AVX512. + * + * Automatically detected if one of the following conditions is met: + * - GCC 4.9 and later are known to support AVX512. + * - Visual Studio 2017 and later are known to support AVX2. + * - The GCC/Clang internal header `` is detected. While this + * is not allowed to be included directly, it still appears in the builtin + * include path and is detectable with `__has_include`. + * + * @see XXH_AVX512 + */ +#ifndef XXH_DISPATCH_AVX512 +# if (defined(__GNUC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9))) /* GCC 4.9+ */ \ + || (defined(_MSC_VER) && _MSC_VER >= 1910) /* VS 2017+ */ \ + || XXH_HAS_INCLUDE() /* GCC/Clang internal header */ +# define XXH_DISPATCH_AVX512 1 /* enable dispatch towards AVX512 */ +# else +# define XXH_DISPATCH_AVX512 0 +# endif +#endif /* XXH_DISPATCH_AVX512 */ + +/*! + * @def XXH_TARGET_SSE2 + * @brief Allows a function to be compiled with SSE2 intrinsics. + * + * Uses `__attribute__((__target__("sse2")))` on GCC to allow SSE2 to be used + * even with `-mno-sse2`. + * + * @def XXH_TARGET_AVX2 + * @brief Like @ref XXH_TARGET_SSE2, but for AVX2. + * + * @def XXH_TARGET_AVX512 + * @brief Like @ref XXH_TARGET_SSE2, but for AVX512. + * + */ +#if defined(__GNUC__) +# include /* SSE2 */ +# if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512 +# include /* AVX2, AVX512F */ +# endif +# define XXH_TARGET_SSE2 __attribute__((__target__("sse2"))) +# define XXH_TARGET_AVX2 __attribute__((__target__("avx2"))) +# define XXH_TARGET_AVX512 __attribute__((__target__("avx512f"))) +#elif defined(__clang__) && defined(_MSC_VER) /* clang-cl.exe */ +# include /* SSE2 */ +# if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512 +# include /* AVX2, AVX512F */ +# include +# include +# include +# include +# endif +# define XXH_TARGET_SSE2 __attribute__((__target__("sse2"))) +# define XXH_TARGET_AVX2 __attribute__((__target__("avx2"))) +# define XXH_TARGET_AVX512 __attribute__((__target__("avx512f"))) +#elif defined(_MSC_VER) +# include +# define XXH_TARGET_SSE2 +# define XXH_TARGET_AVX2 +# define XXH_TARGET_AVX512 +#else +# error "Dispatching is currently not supported for your compiler." +#endif + +/*! @cond Doxygen ignores this part */ +#ifdef XXH_DISPATCH_DEBUG +/* debug logging */ +# include +# define XXH_debugPrint(str) { fprintf(stderr, "DEBUG: xxHash dispatch: %s \n", str); fflush(NULL); } +#else +# define XXH_debugPrint(str) ((void)0) +# undef NDEBUG /* avoid redefinition */ +# define NDEBUG +#endif +/*! @endcond */ +#include + +#ifndef XXH_DOXYGEN +#define XXH_INLINE_ALL +#define XXH_X86DISPATCH +#include "xxhash.h" +#endif + +/*! @cond Doxygen ignores this part */ +#ifndef XXH_HAS_ATTRIBUTE +# ifdef __has_attribute +# define XXH_HAS_ATTRIBUTE(...) __has_attribute(__VA_ARGS__) +# else +# define XXH_HAS_ATTRIBUTE(...) 0 +# endif +#endif +/*! @endcond */ + +/*! @cond Doxygen ignores this part */ +#if XXH_HAS_ATTRIBUTE(constructor) +# define XXH_CONSTRUCTOR __attribute__((constructor)) +# define XXH_DISPATCH_MAYBE_NULL 0 +#else +# define XXH_CONSTRUCTOR +# define XXH_DISPATCH_MAYBE_NULL 1 +#endif +/*! @endcond */ + + +/*! @cond Doxygen ignores this part */ +/* + * Support both AT&T and Intel dialects + * + * GCC doesn't convert AT&T syntax to Intel syntax, and will error out if + * compiled with -masm=intel. Instead, it supports dialect switching with + * curly braces: { AT&T syntax | Intel syntax } + * + * Clang's integrated assembler automatically converts AT&T syntax to Intel if + * needed, making the dialect switching useless (it isn't even supported). + * + * Note: Comments are written in the inline assembly itself. + */ +#ifdef __clang__ +# define XXH_I_ATT(intel, att) att "\n\t" +#else +# define XXH_I_ATT(intel, att) "{" att "|" intel "}\n\t" +#endif +/*! @endcond */ + +/*! + * @private + * @brief Runs CPUID. + * + * @param eax , ecx The parameters to pass to CPUID, %eax and %ecx respectively. + * @param abcd The array to store the result in, `{ eax, ebx, ecx, edx }` + */ +static void XXH_cpuid(xxh_u32 eax, xxh_u32 ecx, xxh_u32* abcd) +{ +#if defined(_MSC_VER) + __cpuidex((int*)abcd, eax, ecx); +#else + xxh_u32 ebx, edx; +# if defined(__i386__) && defined(__PIC__) + __asm__( + "# Call CPUID\n\t" + "#\n\t" + "# On 32-bit x86 with PIC enabled, we are not allowed to overwrite\n\t" + "# EBX, so we use EDI instead.\n\t" + XXH_I_ATT("mov edi, ebx", "movl %%ebx, %%edi") + XXH_I_ATT("cpuid", "cpuid" ) + XXH_I_ATT("xchg edi, ebx", "xchgl %%ebx, %%edi") + : "=D" (ebx), +# else + __asm__( + "# Call CPUID\n\t" + XXH_I_ATT("cpuid", "cpuid") + : "=b" (ebx), +# endif + "+a" (eax), "+c" (ecx), "=d" (edx)); + abcd[0] = eax; + abcd[1] = ebx; + abcd[2] = ecx; + abcd[3] = edx; +#endif +} + +/* + * Modified version of Intel's guide + * https://software.intel.com/en-us/articles/how-to-detect-new-instruction-support-in-the-4th-generation-intel-core-processor-family + */ + +#if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512 +/*! + * @private + * @brief Runs `XGETBV`. + * + * While the CPU may support AVX2, the operating system might not properly save + * the full YMM/ZMM registers. + * + * xgetbv is used for detecting this: Any compliant operating system will define + * a set of flags in the xcr0 register indicating how it saves the AVX registers. + * + * You can manually disable this flag on Windows by running, as admin: + * + * bcdedit.exe /set xsavedisable 1 + * + * and rebooting. Run the same command with 0 to re-enable it. + */ +static xxh_u64 XXH_xgetbv(void) +{ +#if defined(_MSC_VER) + return _xgetbv(0); /* min VS2010 SP1 compiler is required */ +#else + xxh_u32 xcr0_lo, xcr0_hi; + __asm__( + "# Call XGETBV\n\t" + "#\n\t" + "# Older assemblers (e.g. macOS's ancient GAS version) don't support\n\t" + "# the XGETBV opcode, so we encode it by hand instead.\n\t" + "# See for details.\n\t" + ".byte 0x0f, 0x01, 0xd0\n\t" + : "=a" (xcr0_lo), "=d" (xcr0_hi) : "c" (0)); + return xcr0_lo | ((xxh_u64)xcr0_hi << 32); +#endif +} +#endif + +/*! @cond Doxygen ignores this part */ +#define XXH_SSE2_CPUID_MASK (1 << 26) +#define XXH_OSXSAVE_CPUID_MASK ((1 << 26) | (1 << 27)) +#define XXH_AVX2_CPUID_MASK (1 << 5) +#define XXH_AVX2_XGETBV_MASK ((1 << 2) | (1 << 1)) +#define XXH_AVX512F_CPUID_MASK (1 << 16) +#define XXH_AVX512F_XGETBV_MASK ((7 << 5) | (1 << 2) | (1 << 1)) +/*! @endcond */ + +/*! + * @private + * @brief Returns the best XXH3 implementation. + * + * Runs various CPUID/XGETBV tests to try and determine the best implementation. + * + * @return The best @ref XXH_VECTOR implementation. + * @see XXH_VECTOR_TYPES + */ +int XXH_featureTest(void) +{ + xxh_u32 abcd[4]; + xxh_u32 max_leaves; + int best = XXH_SCALAR; +#if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512 + xxh_u64 xgetbv_val; +#endif +#if defined(__GNUC__) && defined(__i386__) + xxh_u32 cpuid_supported; + __asm__( + "# For the sake of ruthless backwards compatibility, check if CPUID\n\t" + "# is supported in the EFLAGS on i386.\n\t" + "# This is not necessary on x86_64 - CPUID is mandatory.\n\t" + "# The ID flag (bit 21) in the EFLAGS register indicates support\n\t" + "# for the CPUID instruction. If a software procedure can set and\n\t" + "# clear this flag, the processor executing the procedure supports\n\t" + "# the CPUID instruction.\n\t" + "# \n\t" + "#\n\t" + "# Routine is from .\n\t" + + "# Save EFLAGS\n\t" + XXH_I_ATT("pushfd", "pushfl" ) + "# Store EFLAGS\n\t" + XXH_I_ATT("pushfd", "pushfl" ) + "# Invert the ID bit in stored EFLAGS\n\t" + XXH_I_ATT("xor dword ptr[esp], 0x200000", "xorl $0x200000, (%%esp)") + "# Load stored EFLAGS (with ID bit inverted)\n\t" + XXH_I_ATT("popfd", "popfl" ) + "# Store EFLAGS again (ID bit may or not be inverted)\n\t" + XXH_I_ATT("pushfd", "pushfl" ) + "# eax = modified EFLAGS (ID bit may or may not be inverted)\n\t" + XXH_I_ATT("pop eax", "popl %%eax" ) + "# eax = whichever bits were changed\n\t" + XXH_I_ATT("xor eax, dword ptr[esp]", "xorl (%%esp), %%eax" ) + "# Restore original EFLAGS\n\t" + XXH_I_ATT("popfd", "popfl" ) + "# eax = zero if ID bit can't be changed, else non-zero\n\t" + XXH_I_ATT("and eax, 0x200000", "andl $0x200000, %%eax" ) + : "=a" (cpuid_supported) :: "cc"); + + if (XXH_unlikely(!cpuid_supported)) { + XXH_debugPrint("CPUID support is not detected!"); + return best; + } + +#endif + /* Check how many CPUID pages we have */ + XXH_cpuid(0, 0, abcd); + max_leaves = abcd[0]; + + /* Shouldn't happen on hardware, but happens on some QEMU configs. */ + if (XXH_unlikely(max_leaves == 0)) { + XXH_debugPrint("Max CPUID leaves == 0!"); + return best; + } + + /* Check for SSE2, OSXSAVE and xgetbv */ + XXH_cpuid(1, 0, abcd); + + /* + * Test for SSE2. The check is redundant on x86_64, but it doesn't hurt. + */ + if (XXH_unlikely((abcd[3] & XXH_SSE2_CPUID_MASK) != XXH_SSE2_CPUID_MASK)) + return best; + + XXH_debugPrint("SSE2 support detected."); + + best = XXH_SSE2; +#if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512 + /* Make sure we have enough leaves */ + if (XXH_unlikely(max_leaves < 7)) + return best; + + /* Test for OSXSAVE and XGETBV */ + if ((abcd[2] & XXH_OSXSAVE_CPUID_MASK) != XXH_OSXSAVE_CPUID_MASK) + return best; + + /* CPUID check for AVX features */ + XXH_cpuid(7, 0, abcd); + + xgetbv_val = XXH_xgetbv(); +#if XXH_DISPATCH_AVX2 + /* Validate that AVX2 is supported by the CPU */ + if ((abcd[1] & XXH_AVX2_CPUID_MASK) != XXH_AVX2_CPUID_MASK) + return best; + + /* Validate that the OS supports YMM registers */ + if ((xgetbv_val & XXH_AVX2_XGETBV_MASK) != XXH_AVX2_XGETBV_MASK) { + XXH_debugPrint("AVX2 supported by the CPU, but not the OS."); + return best; + } + + /* AVX2 supported */ + XXH_debugPrint("AVX2 support detected."); + best = XXH_AVX2; +#endif +#if XXH_DISPATCH_AVX512 + /* Check if AVX512F is supported by the CPU */ + if ((abcd[1] & XXH_AVX512F_CPUID_MASK) != XXH_AVX512F_CPUID_MASK) { + XXH_debugPrint("AVX512F not supported by CPU"); + return best; + } + + /* Validate that the OS supports ZMM registers */ + if ((xgetbv_val & XXH_AVX512F_XGETBV_MASK) != XXH_AVX512F_XGETBV_MASK) { + XXH_debugPrint("AVX512F supported by the CPU, but not the OS."); + return best; + } + + /* AVX512F supported */ + XXH_debugPrint("AVX512F support detected."); + best = XXH_AVX512; +#endif +#endif + return best; +} + + +/* === Vector implementations === */ + +/*! @cond PRIVATE */ +/*! + * @private + * @brief Defines the various dispatch functions. + * + * TODO: Consolidate? + * + * @param suffix The suffix for the functions, e.g. sse2 or scalar + * @param target XXH_TARGET_* or empty. + */ + +#define XXH_DEFINE_DISPATCH_FUNCS(suffix, target) \ + \ +/* === XXH3, default variants === */ \ + \ +XXH_NO_INLINE target XXH64_hash_t \ +XXHL64_default_##suffix(XXH_NOESCAPE const void* XXH_RESTRICT input, \ + size_t len) \ +{ \ + return XXH3_hashLong_64b_internal( \ + input, len, XXH3_kSecret, sizeof(XXH3_kSecret), \ + XXH3_accumulate_##suffix, XXH3_scrambleAcc_##suffix \ + ); \ +} \ + \ +/* === XXH3, Seeded variants === */ \ + \ +XXH_NO_INLINE target XXH64_hash_t \ +XXHL64_seed_##suffix(XXH_NOESCAPE const void* XXH_RESTRICT input, size_t len, \ + XXH64_hash_t seed) \ +{ \ + return XXH3_hashLong_64b_withSeed_internal( \ + input, len, seed, XXH3_accumulate_##suffix, \ + XXH3_scrambleAcc_##suffix, XXH3_initCustomSecret_##suffix \ + ); \ +} \ + \ +/* === XXH3, Secret variants === */ \ + \ +XXH_NO_INLINE target XXH64_hash_t \ +XXHL64_secret_##suffix(XXH_NOESCAPE const void* XXH_RESTRICT input, \ + size_t len, XXH_NOESCAPE const void* secret, \ + size_t secretLen) \ +{ \ + return XXH3_hashLong_64b_internal( \ + input, len, secret, secretLen, \ + XXH3_accumulate_##suffix, XXH3_scrambleAcc_##suffix \ + ); \ +} \ + \ +/* === XXH3 update variants === */ \ + \ +XXH_NO_INLINE target XXH_errorcode \ +XXH3_update_##suffix(XXH_NOESCAPE XXH3_state_t* state, \ + XXH_NOESCAPE const void* input, size_t len) \ +{ \ + return XXH3_update(state, (const xxh_u8*)input, len, \ + XXH3_accumulate_##suffix, XXH3_scrambleAcc_##suffix); \ +} \ + \ +/* === XXH128 default variants === */ \ + \ +XXH_NO_INLINE target XXH128_hash_t \ +XXHL128_default_##suffix(XXH_NOESCAPE const void* XXH_RESTRICT input, \ + size_t len) \ +{ \ + return XXH3_hashLong_128b_internal( \ + input, len, XXH3_kSecret, sizeof(XXH3_kSecret), \ + XXH3_accumulate_##suffix, XXH3_scrambleAcc_##suffix \ + ); \ +} \ + \ +/* === XXH128 Secret variants === */ \ + \ +XXH_NO_INLINE target XXH128_hash_t \ +XXHL128_secret_##suffix(XXH_NOESCAPE const void* XXH_RESTRICT input, \ + size_t len, \ + XXH_NOESCAPE const void* XXH_RESTRICT secret, \ + size_t secretLen) \ +{ \ + return XXH3_hashLong_128b_internal( \ + input, len, (const xxh_u8*)secret, secretLen, \ + XXH3_accumulate_##suffix, XXH3_scrambleAcc_##suffix); \ +} \ + \ +/* === XXH128 Seeded variants === */ \ + \ +XXH_NO_INLINE target XXH128_hash_t \ +XXHL128_seed_##suffix(XXH_NOESCAPE const void* XXH_RESTRICT input, size_t len,\ + XXH64_hash_t seed) \ +{ \ + return XXH3_hashLong_128b_withSeed_internal(input, len, seed, \ + XXH3_accumulate_##suffix, XXH3_scrambleAcc_##suffix, \ + XXH3_initCustomSecret_##suffix); \ +} + +/*! @endcond */ +/* End XXH_DEFINE_DISPATCH_FUNCS */ + +/*! @cond Doxygen ignores this part */ +#if XXH_DISPATCH_SCALAR +XXH_DEFINE_DISPATCH_FUNCS(scalar, /* nothing */) +#endif +XXH_DEFINE_DISPATCH_FUNCS(sse2, XXH_TARGET_SSE2) +#if XXH_DISPATCH_AVX2 +XXH_DEFINE_DISPATCH_FUNCS(avx2, XXH_TARGET_AVX2) +#endif +#if XXH_DISPATCH_AVX512 +XXH_DEFINE_DISPATCH_FUNCS(avx512, XXH_TARGET_AVX512) +#endif +#undef XXH_DEFINE_DISPATCH_FUNCS +/*! @endcond */ + +/* ==== Dispatchers ==== */ + +/*! @cond Doxygen ignores this part */ +typedef XXH64_hash_t (*XXH3_dispatchx86_hashLong64_default)(XXH_NOESCAPE const void* XXH_RESTRICT, size_t); + +typedef XXH64_hash_t (*XXH3_dispatchx86_hashLong64_withSeed)(XXH_NOESCAPE const void* XXH_RESTRICT, size_t, XXH64_hash_t); + +typedef XXH64_hash_t (*XXH3_dispatchx86_hashLong64_withSecret)(XXH_NOESCAPE const void* XXH_RESTRICT, size_t, XXH_NOESCAPE const void* XXH_RESTRICT, size_t); + +typedef XXH_errorcode (*XXH3_dispatchx86_update)(XXH_NOESCAPE XXH3_state_t*, XXH_NOESCAPE const void*, size_t); + +typedef struct { + XXH3_dispatchx86_hashLong64_default hashLong64_default; + XXH3_dispatchx86_hashLong64_withSeed hashLong64_seed; + XXH3_dispatchx86_hashLong64_withSecret hashLong64_secret; + XXH3_dispatchx86_update update; +} XXH_dispatchFunctions_s; + +#define XXH_NB_DISPATCHES 4 +/*! @endcond */ + +/*! + * @private + * @brief Table of dispatchers for @ref XXH3_64bits(). + * + * @pre The indices must match @ref XXH_VECTOR_TYPE. + */ +static const XXH_dispatchFunctions_s XXH_kDispatch[XXH_NB_DISPATCHES] = { +#if XXH_DISPATCH_SCALAR + /* Scalar */ { XXHL64_default_scalar, XXHL64_seed_scalar, XXHL64_secret_scalar, XXH3_update_scalar }, +#else + /* Scalar */ { NULL, NULL, NULL, NULL }, +#endif + /* SSE2 */ { XXHL64_default_sse2, XXHL64_seed_sse2, XXHL64_secret_sse2, XXH3_update_sse2 }, +#if XXH_DISPATCH_AVX2 + /* AVX2 */ { XXHL64_default_avx2, XXHL64_seed_avx2, XXHL64_secret_avx2, XXH3_update_avx2 }, +#else + /* AVX2 */ { NULL, NULL, NULL, NULL }, +#endif +#if XXH_DISPATCH_AVX512 + /* AVX512 */ { XXHL64_default_avx512, XXHL64_seed_avx512, XXHL64_secret_avx512, XXH3_update_avx512 } +#else + /* AVX512 */ { NULL, NULL, NULL, NULL } +#endif +}; +/*! + * @private + * @brief The selected dispatch table for @ref XXH3_64bits(). + */ +static XXH_dispatchFunctions_s XXH_g_dispatch = { NULL, NULL, NULL, NULL }; + + +/*! @cond Doxygen ignores this part */ +typedef XXH128_hash_t (*XXH3_dispatchx86_hashLong128_default)(XXH_NOESCAPE const void* XXH_RESTRICT, size_t); + +typedef XXH128_hash_t (*XXH3_dispatchx86_hashLong128_withSeed)(XXH_NOESCAPE const void* XXH_RESTRICT, size_t, XXH64_hash_t); + +typedef XXH128_hash_t (*XXH3_dispatchx86_hashLong128_withSecret)(XXH_NOESCAPE const void* XXH_RESTRICT, size_t, XXH_NOESCAPE const void* XXH_RESTRICT, size_t); + +typedef struct { + XXH3_dispatchx86_hashLong128_default hashLong128_default; + XXH3_dispatchx86_hashLong128_withSeed hashLong128_seed; + XXH3_dispatchx86_hashLong128_withSecret hashLong128_secret; + XXH3_dispatchx86_update update; +} XXH_dispatch128Functions_s; +/*! @endcond */ + + +/*! + * @private + * @brief Table of dispatchers for @ref XXH3_128bits(). + * + * @pre The indices must match @ref XXH_VECTOR_TYPE. + */ +static const XXH_dispatch128Functions_s XXH_kDispatch128[XXH_NB_DISPATCHES] = { +#if XXH_DISPATCH_SCALAR + /* Scalar */ { XXHL128_default_scalar, XXHL128_seed_scalar, XXHL128_secret_scalar, XXH3_update_scalar }, +#else + /* Scalar */ { NULL, NULL, NULL, NULL }, +#endif + /* SSE2 */ { XXHL128_default_sse2, XXHL128_seed_sse2, XXHL128_secret_sse2, XXH3_update_sse2 }, +#if XXH_DISPATCH_AVX2 + /* AVX2 */ { XXHL128_default_avx2, XXHL128_seed_avx2, XXHL128_secret_avx2, XXH3_update_avx2 }, +#else + /* AVX2 */ { NULL, NULL, NULL, NULL }, +#endif +#if XXH_DISPATCH_AVX512 + /* AVX512 */ { XXHL128_default_avx512, XXHL128_seed_avx512, XXHL128_secret_avx512, XXH3_update_avx512 } +#else + /* AVX512 */ { NULL, NULL, NULL, NULL } +#endif +}; + +/*! + * @private + * @brief The selected dispatch table for @ref XXH3_64bits(). + */ +static XXH_dispatch128Functions_s XXH_g_dispatch128 = { NULL, NULL, NULL, NULL }; + +/*! + * @private + * @brief Runs a CPUID check and sets the correct dispatch tables. + */ +static XXH_CONSTRUCTOR void XXH_setDispatch(void) +{ + int vecID = XXH_featureTest(); + XXH_STATIC_ASSERT(XXH_AVX512 == XXH_NB_DISPATCHES-1); + assert(XXH_SCALAR <= vecID && vecID <= XXH_AVX512); +#if !XXH_DISPATCH_SCALAR + assert(vecID != XXH_SCALAR); +#endif +#if !XXH_DISPATCH_AVX512 + assert(vecID != XXH_AVX512); +#endif +#if !XXH_DISPATCH_AVX2 + assert(vecID != XXH_AVX2); +#endif + XXH_g_dispatch = XXH_kDispatch[vecID]; + XXH_g_dispatch128 = XXH_kDispatch128[vecID]; +} + + +/* ==== XXH3 public functions ==== */ +/*! @cond Doxygen ignores this part */ + +static XXH64_hash_t +XXH3_hashLong_64b_defaultSecret_selection(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) +{ + (void)seed64; (void)secret; (void)secretLen; + if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch.hashLong64_default == NULL) + XXH_setDispatch(); + return XXH_g_dispatch.hashLong64_default(input, len); +} + +XXH64_hash_t XXH3_64bits_dispatch(XXH_NOESCAPE const void* input, size_t len) +{ + return XXH3_64bits_internal(input, len, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_defaultSecret_selection); +} + +static XXH64_hash_t +XXH3_hashLong_64b_withSeed_selection(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) +{ + (void)secret; (void)secretLen; + if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch.hashLong64_seed == NULL) + XXH_setDispatch(); + return XXH_g_dispatch.hashLong64_seed(input, len, seed64); +} + +XXH64_hash_t XXH3_64bits_withSeed_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed) +{ + return XXH3_64bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_withSeed_selection); +} + +static XXH64_hash_t +XXH3_hashLong_64b_withSecret_selection(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) +{ + (void)seed64; + if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch.hashLong64_secret == NULL) + XXH_setDispatch(); + return XXH_g_dispatch.hashLong64_secret(input, len, secret, secretLen); +} + +XXH64_hash_t XXH3_64bits_withSecret_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretLen) +{ + return XXH3_64bits_internal(input, len, 0, secret, secretLen, XXH3_hashLong_64b_withSecret_selection); +} + +XXH_errorcode +XXH3_64bits_update_dispatch(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len) +{ + if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch.update == NULL) + XXH_setDispatch(); + + return XXH_g_dispatch.update(state, (const xxh_u8*)input, len); +} + +/*! @endcond */ + + +/* ==== XXH128 public functions ==== */ +/*! @cond Doxygen ignores this part */ + +static XXH128_hash_t +XXH3_hashLong_128b_defaultSecret_selection(const void* input, size_t len, + XXH64_hash_t seed64, const void* secret, size_t secretLen) +{ + (void)seed64; (void)secret; (void)secretLen; + if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch128.hashLong128_default == NULL) + XXH_setDispatch(); + return XXH_g_dispatch128.hashLong128_default(input, len); +} + +XXH128_hash_t XXH3_128bits_dispatch(XXH_NOESCAPE const void* input, size_t len) +{ + return XXH3_128bits_internal(input, len, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_128b_defaultSecret_selection); +} + +static XXH128_hash_t +XXH3_hashLong_128b_withSeed_selection(const void* input, size_t len, + XXH64_hash_t seed64, const void* secret, size_t secretLen) +{ + (void)secret; (void)secretLen; + if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch128.hashLong128_seed == NULL) + XXH_setDispatch(); + return XXH_g_dispatch128.hashLong128_seed(input, len, seed64); +} + +XXH128_hash_t XXH3_128bits_withSeed_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed) +{ + return XXH3_128bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_128b_withSeed_selection); +} + +static XXH128_hash_t +XXH3_hashLong_128b_withSecret_selection(const void* input, size_t len, + XXH64_hash_t seed64, const void* secret, size_t secretLen) +{ + (void)seed64; + if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch128.hashLong128_secret == NULL) + XXH_setDispatch(); + return XXH_g_dispatch128.hashLong128_secret(input, len, secret, secretLen); +} + +XXH128_hash_t XXH3_128bits_withSecret_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretLen) +{ + return XXH3_128bits_internal(input, len, 0, secret, secretLen, XXH3_hashLong_128b_withSecret_selection); +} + +XXH_errorcode +XXH3_128bits_update_dispatch(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len) +{ + if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch128.update == NULL) + XXH_setDispatch(); + return XXH_g_dispatch128.update(state, (const xxh_u8*)input, len); +} + +/*! @endcond */ + +#if defined (__cplusplus) +} +#endif +/*! @} */ diff --git a/xxh_x86dispatch.h b/xxh_x86dispatch.h new file mode 100644 index 0000000..7085221 --- /dev/null +++ b/xxh_x86dispatch.h @@ -0,0 +1,93 @@ +/* + * xxHash - XXH3 Dispatcher for x86-based targets + * Copyright (C) 2020-2024 Yann Collet + * + * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + +#ifndef XXH_X86DISPATCH_H_13563687684 +#define XXH_X86DISPATCH_H_13563687684 + +#include "xxhash.h" /* XXH64_hash_t, XXH3_state_t */ + +#if defined (__cplusplus) +extern "C" { +#endif + +/*! + * @brief Returns the best XXH3 implementation for x86 + * + * @return The best @ref XXH_VECTOR implementation. + * @see XXH_VECTOR_TYPES + */ +XXH_PUBLIC_API int XXH_featureTest(void); + +XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_dispatch(XXH_NOESCAPE const void* input, size_t len); +XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSeed_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed); +XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSecret_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretLen); +XXH_PUBLIC_API XXH_errorcode XXH3_64bits_update_dispatch(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len); + +XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_dispatch(XXH_NOESCAPE const void* input, size_t len); +XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSeed_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed); +XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSecret_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretLen); +XXH_PUBLIC_API XXH_errorcode XXH3_128bits_update_dispatch(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len); + +#if defined (__cplusplus) +} +#endif + + +/* automatic replacement of XXH3 functions. + * can be disabled by setting XXH_DISPATCH_DISABLE_REPLACE */ +#ifndef XXH_DISPATCH_DISABLE_REPLACE + +# undef XXH3_64bits +# define XXH3_64bits XXH3_64bits_dispatch +# undef XXH3_64bits_withSeed +# define XXH3_64bits_withSeed XXH3_64bits_withSeed_dispatch +# undef XXH3_64bits_withSecret +# define XXH3_64bits_withSecret XXH3_64bits_withSecret_dispatch +# undef XXH3_64bits_update +# define XXH3_64bits_update XXH3_64bits_update_dispatch + +# undef XXH128 +# define XXH128 XXH3_128bits_withSeed_dispatch +# undef XXH3_128bits +# define XXH3_128bits XXH3_128bits_dispatch +# undef XXH3_128bits_withSeed +# define XXH3_128bits_withSeed XXH3_128bits_withSeed_dispatch +# undef XXH3_128bits_withSecret +# define XXH3_128bits_withSecret XXH3_128bits_withSecret_dispatch +# undef XXH3_128bits_update +# define XXH3_128bits_update XXH3_128bits_update_dispatch + +#endif /* XXH_DISPATCH_DISABLE_REPLACE */ + +#endif /* XXH_X86DISPATCH_H_13563687684 */