1 /*
2 * Copyright(c) 2019 Intel Corporation
3 * SPDX - License - Identifier: BSD - 2 - Clause - Patent
4 */
5
6 // Summary:
7 // EbThreads contains wrappers functions that hide
8 // platform specific objects such as threads, semaphores,
9 // and mutexs. The goal is to eliminiate platform #define
10 // in the code.
11
12 /****************************************
13 * Universal Includes
14 ****************************************/
15 #include <stdlib.h>
16 #include "EbDefinitions.h"
17 #include "EbThreads.h"
18
19 /****************************************
20 * Win32 Includes
21 ****************************************/
22 #ifdef _WIN32
23 #include <windows.h>
24 #elif __unix__
25 #include <pthread.h>
26 #include <semaphore.h>
27 #include <time.h>
28 #include <errno.h>
29 #else
30 #error OS/Platform not supported.
31 #endif // _WIN32
32 #if PRINTF_TIME
33 #ifdef _WIN32
34 #include <time.h>
printfTime(const char * fmt,...)35 void printfTime(const char *fmt, ...)
36 {
37 va_list args;
38 va_start(args, fmt);
39 SVT_LOG(" [%i ms]\t", ((int)clock()));
40 vprintf(fmt, args);
41 va_end(args);
42 }
43 #endif
44 #endif
45 /****************************************
46 * eb_vp9_create_thread
47 ****************************************/
eb_vp9_create_thread(void * thread_function (void *),void * thread_context)48 EbHandle eb_vp9_create_thread(
49 void *thread_function(void *),
50 void *thread_context)
51 {
52 EbHandle thread_handle = NULL;
53
54 #ifdef _WIN32
55
56 thread_handle = (EbHandle) CreateThread(
57 NULL, // default security attributes
58 0, // default stack size
59 (LPTHREAD_START_ROUTINE) thread_function, // function to be tied to the new thread
60 thread_context, // context to be tied to the new thread
61 0, // thread active when created
62 NULL); // new thread ID
63
64 #elif __unix__
65
66 pthread_attr_t attr;
67 struct sched_param param = {
68 .sched_priority = 99
69 };
70 pthread_attr_init(&attr);
71 pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
72 pthread_attr_setschedparam(&attr, ¶m);
73
74 pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
75
76 thread_handle = (pthread_t*) malloc(sizeof(pthread_t));
77 if (thread_handle != NULL) {
78 int ret = pthread_create(
79 (pthread_t*)thread_handle, // Thread handle
80 &attr, // attributes
81 thread_function, // function to be run by new thread
82 thread_context);
83
84 if (ret != 0) {
85 if (ret == EPERM) {
86
87 pthread_cancel(*((pthread_t*)thread_handle));
88 free(thread_handle);
89
90 thread_handle = (pthread_t*)malloc(sizeof(pthread_t));
91 if (thread_handle != NULL) {
92 pthread_create(
93 (pthread_t*)thread_handle, // Thread handle
94 (const pthread_attr_t*)EB_NULL, // attributes
95 thread_function, // function to be run by new thread
96 thread_context);
97 }
98 }
99 }
100 }
101 pthread_attr_destroy(&attr);
102 #endif // _WIN32
103
104 return thread_handle;
105 }
106
107 /****************************************
108 * eb_start_thread
109 ****************************************/
eb_start_thread(EbHandle thread_handle)110 EbErrorType eb_start_thread(
111 EbHandle thread_handle)
112 {
113 EbErrorType error_return = EB_ErrorNone;
114
115 /* Note JMJ 9/6/2011
116 The thread Pause/Resume functionality is being removed. The main reason is that
117 POSIX Threads (aka pthreads) does not support this functionality. The destructor
118 and deinit code is safe as along as when EbDestropyThread is called on a thread,
119 the thread is immediately destroyed and its stack cleared.
120
121 The Encoder Start/Stop functionality, which previously used the thread Pause/Resume
122 functions could be implemented with mutex checks either at the head of the pipeline,
123 or throughout the code if a more responsive Pause is needed.
124 */
125
126 #ifdef _WIN32
127 //error_return = ResumeThread((HANDLE) thread_handle) ? EB_ErrorThreadUnresponsive : EB_ErrorNone;
128 #elif __unix__
129 #endif // _WIN32
130
131 error_return = (thread_handle) ? EB_ErrorNone : EB_ErrorNullThread;
132
133 return error_return;
134 }
135
136 /****************************************
137 * eb_stop_thread
138 ****************************************/
eb_stop_thread(EbHandle thread_handle)139 EbErrorType eb_stop_thread(
140 EbHandle thread_handle)
141 {
142 EbErrorType error_return = EB_ErrorNone;
143
144 #ifdef _WIN32
145 //error_return = SuspendThread((HANDLE) thread_handle) ? EB_ErrorThreadUnresponsive : EB_ErrorNone;
146 #elif __unix__
147 #endif // _WIN32
148
149 error_return = (thread_handle) ? EB_ErrorNone : EB_ErrorNullThread;
150
151 return error_return;
152 }
153
154 /****************************************
155 * eb_vp9_destroy_thread
156 ****************************************/
eb_vp9_destroy_thread(EbHandle thread_handle)157 EbErrorType eb_vp9_destroy_thread(
158 EbHandle thread_handle)
159 {
160 EbErrorType error_return = EB_ErrorNone;
161
162 #ifdef _WIN32
163 error_return = TerminateThread((HANDLE) thread_handle, 0) ? EB_ErrorDestroyThreadFailed : EB_ErrorNone;
164 #elif __unix__
165 error_return = pthread_cancel(*((pthread_t*) thread_handle)) ? EB_ErrorDestroyThreadFailed : EB_ErrorNone;
166 pthread_join(*((pthread_t*) thread_handle), NULL);
167 free(thread_handle);
168 #endif // _WIN32
169
170 return error_return;
171 }
172
173 /***************************************
174 * eb_vp9_create_semaphore
175 ***************************************/
eb_vp9_create_semaphore(uint32_t initial_count,uint32_t max_count)176 EbHandle eb_vp9_create_semaphore(
177 uint32_t initial_count,
178 uint32_t max_count)
179 {
180 EbHandle semaphore_handle = NULL;
181 (void) max_count;
182
183 #ifdef _WIN32
184 semaphore_handle = (EbHandle) CreateSemaphore(
185 NULL, // default security attributes
186 initial_count, // initial semaphore count
187 max_count, // maximum semaphore count
188 NULL); // semaphore is not named
189 #elif __unix__
190 semaphore_handle = (sem_t*) malloc(sizeof(sem_t));
191 sem_init(
192 (sem_t*) semaphore_handle, // semaphore handle
193 0, // shared semaphore (not local)
194 initial_count); // initial count
195 #endif // _WIN32
196
197 return semaphore_handle;
198 }
199
200 /***************************************
201 * eb_vp9_post_semaphore
202 ***************************************/
eb_vp9_post_semaphore(EbHandle semaphore_handle)203 EbErrorType eb_vp9_post_semaphore(
204 EbHandle semaphore_handle)
205 {
206 EbErrorType return_error = EB_ErrorNone;
207
208 #ifdef _WIN32
209 return_error = ReleaseSemaphore(
210 semaphore_handle, // semaphore handle
211 1, // amount to increment the semaphore
212 NULL) // pointer to previous count (optional)
213 ? EB_ErrorSemaphoreUnresponsive : EB_ErrorNone;
214 #elif __unix__
215 return_error = sem_post((sem_t*) semaphore_handle) ? EB_ErrorSemaphoreUnresponsive : EB_ErrorNone;
216 #endif // _WIN32
217
218 return return_error;
219 }
220
221 /***************************************
222 * eb_vp9_block_on_semaphore
223 ***************************************/
eb_vp9_block_on_semaphore(EbHandle semaphore_handle)224 EbErrorType eb_vp9_block_on_semaphore(
225 EbHandle semaphore_handle)
226 {
227 EbErrorType return_error = EB_ErrorNone;
228
229 #ifdef _WIN32
230 return_error = WaitForSingleObject((HANDLE) semaphore_handle, INFINITE) ? EB_ErrorSemaphoreUnresponsive : EB_ErrorNone;
231 #elif __unix__
232 return_error = sem_wait((sem_t*) semaphore_handle) ? EB_ErrorSemaphoreUnresponsive : EB_ErrorNone;
233 #endif // _WIN32
234
235 return return_error;
236 }
237
238 /***************************************
239 * eb_vp9_destroy_semaphore
240 ***************************************/
eb_vp9_destroy_semaphore(EbHandle semaphore_handle)241 EbErrorType eb_vp9_destroy_semaphore(
242 EbHandle semaphore_handle)
243 {
244 EbErrorType return_error = EB_ErrorNone;
245
246 #ifdef _WIN32
247 return_error = CloseHandle((HANDLE) semaphore_handle) ? EB_ErrorDestroySemaphoreFailed : EB_ErrorNone;
248 #elif __unix__
249 return_error = sem_destroy((sem_t*) semaphore_handle) ? EB_ErrorDestroySemaphoreFailed : EB_ErrorNone;
250 free(semaphore_handle);
251 #endif // _WIN32
252
253 return return_error;
254 }
255 /***************************************
256 * eb_vp9_create_mutex
257 ***************************************/
eb_vp9_create_mutex(void)258 EbHandle eb_vp9_create_mutex(
259 void)
260 {
261 EbHandle mutex_handle = NULL;
262
263 #ifdef _WIN32
264 mutex_handle = (EbHandle) CreateMutex(
265 NULL, // default security attributes
266 FALSE, // FALSE := not initially owned
267 NULL); // mutex is not named
268
269 #elif __unix__
270
271 mutex_handle = (EbHandle) malloc(sizeof(pthread_mutex_t));
272 if (mutex_handle != NULL) {
273 pthread_mutex_init(
274 (pthread_mutex_t*)mutex_handle,
275 NULL); // default attributes
276 }
277 #endif // _WIN32
278
279 return mutex_handle;
280 }
281
282 /***************************************
283 * EbPostMutex
284 ***************************************/
eb_vp9_release_mutex(EbHandle mutex_handle)285 EbErrorType eb_vp9_release_mutex(
286 EbHandle mutex_handle)
287 {
288 EbErrorType return_error = EB_ErrorNone;
289
290 #ifdef _WIN32
291 return_error = ReleaseMutex((HANDLE) mutex_handle)? EB_ErrorCreateMutexFailed : EB_ErrorNone;
292 #elif __unix__
293 return_error = pthread_mutex_unlock((pthread_mutex_t*) mutex_handle) ? EB_ErrorCreateMutexFailed : EB_ErrorNone;
294 #endif // _WIN32
295
296 return return_error;
297 }
298
299 /***************************************
300 * eb_vp9_block_on_mutex
301 ***************************************/
eb_vp9_block_on_mutex(EbHandle mutex_handle)302 EbErrorType eb_vp9_block_on_mutex(
303 EbHandle mutex_handle)
304 {
305 EbErrorType return_error = EB_ErrorNone;
306
307 #ifdef _WIN32
308 return_error = WaitForSingleObject((HANDLE) mutex_handle, INFINITE) ? EB_ErrorMutexUnresponsive : EB_ErrorNone;
309 #elif __unix__
310 return_error = pthread_mutex_lock((pthread_mutex_t*) mutex_handle) ? EB_ErrorMutexUnresponsive : EB_ErrorNone;
311 #endif // _WIN32
312
313 return return_error;
314 }
315
316 /***************************************
317 * eb_vp9_block_on_mutex_timeout
318 ***************************************/
eb_vp9_block_on_mutex_timeout(EbHandle mutex_handle,uint32_t timeout)319 EbErrorType eb_vp9_block_on_mutex_timeout(
320 EbHandle mutex_handle,
321 uint32_t timeout)
322 {
323 EbErrorType return_error = EB_ErrorNone;
324
325 #ifdef _WIN32
326 WaitForSingleObject((HANDLE) mutex_handle, timeout);
327 #elif __unix__
328 return_error = pthread_mutex_lock((pthread_mutex_t*) mutex_handle) ? EB_ErrorMutexUnresponsive : EB_ErrorNone;
329 (void) timeout;
330 #endif // _WIN32
331
332 return return_error;
333 }
334
335 /***************************************
336 * eb_vp9_destroy_mutex
337 ***************************************/
eb_vp9_destroy_mutex(EbHandle mutex_handle)338 EbErrorType eb_vp9_destroy_mutex(
339 EbHandle mutex_handle)
340 {
341 EbErrorType return_error = EB_ErrorNone;
342
343 #ifdef _WIN32
344 return_error = CloseHandle((HANDLE) mutex_handle) ? EB_ErrorDestroyMutexFailed : EB_ErrorNone;
345 #elif __unix__
346 return_error = pthread_mutex_destroy((pthread_mutex_t*) mutex_handle) ? EB_ErrorDestroyMutexFailed : EB_ErrorNone;
347 free(mutex_handle);
348 #endif // _WIN32
349
350 return return_error;
351 }
352