1 /**
2  * Copyright (c) 2016 Tino Reichardt
3  * All rights reserved.
4  *
5  * This source code is licensed under both the BSD-style license (found in the
6  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7  * in the COPYING file in the root directory of this source tree).
8  *
9  * You can contact the author at:
10  * - zstdmt source repository: https://github.com/mcmilk/zstdmt
11  */
12 
13 /**
14  * This file will hold wrapper for systems, which do not support pthreads
15  */
16 
17 #include "threading.h"
18 
19 /* create fake symbol to avoid empty translation unit warning */
20 int g_ZSTD_threading_useless_symbol;
21 
22 #if defined(ZSTD_MULTITHREAD) && defined(_WIN32)
23 
24 /**
25  * Windows minimalist Pthread Wrapper, based on :
26  * http://www.cse.wustl.edu/~schmidt/win32-cv-1.html
27  */
28 
29 
30 /* ===  Dependencies  === */
31 #include <process.h>
32 #include <errno.h>
33 
34 
35 /* ===  Implementation  === */
36 
worker(void * arg)37 static unsigned __stdcall worker(void *arg)
38 {
39     ZSTD_pthread_t* const thread = (ZSTD_pthread_t*) arg;
40     thread->arg = thread->start_routine(thread->arg);
41     return 0;
42 }
43 
ZSTD_pthread_create(ZSTD_pthread_t * thread,const void * unused,void * (* start_routine)(void *),void * arg)44 int ZSTD_pthread_create(ZSTD_pthread_t* thread, const void* unused,
45             void* (*start_routine) (void*), void* arg)
46 {
47     (void)unused;
48     thread->arg = arg;
49     thread->start_routine = start_routine;
50     thread->handle = (HANDLE) _beginthreadex(NULL, 0, worker, thread, 0, NULL);
51 
52     if (!thread->handle)
53         return errno;
54     else
55         return 0;
56 }
57 
ZSTD_pthread_join(ZSTD_pthread_t thread,void ** value_ptr)58 int ZSTD_pthread_join(ZSTD_pthread_t thread, void **value_ptr)
59 {
60     DWORD result;
61 
62     if (!thread.handle) return 0;
63 
64     result = WaitForSingleObject(thread.handle, INFINITE);
65     switch (result) {
66     case WAIT_OBJECT_0:
67         if (value_ptr) *value_ptr = thread.arg;
68         return 0;
69     case WAIT_ABANDONED:
70         return EINVAL;
71     default:
72         return GetLastError();
73     }
74 }
75 
76 #endif   /* ZSTD_MULTITHREAD */
77 
78 #if defined(ZSTD_MULTITHREAD) && DEBUGLEVEL >= 1 && !defined(_WIN32)
79 
80 #include <stdlib.h>
81 
ZSTD_pthread_mutex_init(ZSTD_pthread_mutex_t * mutex,pthread_mutexattr_t const * attr)82 int ZSTD_pthread_mutex_init(ZSTD_pthread_mutex_t* mutex, pthread_mutexattr_t const* attr)
83 {
84     *mutex = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
85     if (!*mutex)
86         return 1;
87     return pthread_mutex_init(*mutex, attr);
88 }
89 
ZSTD_pthread_mutex_destroy(ZSTD_pthread_mutex_t * mutex)90 int ZSTD_pthread_mutex_destroy(ZSTD_pthread_mutex_t* mutex)
91 {
92     if (!*mutex)
93         return 0;
94     {
95         int const ret = pthread_mutex_destroy(*mutex);
96         free(*mutex);
97         return ret;
98     }
99 }
100 
ZSTD_pthread_cond_init(ZSTD_pthread_cond_t * cond,pthread_condattr_t const * attr)101 int ZSTD_pthread_cond_init(ZSTD_pthread_cond_t* cond, pthread_condattr_t const* attr)
102 {
103     *cond = (pthread_cond_t*)malloc(sizeof(pthread_cond_t));
104     if (!*cond)
105         return 1;
106     return pthread_cond_init(*cond, attr);
107 }
108 
ZSTD_pthread_cond_destroy(ZSTD_pthread_cond_t * cond)109 int ZSTD_pthread_cond_destroy(ZSTD_pthread_cond_t* cond)
110 {
111     if (!*cond)
112         return 0;
113     {
114         int const ret = pthread_cond_destroy(*cond);
115         free(*cond);
116         return ret;
117     }
118 }
119 
120 #endif
121