1*3117ece4Schristos /** 2*3117ece4Schristos * Copyright (c) 2016 Tino Reichardt 3*3117ece4Schristos * All rights reserved. 4*3117ece4Schristos * 5*3117ece4Schristos * You can contact the author at: 6*3117ece4Schristos * - zstdmt source repository: https://github.com/mcmilk/zstdmt 7*3117ece4Schristos * 8*3117ece4Schristos * This source code is licensed under both the BSD-style license (found in the 9*3117ece4Schristos * LICENSE file in the root directory of this source tree) and the GPLv2 (found 10*3117ece4Schristos * in the COPYING file in the root directory of this source tree). 11*3117ece4Schristos * You may select, at your option, one of the above-listed licenses. 12*3117ece4Schristos */ 13*3117ece4Schristos 14*3117ece4Schristos /** 15*3117ece4Schristos * This file will hold wrapper for systems, which do not support pthreads 16*3117ece4Schristos */ 17*3117ece4Schristos 18*3117ece4Schristos #include "threading.h" 19*3117ece4Schristos 20*3117ece4Schristos /* create fake symbol to avoid empty translation unit warning */ 21*3117ece4Schristos int g_ZSTD_threading_useless_symbol; 22*3117ece4Schristos 23*3117ece4Schristos #if defined(ZSTD_MULTITHREAD) && defined(_WIN32) 24*3117ece4Schristos 25*3117ece4Schristos /** 26*3117ece4Schristos * Windows minimalist Pthread Wrapper 27*3117ece4Schristos */ 28*3117ece4Schristos 29*3117ece4Schristos 30*3117ece4Schristos /* === Dependencies === */ 31*3117ece4Schristos #include <process.h> 32*3117ece4Schristos #include <errno.h> 33*3117ece4Schristos 34*3117ece4Schristos 35*3117ece4Schristos /* === Implementation === */ 36*3117ece4Schristos 37*3117ece4Schristos typedef struct { 38*3117ece4Schristos void* (*start_routine)(void*); 39*3117ece4Schristos void* arg; 40*3117ece4Schristos int initialized; 41*3117ece4Schristos ZSTD_pthread_cond_t initialized_cond; 42*3117ece4Schristos ZSTD_pthread_mutex_t initialized_mutex; 43*3117ece4Schristos } ZSTD_thread_params_t; 44*3117ece4Schristos 45*3117ece4Schristos static unsigned __stdcall worker(void *arg) 46*3117ece4Schristos { 47*3117ece4Schristos void* (*start_routine)(void*); 48*3117ece4Schristos void* thread_arg; 49*3117ece4Schristos 50*3117ece4Schristos /* Initialized thread_arg and start_routine and signal main thread that we don't need it 51*3117ece4Schristos * to wait any longer. 52*3117ece4Schristos */ 53*3117ece4Schristos { 54*3117ece4Schristos ZSTD_thread_params_t* thread_param = (ZSTD_thread_params_t*)arg; 55*3117ece4Schristos thread_arg = thread_param->arg; 56*3117ece4Schristos start_routine = thread_param->start_routine; 57*3117ece4Schristos 58*3117ece4Schristos /* Signal main thread that we are running and do not depend on its memory anymore */ 59*3117ece4Schristos ZSTD_pthread_mutex_lock(&thread_param->initialized_mutex); 60*3117ece4Schristos thread_param->initialized = 1; 61*3117ece4Schristos ZSTD_pthread_cond_signal(&thread_param->initialized_cond); 62*3117ece4Schristos ZSTD_pthread_mutex_unlock(&thread_param->initialized_mutex); 63*3117ece4Schristos } 64*3117ece4Schristos 65*3117ece4Schristos start_routine(thread_arg); 66*3117ece4Schristos 67*3117ece4Schristos return 0; 68*3117ece4Schristos } 69*3117ece4Schristos 70*3117ece4Schristos int ZSTD_pthread_create(ZSTD_pthread_t* thread, const void* unused, 71*3117ece4Schristos void* (*start_routine) (void*), void* arg) 72*3117ece4Schristos { 73*3117ece4Schristos ZSTD_thread_params_t thread_param; 74*3117ece4Schristos (void)unused; 75*3117ece4Schristos 76*3117ece4Schristos if (thread==NULL) return -1; 77*3117ece4Schristos *thread = NULL; 78*3117ece4Schristos 79*3117ece4Schristos thread_param.start_routine = start_routine; 80*3117ece4Schristos thread_param.arg = arg; 81*3117ece4Schristos thread_param.initialized = 0; 82*3117ece4Schristos 83*3117ece4Schristos /* Setup thread initialization synchronization */ 84*3117ece4Schristos if(ZSTD_pthread_cond_init(&thread_param.initialized_cond, NULL)) { 85*3117ece4Schristos /* Should never happen on Windows */ 86*3117ece4Schristos return -1; 87*3117ece4Schristos } 88*3117ece4Schristos if(ZSTD_pthread_mutex_init(&thread_param.initialized_mutex, NULL)) { 89*3117ece4Schristos /* Should never happen on Windows */ 90*3117ece4Schristos ZSTD_pthread_cond_destroy(&thread_param.initialized_cond); 91*3117ece4Schristos return -1; 92*3117ece4Schristos } 93*3117ece4Schristos 94*3117ece4Schristos /* Spawn thread */ 95*3117ece4Schristos *thread = (HANDLE)_beginthreadex(NULL, 0, worker, &thread_param, 0, NULL); 96*3117ece4Schristos if (*thread==NULL) { 97*3117ece4Schristos ZSTD_pthread_mutex_destroy(&thread_param.initialized_mutex); 98*3117ece4Schristos ZSTD_pthread_cond_destroy(&thread_param.initialized_cond); 99*3117ece4Schristos return errno; 100*3117ece4Schristos } 101*3117ece4Schristos 102*3117ece4Schristos /* Wait for thread to be initialized */ 103*3117ece4Schristos ZSTD_pthread_mutex_lock(&thread_param.initialized_mutex); 104*3117ece4Schristos while(!thread_param.initialized) { 105*3117ece4Schristos ZSTD_pthread_cond_wait(&thread_param.initialized_cond, &thread_param.initialized_mutex); 106*3117ece4Schristos } 107*3117ece4Schristos ZSTD_pthread_mutex_unlock(&thread_param.initialized_mutex); 108*3117ece4Schristos ZSTD_pthread_mutex_destroy(&thread_param.initialized_mutex); 109*3117ece4Schristos ZSTD_pthread_cond_destroy(&thread_param.initialized_cond); 110*3117ece4Schristos 111*3117ece4Schristos return 0; 112*3117ece4Schristos } 113*3117ece4Schristos 114*3117ece4Schristos int ZSTD_pthread_join(ZSTD_pthread_t thread) 115*3117ece4Schristos { 116*3117ece4Schristos DWORD result; 117*3117ece4Schristos 118*3117ece4Schristos if (!thread) return 0; 119*3117ece4Schristos 120*3117ece4Schristos result = WaitForSingleObject(thread, INFINITE); 121*3117ece4Schristos CloseHandle(thread); 122*3117ece4Schristos 123*3117ece4Schristos switch (result) { 124*3117ece4Schristos case WAIT_OBJECT_0: 125*3117ece4Schristos return 0; 126*3117ece4Schristos case WAIT_ABANDONED: 127*3117ece4Schristos return EINVAL; 128*3117ece4Schristos default: 129*3117ece4Schristos return GetLastError(); 130*3117ece4Schristos } 131*3117ece4Schristos } 132*3117ece4Schristos 133*3117ece4Schristos #endif /* ZSTD_MULTITHREAD */ 134*3117ece4Schristos 135*3117ece4Schristos #if defined(ZSTD_MULTITHREAD) && DEBUGLEVEL >= 1 && !defined(_WIN32) 136*3117ece4Schristos 137*3117ece4Schristos #define ZSTD_DEPS_NEED_MALLOC 138*3117ece4Schristos #include "zstd_deps.h" 139*3117ece4Schristos 140*3117ece4Schristos int ZSTD_pthread_mutex_init(ZSTD_pthread_mutex_t* mutex, pthread_mutexattr_t const* attr) 141*3117ece4Schristos { 142*3117ece4Schristos assert(mutex != NULL); 143*3117ece4Schristos *mutex = (pthread_mutex_t*)ZSTD_malloc(sizeof(pthread_mutex_t)); 144*3117ece4Schristos if (!*mutex) 145*3117ece4Schristos return 1; 146*3117ece4Schristos return pthread_mutex_init(*mutex, attr); 147*3117ece4Schristos } 148*3117ece4Schristos 149*3117ece4Schristos int ZSTD_pthread_mutex_destroy(ZSTD_pthread_mutex_t* mutex) 150*3117ece4Schristos { 151*3117ece4Schristos assert(mutex != NULL); 152*3117ece4Schristos if (!*mutex) 153*3117ece4Schristos return 0; 154*3117ece4Schristos { 155*3117ece4Schristos int const ret = pthread_mutex_destroy(*mutex); 156*3117ece4Schristos ZSTD_free(*mutex); 157*3117ece4Schristos return ret; 158*3117ece4Schristos } 159*3117ece4Schristos } 160*3117ece4Schristos 161*3117ece4Schristos int ZSTD_pthread_cond_init(ZSTD_pthread_cond_t* cond, pthread_condattr_t const* attr) 162*3117ece4Schristos { 163*3117ece4Schristos assert(cond != NULL); 164*3117ece4Schristos *cond = (pthread_cond_t*)ZSTD_malloc(sizeof(pthread_cond_t)); 165*3117ece4Schristos if (!*cond) 166*3117ece4Schristos return 1; 167*3117ece4Schristos return pthread_cond_init(*cond, attr); 168*3117ece4Schristos } 169*3117ece4Schristos 170*3117ece4Schristos int ZSTD_pthread_cond_destroy(ZSTD_pthread_cond_t* cond) 171*3117ece4Schristos { 172*3117ece4Schristos assert(cond != NULL); 173*3117ece4Schristos if (!*cond) 174*3117ece4Schristos return 0; 175*3117ece4Schristos { 176*3117ece4Schristos int const ret = pthread_cond_destroy(*cond); 177*3117ece4Schristos ZSTD_free(*cond); 178*3117ece4Schristos return ret; 179*3117ece4Schristos } 180*3117ece4Schristos } 181*3117ece4Schristos 182*3117ece4Schristos #endif 183