Line data Source code
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 : * Win32 Includes
20 : ****************************************/
21 : #ifdef _WIN32
22 : #include <windows.h>
23 : #else
24 : #include <stdio.h>
25 : #include <errno.h>
26 : #include <fcntl.h>
27 : #include <pthread.h>
28 : #include <semaphore.h>
29 : #include <unistd.h>
30 : #endif // _WIN32
31 : #if PRINTF_TIME
32 : #include <time.h>
33 : #ifdef _WIN32
34 : void printfTime(const char *fmt, ...)
35 : {
36 : va_list args;
37 : va_start(args, fmt);
38 : printf(" [%i ms]\t", ((int32_t)clock()));
39 : vprintf(fmt, args);
40 : va_end(args);
41 : }
42 : #endif
43 : #endif
44 :
45 : /****************************************
46 : * eb_create_thread
47 : ****************************************/
48 110 : EbHandle eb_create_thread(
49 : void *thread_function(void *),
50 : void *thread_context)
51 : {
52 110 : 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 : #else
65 :
66 : pthread_attr_t attr;
67 110 : struct sched_param param = {
68 : .sched_priority = 99
69 : };
70 110 : pthread_attr_init(&attr);
71 110 : pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
72 110 : pthread_attr_setschedparam(&attr, ¶m);
73 :
74 110 : pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
75 :
76 110 : thread_handle = (pthread_t*)malloc(sizeof(pthread_t));
77 110 : if (thread_handle != NULL) {
78 110 : int32_t 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 110 : if (ret != 0) {
85 110 : if (ret == EPERM) {
86 110 : pthread_cancel(*((pthread_t*)thread_handle));
87 110 : free(thread_handle);
88 :
89 110 : thread_handle = (pthread_t*)malloc(sizeof(pthread_t));
90 110 : if (thread_handle != NULL) {
91 110 : pthread_create(
92 : (pthread_t*)thread_handle, // Thread handle
93 : (const pthread_attr_t*)EB_NULL, // attributes
94 : thread_function, // function to be run by new thread
95 : thread_context);
96 : }
97 : }
98 : }
99 : }
100 110 : pthread_attr_destroy(&attr);
101 : #endif // _WIN32
102 :
103 110 : return thread_handle;
104 : }
105 :
106 : ///****************************************
107 : // * eb_start_thread
108 : // ****************************************/
109 : //EbErrorType eb_start_thread(
110 : // EbHandle thread_handle)
111 : //{
112 : // EbErrorType error_return = EB_ErrorNone;
113 : //
114 : // /* Note JMJ 9/6/2011
115 : // The thread Pause/Resume functionality is being removed. The main reason is that
116 : // POSIX Threads (aka pthreads) does not support this functionality. The destructor
117 : // and deinit code is safe as along as when EbDestropyThread is called on a thread,
118 : // the thread is immediately destroyed and its stack cleared.
119 : //
120 : // The Encoder Start/Stop functionality, which previously used the thread Pause/Resume
121 : // functions could be implemented with mutex checks either at the head of the pipeline,
122 : // or throughout the code if a more responsive Pause is needed.
123 : // */
124 : //
125 : //#ifdef _WIN32
126 : // //error_return = ResumeThread((HANDLE) thread_handle) ? EB_ErrorThreadUnresponsive : EB_ErrorNone;
127 : //#else
128 : //#endif // _WIN32
129 : //
130 : // error_return = (thread_handle) ? EB_ErrorNone : EB_ErrorNullThread;
131 : //
132 : // return error_return;
133 : //}
134 : //
135 : ///****************************************
136 : // * eb_stop_thread
137 : // ****************************************/
138 : //EbErrorType eb_stop_thread(
139 : // EbHandle thread_handle)
140 : //{
141 : // EbErrorType error_return = EB_ErrorNone;
142 : //
143 : //#ifdef _WIN32
144 : // //error_return = SuspendThread((HANDLE) thread_handle) ? EB_ErrorThreadUnresponsive : EB_ErrorNone;
145 : //#else
146 : //#endif // _WIN32
147 : //
148 : // error_return = (thread_handle) ? EB_ErrorNone : EB_ErrorNullThread;
149 : //
150 : // return error_return;
151 : //}
152 : //
153 : /****************************************
154 : * eb_destroy_thread
155 : ****************************************/
156 110 : EbErrorType eb_destroy_thread(
157 : EbHandle thread_handle)
158 : {
159 110 : EbErrorType error_return = EB_ErrorNone;
160 :
161 : #ifdef _WIN32
162 : error_return = !TerminateThread((HANDLE)thread_handle, 0) ? EB_ErrorDestroyThreadFailed : EB_ErrorNone;
163 : #else
164 110 : error_return = pthread_cancel(*((pthread_t*)thread_handle)) ? EB_ErrorDestroyThreadFailed : EB_ErrorNone;
165 110 : pthread_join(*((pthread_t*)thread_handle), NULL);
166 110 : free(thread_handle);
167 : #endif // _WIN32
168 :
169 110 : return error_return;
170 : }
171 : #if defined(__APPLE__)
172 : static int32_t semaphore_id(void)
173 : {
174 : static unsigned id = 0;
175 : return id++;
176 : }
177 : #endif
178 :
179 : /***************************************
180 : * eb_create_semaphore
181 : ***************************************/
182 528 : EbHandle eb_create_semaphore(uint32_t initial_count, uint32_t max_count)
183 : {
184 : #ifdef _WIN32
185 : EbHandle semaphore_handle = NULL;
186 : (void)max_count;
187 :
188 : semaphore_handle = (EbHandle)CreateSemaphore(
189 : NULL, // default security attributes
190 : initial_count, // initial semaphore count
191 : max_count, // maximum semaphore count
192 : NULL); // semaphore is not named
193 : return semaphore_handle;
194 :
195 : #elif defined(__APPLE__)
196 : UNUSED(max_count);
197 : char name[15];
198 : sprintf(name, "/sem_%05d_%03d", getpid(), semaphore_id());
199 : sem_t *s = sem_open(name, O_CREAT | O_EXCL, 0644, initial_count);
200 : if (s == SEM_FAILED) {
201 : fprintf(stderr, "errno: %d\n", errno);
202 : return NULL;
203 : }
204 : sem_unlink(name);
205 : return s;
206 : #else
207 528 : EbHandle semaphore_handle = NULL;
208 : (void)max_count;
209 :
210 528 : semaphore_handle = (sem_t*)malloc(sizeof(sem_t));
211 528 : sem_init(
212 : (sem_t*)semaphore_handle, // semaphore handle
213 : 0, // shared semaphore (not local)
214 : initial_count); // initial count
215 528 : return semaphore_handle;
216 :
217 : #endif // _WIN32
218 : }
219 :
220 : /***************************************
221 : * eb_post_semaphore
222 : ***************************************/
223 52258 : EbErrorType eb_post_semaphore(
224 : EbHandle semaphore_handle)
225 : {
226 52258 : EbErrorType return_error = EB_ErrorNone;
227 :
228 : #ifdef _WIN32
229 : return_error = !ReleaseSemaphore(
230 : semaphore_handle, // semaphore handle
231 : 1, // amount to increment the semaphore
232 : NULL) // pointer to previous count (optional)
233 : ? EB_ErrorSemaphoreUnresponsive : EB_ErrorNone;
234 : #else
235 52258 : return_error = sem_post((sem_t*)semaphore_handle) ? EB_ErrorSemaphoreUnresponsive : EB_ErrorNone;
236 : #endif // _WIN32
237 :
238 52273 : return return_error;
239 : }
240 :
241 : /***************************************
242 : * eb_block_on_semaphore
243 : ***************************************/
244 52369 : EbErrorType eb_block_on_semaphore(
245 : EbHandle semaphore_handle)
246 : {
247 52369 : EbErrorType return_error = EB_ErrorNone;
248 :
249 : #ifdef _WIN32
250 : return_error = WaitForSingleObject((HANDLE)semaphore_handle, INFINITE) ? EB_ErrorSemaphoreUnresponsive : EB_ErrorNone;
251 : #else
252 52369 : return_error = sem_wait((sem_t*)semaphore_handle) ? EB_ErrorSemaphoreUnresponsive : EB_ErrorNone;
253 : #endif // _WIN32
254 :
255 52205 : return return_error;
256 : }
257 :
258 : /***************************************
259 : * eb_destroy_semaphore
260 : ***************************************/
261 528 : EbErrorType eb_destroy_semaphore(EbHandle semaphore_handle)
262 : {
263 528 : EbErrorType return_error = EB_ErrorNone;
264 :
265 : #ifdef _WIN32
266 : return_error = !CloseHandle((HANDLE)semaphore_handle) ? EB_ErrorDestroySemaphoreFailed : EB_ErrorNone;
267 : #elif defined(__APPLE__)
268 : return_error = sem_close(semaphore_handle);
269 : #else
270 528 : return_error = sem_destroy((sem_t*)semaphore_handle) ? EB_ErrorDestroySemaphoreFailed : EB_ErrorNone;
271 528 : free(semaphore_handle);
272 : #endif // _WIN32
273 :
274 528 : return return_error;
275 : }
276 : /***************************************
277 : * eb_create_mutex
278 : ***************************************/
279 1086 : EbHandle eb_create_mutex(
280 : void)
281 : {
282 1086 : EbHandle mutex_handle = NULL;
283 :
284 : #ifdef _WIN32
285 : mutex_handle = (EbHandle)CreateMutex(
286 : NULL, // default security attributes
287 : FALSE, // FALSE := not initially owned
288 : NULL); // mutex is not named
289 :
290 : #else
291 :
292 1086 : mutex_handle = (EbHandle)malloc(sizeof(pthread_mutex_t));
293 :
294 1086 : if (mutex_handle != NULL) {
295 1086 : pthread_mutex_init(
296 : (pthread_mutex_t*)mutex_handle,
297 : NULL); // default attributes
298 : }
299 : #endif // _WIN32
300 :
301 1086 : return mutex_handle;
302 : }
303 :
304 : /***************************************
305 : * EbPostMutex
306 : ***************************************/
307 1011280 : EbErrorType eb_release_mutex(
308 : EbHandle mutex_handle)
309 : {
310 1011280 : EbErrorType return_error = EB_ErrorNone;
311 :
312 : #ifdef _WIN32
313 : return_error = !ReleaseMutex((HANDLE)mutex_handle) ? EB_ErrorCreateMutexFailed : EB_ErrorNone;
314 : #else
315 1011280 : return_error = pthread_mutex_unlock((pthread_mutex_t*)mutex_handle) ? EB_ErrorCreateMutexFailed : EB_ErrorNone;
316 : #endif // _WIN32
317 :
318 1012070 : return return_error;
319 : }
320 :
321 : /***************************************
322 : * eb_block_on_mutex
323 : ***************************************/
324 1010980 : EbErrorType eb_block_on_mutex(
325 : EbHandle mutex_handle)
326 : {
327 1010980 : EbErrorType return_error = EB_ErrorNone;
328 :
329 : #ifdef _WIN32
330 : return_error = WaitForSingleObject((HANDLE)mutex_handle, INFINITE) ? EB_ErrorMutexUnresponsive : EB_ErrorNone;
331 : #else
332 1010980 : return_error = pthread_mutex_lock((pthread_mutex_t*)mutex_handle) ? EB_ErrorMutexUnresponsive : EB_ErrorNone;
333 : #endif // _WIN32
334 :
335 1011880 : return return_error;
336 : }
337 :
338 : /***************************************
339 : * eb_block_on_mutex_timeout
340 : ***************************************/
341 0 : EbErrorType eb_block_on_mutex_timeout(
342 : EbHandle mutex_handle,
343 : uint32_t timeout)
344 : {
345 0 : EbErrorType return_error = EB_ErrorNone;
346 :
347 : #ifdef _WIN32
348 : WaitForSingleObject((HANDLE)mutex_handle, timeout);
349 : #else
350 0 : return_error = pthread_mutex_lock((pthread_mutex_t*)mutex_handle) ? EB_ErrorMutexUnresponsive : EB_ErrorNone;
351 : (void)timeout;
352 : #endif // _WIN32
353 :
354 0 : return return_error;
355 : }
356 :
357 : /***************************************
358 : * eb_destroy_mutex
359 : ***************************************/
360 1084 : EbErrorType eb_destroy_mutex(
361 : EbHandle mutex_handle)
362 : {
363 1084 : EbErrorType return_error = EB_ErrorNone;
364 :
365 : #ifdef _WIN32
366 : return_error = CloseHandle((HANDLE)mutex_handle) ? EB_ErrorDestroyMutexFailed : EB_ErrorNone;
367 : #else
368 1084 : return_error = pthread_mutex_destroy((pthread_mutex_t*)mutex_handle) ? EB_ErrorDestroyMutexFailed : EB_ErrorNone;
369 1084 : free(mutex_handle);
370 : #endif // _WIN32
371 :
372 1084 : return return_error;
373 : }
|