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