1 /*
2 * Copyright © 2018-2021, VideoLAN and dav1d authors
3 * Copyright © 2018, Two Orioles, LLC
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice, this
10 * list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #ifndef DAV1D_SRC_THREAD_H
29 #define DAV1D_SRC_THREAD_H
30
31 #if defined(_WIN32)
32
33 #include <limits.h>
34 #include <windows.h>
35
36 #define PTHREAD_MUTEX_INITIALIZER SRWLOCK_INIT
37 #define PTHREAD_ONCE_INIT INIT_ONCE_STATIC_INIT
38
39 typedef struct {
40 HANDLE h;
41 void *(*func)(void*);
42 void *arg;
43 } pthread_t;
44
45 typedef struct {
46 unsigned stack_size;
47 } pthread_attr_t;
48
49 typedef SRWLOCK pthread_mutex_t;
50 typedef CONDITION_VARIABLE pthread_cond_t;
51 typedef INIT_ONCE pthread_once_t;
52
53 void dav1d_init_thread(void);
54 void dav1d_set_thread_name(const wchar_t *name);
55 #define dav1d_set_thread_name(name) dav1d_set_thread_name(L##name)
56
57 int dav1d_pthread_create(pthread_t *thread, const pthread_attr_t *attr,
58 void *(*func)(void*), void *arg);
59 int dav1d_pthread_join(pthread_t *thread, void **res);
60 int dav1d_pthread_once(pthread_once_t *once_control,
61 void (*init_routine)(void));
62
63 #define pthread_create dav1d_pthread_create
64 #define pthread_join(thread, res) dav1d_pthread_join(&(thread), res)
65 #define pthread_once dav1d_pthread_once
66
pthread_attr_init(pthread_attr_t * const attr)67 static inline int pthread_attr_init(pthread_attr_t *const attr) {
68 attr->stack_size = 0;
69 return 0;
70 }
71
pthread_attr_destroy(pthread_attr_t * const attr)72 static inline int pthread_attr_destroy(pthread_attr_t *const attr) {
73 return 0;
74 }
75
pthread_attr_setstacksize(pthread_attr_t * const attr,const size_t stack_size)76 static inline int pthread_attr_setstacksize(pthread_attr_t *const attr,
77 const size_t stack_size)
78 {
79 if (stack_size > UINT_MAX) return 1;
80 attr->stack_size = (unsigned) stack_size;
81 return 0;
82 }
83
pthread_mutex_init(pthread_mutex_t * const mutex,const void * const attr)84 static inline int pthread_mutex_init(pthread_mutex_t *const mutex,
85 const void *const attr)
86 {
87 InitializeSRWLock(mutex);
88 return 0;
89 }
90
pthread_mutex_destroy(pthread_mutex_t * const mutex)91 static inline int pthread_mutex_destroy(pthread_mutex_t *const mutex) {
92 return 0;
93 }
94
pthread_mutex_lock(pthread_mutex_t * const mutex)95 static inline int pthread_mutex_lock(pthread_mutex_t *const mutex) {
96 AcquireSRWLockExclusive(mutex);
97 return 0;
98 }
99
pthread_mutex_unlock(pthread_mutex_t * const mutex)100 static inline int pthread_mutex_unlock(pthread_mutex_t *const mutex) {
101 ReleaseSRWLockExclusive(mutex);
102 return 0;
103 }
104
pthread_cond_init(pthread_cond_t * const cond,const void * const attr)105 static inline int pthread_cond_init(pthread_cond_t *const cond,
106 const void *const attr)
107 {
108 InitializeConditionVariable(cond);
109 return 0;
110 }
111
pthread_cond_destroy(pthread_cond_t * const cond)112 static inline int pthread_cond_destroy(pthread_cond_t *const cond) {
113 return 0;
114 }
115
pthread_cond_wait(pthread_cond_t * const cond,pthread_mutex_t * const mutex)116 static inline int pthread_cond_wait(pthread_cond_t *const cond,
117 pthread_mutex_t *const mutex)
118 {
119 return !SleepConditionVariableSRW(cond, mutex, INFINITE, 0);
120 }
121
pthread_cond_signal(pthread_cond_t * const cond)122 static inline int pthread_cond_signal(pthread_cond_t *const cond) {
123 WakeConditionVariable(cond);
124 return 0;
125 }
126
pthread_cond_broadcast(pthread_cond_t * const cond)127 static inline int pthread_cond_broadcast(pthread_cond_t *const cond) {
128 WakeAllConditionVariable(cond);
129 return 0;
130 }
131
132 #else
133
134 #include <pthread.h>
135 #if defined(__FreeBSD__)
136 /* ALIGN from <sys/param.h> conflicts with ALIGN from "common/attributes.h" */
137 #define _SYS_PARAM_H_
138 #include <sys/types.h>
139 #endif
140 #if HAVE_PTHREAD_NP_H
141 #include <pthread_np.h>
142 #endif
143
144 #define dav1d_init_thread() do {} while (0)
145
146 /* Thread naming support */
147
148 #ifdef __linux__
149
150 #include <sys/prctl.h>
151
dav1d_set_thread_name(const char * const name)152 static inline void dav1d_set_thread_name(const char *const name) {
153 prctl(PR_SET_NAME, name);
154 }
155
156 #elif HAVE_PTHREAD_SETNAME_NP && defined(__APPLE__)
157
dav1d_set_thread_name(const char * const name)158 static inline void dav1d_set_thread_name(const char *const name) {
159 pthread_setname_np(name);
160 }
161
162 #elif HAVE_PTHREAD_SETNAME_NP && defined(__NetBSD__)
163
dav1d_set_thread_name(const char * const name)164 static inline void dav1d_set_thread_name(const char *const name) {
165 pthread_setname_np(pthread_self(), "%s", (void*)name);
166 }
167
168 #elif HAVE_PTHREAD_SETNAME_NP
169
dav1d_set_thread_name(const char * const name)170 static inline void dav1d_set_thread_name(const char *const name) {
171 pthread_setname_np(pthread_self(), name);
172 }
173
174 #elif HAVE_PTHREAD_SET_NAME_NP
175
dav1d_set_thread_name(const char * const name)176 static inline void dav1d_set_thread_name(const char *const name) {
177 pthread_set_name_np(pthread_self(), name);
178 }
179
180 #elif defined(__HAIKU__)
181
182 #include <os/kernel/OS.h>
183
dav1d_set_thread_name(const char * const name)184 static inline void dav1d_set_thread_name(const char *const name) {
185 rename_thread(find_thread(NULL), name);
186 }
187
188 #else
189
190 #define dav1d_set_thread_name(name) do {} while (0)
191
192 #endif
193
194 #endif
195
196 #endif /* DAV1D_SRC_THREAD_H */
197