ithread.c revision a2b49e5f0574dee76f81507f288143d83a4b7c1a
1/****************************************************************************** 2 * 3 * Copyright (C) 2015 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ***************************************************************************** 18 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore 19*/ 20/*****************************************************************************/ 21/* */ 22/* File Name : ithread.c */ 23/* */ 24/* Description : Contains abstraction for threads, mutex and semaphores*/ 25/* */ 26/* List of Functions : */ 27/* */ 28/* Issues / Problems : None */ 29/* */ 30/* Revision History : */ 31/* */ 32/* DD MM YYYY Author(s) Changes */ 33/* 07 09 2012 Harish Initial Version */ 34/*****************************************************************************/ 35/*****************************************************************************/ 36/* File Includes */ 37/*****************************************************************************/ 38#include <string.h> 39#include "ih264_typedefs.h" 40 41/* 42 * If the end target is bare metal, then there shall be no OS. 43 * In this case, the functions ithread_* used inside the h264 encoder library to assist multicore 44 * will not longer be functional. To resolve link issues, the functions are re-defined with no body. 45 */ 46#ifndef BAREMETAL 47 48 49#include "ithread.h" 50#include <sys/types.h> 51 52 53#define UNUSED(x) ((void)(x)) 54 55#ifndef X86_MSVC 56//#define PTHREAD_AFFINITY 57//#define SYSCALL_AFFINITY 58 59#ifdef PTHREAD_AFFINITY 60#define _GNU_SOURCE 61#define __USE_GNU 62#endif 63 64#include <pthread.h> 65#include <sched.h> 66#include <semaphore.h> 67#include <unistd.h> 68#ifdef PTHREAD_AFFINITY 69#include <sys/prctl.h> 70#endif 71 72#endif 73 74#ifdef X86_MSVC 75 76#include <windows.h> 77#define SEM_MAX_COUNT 100 78#define SEM_INCREMENT_COUNT 1 79 80UWORD32 ithread_get_handle_size(void) 81{ 82 return (sizeof(HANDLE)); 83} 84 85UWORD32 ithread_get_mutex_lock_size(void) 86{ 87 return (sizeof(HANDLE)); 88} 89 90WORD32 ithread_create(void *thread_handle, void *attribute, void *strt, void *argument) 91{ 92 HANDLE *ppv_thread_handle; 93 HANDLE thread_handle_value; 94 95 UNUSED(attribute); 96 97 if(0 == thread_handle) 98 return -1; 99 100 ppv_thread_handle = (HANDLE *)thread_handle; 101 thread_handle_value = (void *)CreateThread 102 (NULL, /* Attributes */ 103 1024*128, /* Stack i4_size */ 104 (LPTHREAD_START_ROUTINE)strt, /* Thread function */ 105 argument, /* Parameters */ 106 0, /* Creation flags */ 107 NULL); /* Thread ID */ 108 *ppv_thread_handle = (HANDLE)thread_handle_value; 109 110 return 0; 111} 112 113WORD32 ithread_join(void *thread_handle, void ** val_ptr) 114{ 115 HANDLE *ppv_thread_handle; 116 HANDLE thread_handle_value; 117 118 UNUSED(val_ptr); 119 120 if(0 == thread_handle) 121 return -1; 122 123 ppv_thread_handle = (HANDLE *)thread_handle; 124 thread_handle_value = *ppv_thread_handle; 125 126 if(WAIT_OBJECT_0 == WaitForSingleObject(thread_handle_value, INFINITE)) 127 { 128 CloseHandle(thread_handle_value); 129 } 130 131 return 0; 132} 133 134void ithread_exit(void *thread_handle) 135{ 136 HANDLE *ppv_thread_handle; 137 HANDLE thread_handle_value; 138 DWORD thread_exit_code; 139 140 if(0 == thread_handle) 141 return; 142 143 ppv_thread_handle = (HANDLE *)thread_handle; 144 thread_handle_value = *ppv_thread_handle; 145 /* Get exit code for thread. If the return value is 0, means thread is busy */ 146 if( 0 != GetExitCodeThread(thread_handle_value, &thread_exit_code)) 147 { 148 TerminateThread(thread_handle_value, thread_exit_code); 149 } 150 151 return; 152} 153 154WORD32 ithread_get_mutex_struct_size(void) 155{ 156 return (sizeof(HANDLE)); 157} 158 159WORD32 ithread_mutex_init(void *mutex) 160{ 161 HANDLE *ppv_mutex_handle; 162 HANDLE mutex_handle_value; 163 164 if(0 == mutex) 165 return -1; 166 167 ppv_mutex_handle = (HANDLE *)mutex; 168 mutex_handle_value = CreateSemaphore(NULL, 1, 1, NULL); 169 *ppv_mutex_handle = mutex_handle_value; 170 return 0; 171} 172 173WORD32 ithread_mutex_destroy(void *mutex) 174{ 175 HANDLE *ppv_mutex_handle; 176 HANDLE mutex_handle_value; 177 178 if(0 == mutex) 179 return -1; 180 181 ppv_mutex_handle = (HANDLE *)mutex; 182 mutex_handle_value = *ppv_mutex_handle; 183 CloseHandle(mutex_handle_value); 184 return 0; 185} 186 187WORD32 ithread_mutex_lock(void *mutex) 188{ 189 HANDLE *ppv_mutex_handle; 190 HANDLE mutex_handle_value; 191 DWORD result = 0; 192 193 if(0 == mutex) 194 return -1; 195 196 ppv_mutex_handle = (HANDLE *)mutex; 197 mutex_handle_value = *ppv_mutex_handle; 198 result = WaitForSingleObject(mutex_handle_value, INFINITE); 199 200 if(WAIT_OBJECT_0 == result) 201 return 0; 202 203 return 1; 204 205} 206 207WORD32 ithread_mutex_unlock(void *mutex) 208{ 209 HANDLE *ppv_mutex_handle; 210 HANDLE mutex_handle_value; 211 DWORD result = 0; 212 213 if(0 == mutex) 214 return -1; 215 216 ppv_mutex_handle = (HANDLE *)mutex; 217 mutex_handle_value = *ppv_mutex_handle; 218 result = ReleaseSemaphore(mutex_handle_value, 1, NULL); 219 220 if(0 == result) 221 return -1; 222 223 return 0; 224} 225 226void ithread_yield(void) { } 227 228void ithread_usleep(UWORD32 u4_time_us) 229{ 230 UWORD32 u4_time_ms = u4_time_us / 1000; 231 Sleep(u4_time_ms); 232} 233 234void ithread_msleep(UWORD32 u4_time_ms) 235{ 236 Sleep(u4_time_ms); 237} 238 239void ithread_sleep(UWORD32 u4_time) 240{ 241 UWORD32 u4_time_ms = u4_time * 1000; 242 Sleep(u4_time_ms); 243} 244 245UWORD32 ithread_get_sem_struct_size(void) 246{ 247 return (sizeof(HANDLE)); 248} 249 250WORD32 ithread_sem_init(void *sem,WORD32 pshared,UWORD32 value) 251{ 252 HANDLE *sem_handle = (HANDLE *)sem; 253 HANDLE sem_handle_value; 254 255 if(0 == sem) 256 return -1; 257 258 sem_handle_value = CreateSemaphore(NULL, /* Security Attribute*/ 259 value, /* Initial count */ 260 SEM_MAX_COUNT,/* Max value */ 261 NULL); /* Name, not used */ 262 *sem_handle = sem_handle_value; 263 return 0; 264} 265 266WORD32 ithread_sem_post(void *sem) 267{ 268 HANDLE *sem_handle = (HANDLE *)sem; 269 HANDLE sem_handle_value; 270 271 if(0 == sem) 272 return -1; 273 274 sem_handle_value = *sem_handle; 275 276 /* Post on Semaphore by releasing the lock on mutex */ 277 if(ReleaseSemaphore(sem_handle_value, SEM_INCREMENT_COUNT, NULL)) 278 return 0; 279 280 return -1; 281} 282 283WORD32 ithread_sem_wait(void *sem) 284{ 285 DWORD result = 0; 286 HANDLE *sem_handle = (HANDLE *)sem; 287 HANDLE sem_handle_value; 288 289 if(0 == sem) 290 return -1; 291 292 sem_handle_value = *sem_handle; 293 294 /* Wait on Semaphore object infinitly */ 295 result = WaitForSingleObject(sem_handle_value, INFINITE); 296 297 /* If lock on semaphore is acquired, return SUCCESS */ 298 if(WAIT_OBJECT_0 == result) 299 return 0; 300 301 /* If call timeouts, return FAILURE */ 302 if(WAIT_TIMEOUT == result) 303 return -1; 304 305 return 0; 306} 307 308WORD32 ithread_sem_destroy(void *sem) 309{ 310 HANDLE *sem_handle = (HANDLE *)sem; 311 HANDLE sem_handle_value; 312 313 if(0 == sem) 314 return -1; 315 316 sem_handle_value = *sem_handle; 317 318 if(FALSE == CloseHandle(sem_handle_value) ) 319 { 320 return -1; 321 } 322 return 0; 323} 324 325WORD32 ithread_set_affinity(WORD32 core_id) 326{ 327 return 1; 328} 329 330#else 331 332UWORD32 ithread_get_handle_size(void) 333{ 334 return sizeof(pthread_t); 335} 336 337UWORD32 ithread_get_mutex_lock_size(void) 338{ 339 return sizeof(pthread_mutex_t); 340} 341 342 343WORD32 ithread_create(void *thread_handle, void *attribute, void *strt, void *argument) 344{ 345 UNUSED(attribute); 346 return pthread_create((pthread_t *)thread_handle, NULL,(void *(*)(void *)) strt, argument); 347} 348 349WORD32 ithread_join(void *thread_handle, void ** val_ptr) 350{ 351 UNUSED(val_ptr); 352 pthread_t *pthread_handle = (pthread_t *)thread_handle; 353 return pthread_join(*pthread_handle, NULL); 354} 355 356void ithread_exit(void *val_ptr) 357{ 358 return pthread_exit(val_ptr); 359} 360 361WORD32 ithread_get_mutex_struct_size(void) 362{ 363 return(sizeof(pthread_mutex_t)); 364} 365WORD32 ithread_mutex_init(void *mutex) 366{ 367 return pthread_mutex_init((pthread_mutex_t *) mutex, NULL); 368} 369 370WORD32 ithread_mutex_destroy(void *mutex) 371{ 372 return pthread_mutex_destroy((pthread_mutex_t *) mutex); 373} 374 375WORD32 ithread_mutex_lock(void *mutex) 376{ 377 return pthread_mutex_lock((pthread_mutex_t *)mutex); 378} 379 380WORD32 ithread_mutex_unlock(void *mutex) 381{ 382 return pthread_mutex_unlock((pthread_mutex_t *)mutex); 383} 384 385void ithread_yield(void) 386{ 387 sched_yield(); 388} 389 390void ithread_sleep(UWORD32 u4_time) 391{ 392 usleep(u4_time * 1000 * 1000); 393} 394 395void ithread_msleep(UWORD32 u4_time_ms) 396{ 397 usleep(u4_time_ms * 1000); 398} 399 400void ithread_usleep(UWORD32 u4_time_us) 401{ 402 usleep(u4_time_us); 403} 404 405UWORD32 ithread_get_sem_struct_size(void) 406{ 407 return(sizeof(sem_t)); 408} 409 410 411WORD32 ithread_sem_init(void *sem,WORD32 pshared,UWORD32 value) 412{ 413 return sem_init((sem_t *)sem,pshared,value); 414} 415 416WORD32 ithread_sem_post(void *sem) 417{ 418 return sem_post((sem_t *)sem); 419} 420 421 422WORD32 ithread_sem_wait(void *sem) 423{ 424 return sem_wait((sem_t *)sem); 425} 426 427 428WORD32 ithread_sem_destroy(void *sem) 429{ 430 return sem_destroy((sem_t *)sem); 431} 432 433void ithread_set_name(CHAR *pc_thread_name) 434{ 435 436#ifndef WIN32 437#ifndef QNX 438#ifndef IOS 439 UNUSED(pc_thread_name); 440//prctl(PR_SET_NAME, (unsigned long)pu1_thread_name, 0, 0, 0); 441#endif 442#endif 443#endif 444 445} 446WORD32 ithread_set_affinity(WORD32 core_id) 447{ 448#ifdef PTHREAD_AFFINITY 449 cpu_set_t cpuset; 450 int num_cores = sysconf(_SC_NPROCESSORS_ONLN); 451 pthread_t cur_thread = pthread_self(); 452 453 if (core_id >= num_cores) 454 return -1; 455 456 CPU_ZERO(&cpuset); 457 CPU_SET(core_id, &cpuset); 458 459 return pthread_setaffinity_np(cur_thread, sizeof(cpu_set_t), &cpuset); 460 461#elif SYSCALL_AFFINITY 462 WORD32 i4_sys_res; 463 UNUSED(core_id); 464 465 pid_t pid = gettid(); 466 467 468 i4_sys_res = syscall(__NR_sched_setaffinity, pid, sizeof(i4_mask), &i4_mask); 469 if (i4_sys_res) 470 { 471 //WORD32 err; 472 //err = errno; 473 //perror("Error in setaffinity syscall PERROR : "); 474 //LOG_ERROR("Error in the syscall setaffinity: mask=0x%x err=0x%x", i4_mask, i4_sys_res); 475 return -1; 476 } 477#else 478 UNUSED(core_id); 479#endif 480 return 1; 481 482} 483#endif 484 485#else 486 487UWORD32 ithread_get_handle_size(void) 488{ 489 return sizeof(int); 490} 491 492UWORD32 ithread_get_mutex_lock_size(void) 493{ 494 return sizeof(int); 495} 496 497UWORD32 ithread_get_cond_size(void) 498{ 499 return(sizeof(int)); 500} 501WORD32 ithread_create(void *thread_handle, void *attribute, void *strt, void *argument) 502{ 503 return 0; 504} 505 506WORD32 ithread_join(void *thread_handle, void ** val_ptr) 507{ 508 return 0; 509} 510 511void ithread_exit(void *val_ptr) 512{ 513 return; 514} 515 516WORD32 ithread_mutex_init(void *mutex) 517{ 518 return 0; 519} 520 521WORD32 ithread_mutex_destroy(void *mutex) 522{ 523 return 0; 524} 525 526WORD32 ithread_mutex_lock(void *mutex) 527{ 528 return 0; 529} 530 531WORD32 ithread_mutex_unlock(void *mutex) 532{ 533 return 0; 534} 535 536void ithread_yield(void) 537{ 538 return; 539} 540 541void ithread_sleep(UWORD32 u4_time_in_us) 542{ 543 return; 544} 545 546void ithread_usleep(UWORD32 u4_time_us) 547{ 548 return; 549} 550 551UWORD32 ithread_get_sem_strcut_size(void) 552{ 553 return(sizeof(int)); 554} 555 556 557WORD32 ithread_sem_init(void *sem,WORD32 pshared,UWORD32 value) 558{ 559 return 0; 560} 561 562WORD32 ithread_sem_post(void *sem) 563{ 564 return 0; 565} 566 567 568WORD32 ithread_sem_wait(void *sem) 569{ 570 return 0; 571} 572 573WORD32 ithread_sem_destroy(void *sem) 574{ 575 return 0; 576} 577 578void ithread_set_name(UWORD8 *pu1_thread_name) 579{ 580 return; 581} 582 583void ithread_condition_init(void *condition) 584{ 585 return; 586} 587 588void ithread_condition_signal(void * condition) 589{ 590 return; 591} 592 593 594 595void ithread_condition_wait(void *condition,void *mutex) 596{ 597 return; 598} 599 600WORD32 ithread_set_affinity(WORD32 core_id) 601{ 602 return 1; 603} 604#endif 605