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 __linux__ 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> 35void 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 ****************************************/ 48EbHandle 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 __linux__ 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 ****************************************/ 110EbErrorType 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 __linux__ 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 ****************************************/ 139EbErrorType 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 __linux__ 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 ****************************************/ 157EbErrorType 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 __linux__ 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 ***************************************/ 176EbHandle 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 __linux__ 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 ***************************************/ 203EbErrorType 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 __linux__ 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 ***************************************/ 224EbErrorType 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 __linux__ 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 ***************************************/ 241EbErrorType 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 __linux__ 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 ***************************************/ 258EbHandle 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 __linux__ 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 ***************************************/ 285EbErrorType 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 __linux__ 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 ***************************************/ 302EbErrorType 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 __linux__ 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 ***************************************/ 319EbErrorType 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 __linux__ 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 ***************************************/ 338EbErrorType 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 __linux__ 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