Coverage Report

Created: 2024-09-08 06:26

/src/zstd/lib/common/threading.c
Line
Count
Source (jump to first uncovered line)
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 */
21
int g_ZSTD_threading_useless_symbol;
22
23
#if defined(ZSTD_MULTITHREAD) && defined(_WIN32)
24
25
/**
26
 * Windows minimalist Pthread Wrapper
27
 */
28
29
30
/* ===  Dependencies  === */
31
#include <process.h>
32
#include <errno.h>
33
34
35
/* ===  Implementation  === */
36
37
typedef struct {
38
    void* (*start_routine)(void*);
39
    void* arg;
40
    int initialized;
41
    ZSTD_pthread_cond_t initialized_cond;
42
    ZSTD_pthread_mutex_t initialized_mutex;
43
} ZSTD_thread_params_t;
44
45
static unsigned __stdcall worker(void *arg)
46
{
47
    void* (*start_routine)(void*);
48
    void* thread_arg;
49
50
    /* Initialized thread_arg and start_routine and signal main thread that we don't need it
51
     * to wait any longer.
52
     */
53
    {
54
        ZSTD_thread_params_t*  thread_param = (ZSTD_thread_params_t*)arg;
55
        thread_arg = thread_param->arg;
56
        start_routine = thread_param->start_routine;
57
58
        /* Signal main thread that we are running and do not depend on its memory anymore */
59
        ZSTD_pthread_mutex_lock(&thread_param->initialized_mutex);
60
        thread_param->initialized = 1;
61
        ZSTD_pthread_cond_signal(&thread_param->initialized_cond);
62
        ZSTD_pthread_mutex_unlock(&thread_param->initialized_mutex);
63
    }
64
65
    start_routine(thread_arg);
66
67
    return 0;
68
}
69
70
int ZSTD_pthread_create(ZSTD_pthread_t* thread, const void* unused,
71
            void* (*start_routine) (void*), void* arg)
72
{
73
    ZSTD_thread_params_t thread_param;
74
    (void)unused;
75
76
    if (thread==NULL) return -1;
77
    *thread = NULL;
78
79
    thread_param.start_routine = start_routine;
80
    thread_param.arg = arg;
81
    thread_param.initialized = 0;
82
83
    /* Setup thread initialization synchronization */
84
    if(ZSTD_pthread_cond_init(&thread_param.initialized_cond, NULL)) {
85
        /* Should never happen on Windows */
86
        return -1;
87
    }
88
    if(ZSTD_pthread_mutex_init(&thread_param.initialized_mutex, NULL)) {
89
        /* Should never happen on Windows */
90
        ZSTD_pthread_cond_destroy(&thread_param.initialized_cond);
91
        return -1;
92
    }
93
94
    /* Spawn thread */
95
    *thread = (HANDLE)_beginthreadex(NULL, 0, worker, &thread_param, 0, NULL);
96
    if (*thread==NULL) {
97
        ZSTD_pthread_mutex_destroy(&thread_param.initialized_mutex);
98
        ZSTD_pthread_cond_destroy(&thread_param.initialized_cond);
99
        return errno;
100
    }
101
102
    /* Wait for thread to be initialized */
103
    ZSTD_pthread_mutex_lock(&thread_param.initialized_mutex);
104
    while(!thread_param.initialized) {
105
        ZSTD_pthread_cond_wait(&thread_param.initialized_cond, &thread_param.initialized_mutex);
106
    }
107
    ZSTD_pthread_mutex_unlock(&thread_param.initialized_mutex);
108
    ZSTD_pthread_mutex_destroy(&thread_param.initialized_mutex);
109
    ZSTD_pthread_cond_destroy(&thread_param.initialized_cond);
110
111
    return 0;
112
}
113
114
int ZSTD_pthread_join(ZSTD_pthread_t thread)
115
{
116
    DWORD result;
117
118
    if (!thread) return 0;
119
120
    result = WaitForSingleObject(thread, INFINITE);
121
    CloseHandle(thread);
122
123
    switch (result) {
124
    case WAIT_OBJECT_0:
125
        return 0;
126
    case WAIT_ABANDONED:
127
        return EINVAL;
128
    default:
129
        return GetLastError();
130
    }
131
}
132
133
#endif   /* ZSTD_MULTITHREAD */
134
135
#if defined(ZSTD_MULTITHREAD) && DEBUGLEVEL >= 1 && !defined(_WIN32)
136
137
#define ZSTD_DEPS_NEED_MALLOC
138
#include "zstd_deps.h"
139
140
int ZSTD_pthread_mutex_init(ZSTD_pthread_mutex_t* mutex, pthread_mutexattr_t const* attr)
141
0
{
142
0
    assert(mutex != NULL);
143
0
    *mutex = (pthread_mutex_t*)ZSTD_malloc(sizeof(pthread_mutex_t));
144
0
    if (!*mutex)
145
0
        return 1;
146
0
    return pthread_mutex_init(*mutex, attr);
147
0
}
148
149
int ZSTD_pthread_mutex_destroy(ZSTD_pthread_mutex_t* mutex)
150
0
{
151
0
    assert(mutex != NULL);
152
0
    if (!*mutex)
153
0
        return 0;
154
0
    {
155
0
        int const ret = pthread_mutex_destroy(*mutex);
156
0
        ZSTD_free(*mutex);
157
0
        return ret;
158
0
    }
159
0
}
160
161
int ZSTD_pthread_cond_init(ZSTD_pthread_cond_t* cond, pthread_condattr_t const* attr)
162
0
{
163
0
    assert(cond != NULL);
164
0
    *cond = (pthread_cond_t*)ZSTD_malloc(sizeof(pthread_cond_t));
165
0
    if (!*cond)
166
0
        return 1;
167
0
    return pthread_cond_init(*cond, attr);
168
0
}
169
170
int ZSTD_pthread_cond_destroy(ZSTD_pthread_cond_t* cond)
171
0
{
172
0
    assert(cond != NULL);
173
0
    if (!*cond)
174
0
        return 0;
175
0
    {
176
0
        int const ret = pthread_cond_destroy(*cond);
177
0
        ZSTD_free(*cond);
178
0
        return ret;
179
0
    }
180
0
}
181
182
#endif