[+] Reimplement the minimalistic win32/pthread compatibility layer with Aurora runtime

This commit is contained in:
Reece Wilson 2021-01-02 10:47:03 +00:00
parent ce34dc39a0
commit 6e159dd682
6 changed files with 135 additions and 251 deletions

View File

@ -80,7 +80,7 @@ static void* POOL_thread(void* opaque) {
ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
return opaque;
}
ZSTD_pthread_cond_wait(&ctx->queuePopCond, &ctx->queueMutex);
ZSTD_pthread_cond_wait(&ctx->queuePopCond);
}
/* Pop a job off the queue */
{ POOL_job const job = ctx->queue[ctx->queueHead];
@ -133,9 +133,9 @@ POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize,
ctx->queueEmpty = 1;
{
int error = 0;
error |= ZSTD_pthread_mutex_init(&ctx->queueMutex, NULL);
error |= ZSTD_pthread_cond_init(&ctx->queuePushCond, NULL);
error |= ZSTD_pthread_cond_init(&ctx->queuePopCond, NULL);
error |= ZSTD_pthread_mutex_init(&ctx->queueMutex);
error |= ZSTD_pthread_cond_init(&ctx->queuePushCond, &ctx->queueMutex);
error |= ZSTD_pthread_cond_init(&ctx->queuePopCond, &ctx->queueMutex);
if (error) { POOL_free(ctx); return NULL; }
}
ctx->shutdown = 0;
@ -275,7 +275,7 @@ void POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque)
ZSTD_pthread_mutex_lock(&ctx->queueMutex);
/* Wait until there is space in the queue for the new job */
while (isQueueFull(ctx) && (!ctx->shutdown)) {
ZSTD_pthread_cond_wait(&ctx->queuePushCond, &ctx->queueMutex);
ZSTD_pthread_cond_wait(&ctx->queuePushCond);
}
POOL_add_internal(ctx, function, opaque);
ZSTD_pthread_mutex_unlock(&ctx->queueMutex);

View File

@ -1,122 +0,0 @@
/**
* Copyright (c) 2016 Tino Reichardt
* All rights reserved.
*
* You can contact the author at:
* - zstdmt source repository: https://github.com/mcmilk/zstdmt
*
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
/**
* This file will hold wrapper for systems, which do not support pthreads
*/
#include "threading.h"
/* create fake symbol to avoid empty translation unit warning */
int g_ZSTD_threading_useless_symbol;
#if defined(ZSTD_MULTITHREAD) && defined(_WIN32)
/**
* Windows minimalist Pthread Wrapper, based on :
* http://www.cse.wustl.edu/~schmidt/win32-cv-1.html
*/
/* === Dependencies === */
#include <process.h>
#include <errno.h>
/* === Implementation === */
static unsigned __stdcall worker(void *arg)
{
ZSTD_pthread_t* const thread = (ZSTD_pthread_t*) arg;
thread->arg = thread->start_routine(thread->arg);
return 0;
}
int ZSTD_pthread_create(ZSTD_pthread_t* thread, const void* unused,
void* (*start_routine) (void*), void* arg)
{
(void)unused;
thread->arg = arg;
thread->start_routine = start_routine;
thread->handle = (HANDLE) _beginthreadex(NULL, 0, worker, thread, 0, NULL);
if (!thread->handle)
return errno;
else
return 0;
}
int ZSTD_pthread_join(ZSTD_pthread_t thread, void **value_ptr)
{
DWORD result;
if (!thread.handle) return 0;
result = WaitForSingleObject(thread.handle, INFINITE);
switch (result) {
case WAIT_OBJECT_0:
if (value_ptr) *value_ptr = thread.arg;
return 0;
case WAIT_ABANDONED:
return EINVAL;
default:
return GetLastError();
}
}
#endif /* ZSTD_MULTITHREAD */
#if defined(ZSTD_MULTITHREAD) && DEBUGLEVEL >= 1 && !defined(_WIN32)
#define ZSTD_DEPS_NEED_MALLOC
#include "zstd_deps.h"
int ZSTD_pthread_mutex_init(ZSTD_pthread_mutex_t* mutex, pthread_mutexattr_t const* attr)
{
*mutex = (pthread_mutex_t*)ZSTD_malloc(sizeof(pthread_mutex_t));
if (!*mutex)
return 1;
return pthread_mutex_init(*mutex, attr);
}
int ZSTD_pthread_mutex_destroy(ZSTD_pthread_mutex_t* mutex)
{
if (!*mutex)
return 0;
{
int const ret = pthread_mutex_destroy(*mutex);
ZSTD_free(*mutex);
return ret;
}
}
int ZSTD_pthread_cond_init(ZSTD_pthread_cond_t* cond, pthread_condattr_t const* attr)
{
*cond = (pthread_cond_t*)ZSTD_malloc(sizeof(pthread_cond_t));
if (!*cond)
return 1;
return pthread_cond_init(*cond, attr);
}
int ZSTD_pthread_cond_destroy(ZSTD_pthread_cond_t* cond)
{
if (!*cond)
return 0;
{
int const ret = pthread_cond_destroy(*cond);
ZSTD_free(*cond);
return ret;
}
}
#endif

101
lib/common/threading.cpp Normal file
View File

@ -0,0 +1,101 @@
// TODO: copyright header
#include "threading.h"
#include "KInternal.hpp"
extern "C"
{
int ZSTD_pthread_mutex_init(ZSTD_pthread_mutex_t* in)
{
*in = Aurora::Threading::ConditionalMutexNew();
return *in == nullptr;
}
void ZSTD_pthread_mutex_destroy(ZSTD_pthread_mutex_t* in)
{
if (*in)
{
Aurora::Threading::ConditionalMutexDestroy(reinterpret_cast<Aurora::Threading::IConditionalMutex *>(*in));
*in = nullptr;
}
}
void ZSTD_pthread_mutex_lock(ZSTD_pthread_mutex_t* in)
{
auto mutex = reinterpret_cast<Aurora::Threading::IConditionalMutex*>(*in);
mutex->Lock();
}
void ZSTD_pthread_mutex_unlock(ZSTD_pthread_mutex_t* in)
{
auto mutex = reinterpret_cast<Aurora::Threading::IConditionalMutex*>(*in);
mutex->Unlock();
}
int ZSTD_pthread_cond_init(ZSTD_pthread_cond_t* a, ZSTD_pthread_mutex_t* b)
{
if (*b) return 1;
auto mutex = reinterpret_cast<Aurora::Threading::IConditionalMutex*>(*b);
*a = Aurora::Threading::ConditionalNew(mutex);
return *a == nullptr;
}
void ZSTD_pthread_cond_destroy(ZSTD_pthread_cond_t* a)
{
if (*a)
{
Aurora::Threading::ConditionalDestroy(reinterpret_cast<Aurora::Threading::IConditional*>(*a));
*a = nullptr;
}
}
void ZSTD_pthread_cond_wait(ZSTD_pthread_cond_t* a)
{
auto cond = reinterpret_cast<Aurora::Threading::IConditional*>(*a);
cond->WaitForSignal();
}
void ZSTD_pthread_cond_signal(ZSTD_pthread_cond_t* a)
{
auto cond = reinterpret_cast<Aurora::Threading::IConditional*>(*a);
cond->Signal();
}
void ZSTD_pthread_cond_broadcast(ZSTD_pthread_cond_t* a)
{
auto cond = reinterpret_cast<Aurora::Threading::IConditional*>(*a);
cond->Broadcast();
}
int ZSTD_pthread_create(ZSTD_pthread_t* thread, const void* unused,
void* (*start_routine) (void*), void* arg)
{
*thread = ZSTD_pthread_t{};
Aurora::Threading::IUserThreadHandler handler;
handler.DoRun = [start_routine, arg](Aurora::Threading::IAuroraThread* thread)
{
start_routine(arg);
};
auto handle = Aurora::Threading::NewThread(handler);
if (handle != nullptr) return 1;
handle->Run();
*thread = ZSTD_pthread_t{ handle, start_routine, arg};
return 0;
}
int ZSTD_pthread_join(ZSTD_pthread_t thread, void** value_ptr)
{
if (thread.handle)
{
auto handle = reinterpret_cast<Aurora::Threading::IAuroraThread*>(thread.handle);
handle->Exit();
Aurora::Threading::ExterminateThread(handle);
}
return 0;
}
}

View File

@ -20,50 +20,28 @@
extern "C" {
#endif
#if defined(ZSTD_MULTITHREAD) && defined(_WIN32)
/**
* Windows minimalist Pthread Wrapper, based on :
* http://www.cse.wustl.edu/~schmidt/win32-cv-1.html
*/
#ifdef WINVER
# undef WINVER
#endif
#define WINVER 0x0600
#ifdef _WIN32_WINNT
# undef _WIN32_WINNT
#endif
#define _WIN32_WINNT 0x0600
#ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
#endif
#undef ERROR /* reported already defined on VS 2015 (Rich Geldreich) */
#include <windows.h>
#undef ERROR
#define ERROR(name) ZSTD_ERROR(name)
#if defined(ZSTD_MULTITHREAD)
/* mutex */
#define ZSTD_pthread_mutex_t CRITICAL_SECTION
#define ZSTD_pthread_mutex_init(a, b) ((void)(b), InitializeCriticalSection((a)), 0)
#define ZSTD_pthread_mutex_destroy(a) DeleteCriticalSection((a))
#define ZSTD_pthread_mutex_lock(a) EnterCriticalSection((a))
#define ZSTD_pthread_mutex_unlock(a) LeaveCriticalSection((a))
typedef void* ZSTD_pthread_mutex_t;
int ZSTD_pthread_mutex_init(ZSTD_pthread_mutex_t * in);
void ZSTD_pthread_mutex_destroy(ZSTD_pthread_mutex_t* in);
void ZSTD_pthread_mutex_lock(ZSTD_pthread_mutex_t* in);
void ZSTD_pthread_mutex_unlock(ZSTD_pthread_mutex_t* in);
/* condition variable */
#define ZSTD_pthread_cond_t CONDITION_VARIABLE
#define ZSTD_pthread_cond_init(a, b) ((void)(b), InitializeConditionVariable((a)), 0)
#define ZSTD_pthread_cond_destroy(a) ((void)(a))
#define ZSTD_pthread_cond_wait(a, b) SleepConditionVariableCS((a), (b), INFINITE)
#define ZSTD_pthread_cond_signal(a) WakeConditionVariable((a))
#define ZSTD_pthread_cond_broadcast(a) WakeAllConditionVariable((a))
typedef void* ZSTD_pthread_cond_t;
int ZSTD_pthread_cond_init(ZSTD_pthread_cond_t* a, ZSTD_pthread_mutex_t* b);
void ZSTD_pthread_cond_wait(ZSTD_pthread_cond_t* a);
void ZSTD_pthread_cond_destroy(ZSTD_pthread_cond_t* a);
void ZSTD_pthread_cond_signal(ZSTD_pthread_cond_t* a);
void ZSTD_pthread_cond_broadcast(ZSTD_pthread_cond_t* a);
/* ZSTD_pthread_create() and ZSTD_pthread_join() */
typedef struct {
HANDLE handle;
void * handle;
void* (*start_routine)(void*);
void* arg;
} ZSTD_pthread_t;
@ -73,79 +51,6 @@ int ZSTD_pthread_create(ZSTD_pthread_t* thread, const void* unused,
int ZSTD_pthread_join(ZSTD_pthread_t thread, void** value_ptr);
/**
* add here more wrappers as required
*/
#elif defined(ZSTD_MULTITHREAD) /* posix assumed ; need a better detection method */
/* === POSIX Systems === */
# include <pthread.h>
#if DEBUGLEVEL < 1
#define ZSTD_pthread_mutex_t pthread_mutex_t
#define ZSTD_pthread_mutex_init(a, b) pthread_mutex_init((a), (b))
#define ZSTD_pthread_mutex_destroy(a) pthread_mutex_destroy((a))
#define ZSTD_pthread_mutex_lock(a) pthread_mutex_lock((a))
#define ZSTD_pthread_mutex_unlock(a) pthread_mutex_unlock((a))
#define ZSTD_pthread_cond_t pthread_cond_t
#define ZSTD_pthread_cond_init(a, b) pthread_cond_init((a), (b))
#define ZSTD_pthread_cond_destroy(a) pthread_cond_destroy((a))
#define ZSTD_pthread_cond_wait(a, b) pthread_cond_wait((a), (b))
#define ZSTD_pthread_cond_signal(a) pthread_cond_signal((a))
#define ZSTD_pthread_cond_broadcast(a) pthread_cond_broadcast((a))
#define ZSTD_pthread_t pthread_t
#define ZSTD_pthread_create(a, b, c, d) pthread_create((a), (b), (c), (d))
#define ZSTD_pthread_join(a, b) pthread_join((a),(b))
#else /* DEBUGLEVEL >= 1 */
/* Debug implementation of threading.
* In this implementation we use pointers for mutexes and condition variables.
* This way, if we forget to init/destroy them the program will crash or ASAN
* will report leaks.
*/
#define ZSTD_pthread_mutex_t pthread_mutex_t*
int ZSTD_pthread_mutex_init(ZSTD_pthread_mutex_t* mutex, pthread_mutexattr_t const* attr);
int ZSTD_pthread_mutex_destroy(ZSTD_pthread_mutex_t* mutex);
#define ZSTD_pthread_mutex_lock(a) pthread_mutex_lock(*(a))
#define ZSTD_pthread_mutex_unlock(a) pthread_mutex_unlock(*(a))
#define ZSTD_pthread_cond_t pthread_cond_t*
int ZSTD_pthread_cond_init(ZSTD_pthread_cond_t* cond, pthread_condattr_t const* attr);
int ZSTD_pthread_cond_destroy(ZSTD_pthread_cond_t* cond);
#define ZSTD_pthread_cond_wait(a, b) pthread_cond_wait(*(a), *(b))
#define ZSTD_pthread_cond_signal(a) pthread_cond_signal(*(a))
#define ZSTD_pthread_cond_broadcast(a) pthread_cond_broadcast(*(a))
#define ZSTD_pthread_t pthread_t
#define ZSTD_pthread_create(a, b, c, d) pthread_create((a), (b), (c), (d))
#define ZSTD_pthread_join(a, b) pthread_join((a),(b))
#endif
#else /* ZSTD_MULTITHREAD not defined */
/* No multithreading support */
typedef int ZSTD_pthread_mutex_t;
#define ZSTD_pthread_mutex_init(a, b) ((void)(a), (void)(b), 0)
#define ZSTD_pthread_mutex_destroy(a) ((void)(a))
#define ZSTD_pthread_mutex_lock(a) ((void)(a))
#define ZSTD_pthread_mutex_unlock(a) ((void)(a))
typedef int ZSTD_pthread_cond_t;
#define ZSTD_pthread_cond_init(a, b) ((void)(a), (void)(b), 0)
#define ZSTD_pthread_cond_destroy(a) ((void)(a))
#define ZSTD_pthread_cond_wait(a, b) ((void)(a), (void)(b))
#define ZSTD_pthread_cond_signal(a) ((void)(a))
#define ZSTD_pthread_cond_broadcast(a) ((void)(a))
/* do not use ZSTD_pthread_t */
#endif /* ZSTD_MULTITHREAD */
#if defined (__cplusplus)

View File

@ -108,7 +108,7 @@ static ZSTDMT_bufferPool* ZSTDMT_createBufferPool(unsigned nbWorkers, ZSTD_custo
ZSTDMT_bufferPool* const bufPool = (ZSTDMT_bufferPool*)ZSTD_customCalloc(
sizeof(ZSTDMT_bufferPool) + (maxNbBuffers-1) * sizeof(buffer_t), cMem);
if (bufPool==NULL) return NULL;
if (ZSTD_pthread_mutex_init(&bufPool->poolMutex, NULL)) {
if (ZSTD_pthread_mutex_init(&bufPool->poolMutex)) {
ZSTD_customFree(bufPool, cMem);
return NULL;
}
@ -363,7 +363,7 @@ static ZSTDMT_CCtxPool* ZSTDMT_createCCtxPool(int nbWorkers,
sizeof(ZSTDMT_CCtxPool) + (nbWorkers-1)*sizeof(ZSTD_CCtx*), cMem);
assert(nbWorkers > 0);
if (!cctxPool) return NULL;
if (ZSTD_pthread_mutex_init(&cctxPool->poolMutex, NULL)) {
if (ZSTD_pthread_mutex_init(&cctxPool->poolMutex)) {
ZSTD_customFree(cctxPool, cMem);
return NULL;
}
@ -535,10 +535,10 @@ static int ZSTDMT_serialState_init(serialState_t* serialState)
{
int initError = 0;
ZSTD_memset(serialState, 0, sizeof(*serialState));
initError |= ZSTD_pthread_mutex_init(&serialState->mutex, NULL);
initError |= ZSTD_pthread_cond_init(&serialState->cond, NULL);
initError |= ZSTD_pthread_mutex_init(&serialState->ldmWindowMutex, NULL);
initError |= ZSTD_pthread_cond_init(&serialState->ldmWindowCond, NULL);
initError |= ZSTD_pthread_mutex_init(&serialState->mutex);
initError |= ZSTD_pthread_cond_init(&serialState->cond, &serialState->mutex);
initError |= ZSTD_pthread_mutex_init(&serialState->ldmWindowMutex);
initError |= ZSTD_pthread_cond_init(&serialState->ldmWindowCond, &serialState->ldmWindowMutex);
return initError;
}
@ -561,7 +561,7 @@ static void ZSTDMT_serialState_update(serialState_t* serialState,
ZSTD_PTHREAD_MUTEX_LOCK(&serialState->mutex);
while (serialState->nextJobID < jobID) {
DEBUGLOG(5, "wait for serialState->cond");
ZSTD_pthread_cond_wait(&serialState->cond, &serialState->mutex);
ZSTD_pthread_cond_wait(&serialState->cond);
}
/* A future job may error and skip our job */
if (serialState->nextJobID == jobID) {
@ -856,8 +856,8 @@ static ZSTDMT_jobDescription* ZSTDMT_createJobsTable(U32* nbJobsPtr, ZSTD_custom
if (jobTable==NULL) return NULL;
*nbJobsPtr = nbJobs;
for (jobNb=0; jobNb<nbJobs; jobNb++) {
initError |= ZSTD_pthread_mutex_init(&jobTable[jobNb].job_mutex, NULL);
initError |= ZSTD_pthread_cond_init(&jobTable[jobNb].job_cond, NULL);
initError |= ZSTD_pthread_mutex_init(&jobTable[jobNb].job_mutex);
initError |= ZSTD_pthread_cond_init(&jobTable[jobNb].job_cond, &jobTable[jobNb].job_mutex);
}
if (initError != 0) {
ZSTDMT_freeJobsTable(jobTable, nbJobs, cMem);
@ -974,7 +974,7 @@ static void ZSTDMT_waitForAllJobsCompleted(ZSTDMT_CCtx* mtctx)
ZSTD_PTHREAD_MUTEX_LOCK(&mtctx->jobs[jobID].job_mutex);
while (mtctx->jobs[jobID].consumed < mtctx->jobs[jobID].src.size) {
DEBUGLOG(4, "waiting for jobCompleted signal from job %u", mtctx->doneJobID); /* we want to block when waiting for data to flush */
ZSTD_pthread_cond_wait(&mtctx->jobs[jobID].job_cond, &mtctx->jobs[jobID].job_mutex);
ZSTD_pthread_cond_wait(&mtctx->jobs[jobID].job_cond);
}
ZSTD_pthread_mutex_unlock(&mtctx->jobs[jobID].job_mutex);
mtctx->doneJobID++;
@ -1422,7 +1422,7 @@ static size_t ZSTDMT_flushProduced(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, u
}
DEBUGLOG(5, "waiting for something to flush from job %u (currently flushed: %u bytes)",
mtctx->doneJobID, (U32)mtctx->jobs[wJobID].dstFlushed);
ZSTD_pthread_cond_wait(&mtctx->jobs[wJobID].job_cond, &mtctx->jobs[wJobID].job_mutex); /* block when nothing to flush but some to come */
ZSTD_pthread_cond_wait(&mtctx->jobs[wJobID].job_cond); /* block when nothing to flush but some to come */
} }
/* try to flush something */
@ -1574,7 +1574,7 @@ static void ZSTDMT_waitForLdmComplete(ZSTDMT_CCtx* mtctx, buffer_t buffer)
ZSTD_PTHREAD_MUTEX_LOCK(mutex);
while (ZSTDMT_doesOverlapWindow(buffer, mtctx->serial.ldmWindow)) {
DEBUGLOG(5, "Waiting for LDM to finish...");
ZSTD_pthread_cond_wait(&mtctx->serial.ldmWindowCond, mutex);
ZSTD_pthread_cond_wait(&mtctx->serial.ldmWindowCond);
}
DEBUGLOG(6, "Done waiting for LDM to finish");
ZSTD_pthread_mutex_unlock(mutex);

View File

@ -842,8 +842,8 @@ _compressCleanup:
*/
void COVER_best_init(COVER_best_t *best) {
if (best==NULL) return; /* compatible with init on NULL */
(void)ZSTD_pthread_mutex_init(&best->mutex, NULL);
(void)ZSTD_pthread_cond_init(&best->cond, NULL);
(void)ZSTD_pthread_mutex_init(&best->mutex);
(void)ZSTD_pthread_cond_init(&best->cond, &best->mutex);
best->liveJobs = 0;
best->dict = NULL;
best->dictSize = 0;
@ -860,7 +860,7 @@ void COVER_best_wait(COVER_best_t *best) {
}
ZSTD_pthread_mutex_lock(&best->mutex);
while (best->liveJobs != 0) {
ZSTD_pthread_cond_wait(&best->cond, &best->mutex);
ZSTD_pthread_cond_wait(&best->cond);
}
ZSTD_pthread_mutex_unlock(&best->mutex);
}