1/****************************************************************************** 2* 3* Copyright (C) 2012 Ittiam Systems Pvt Ltd, Bangalore 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/*****************************************************************************/ 19/* */ 20/* File Name : ithread.c */ 21/* */ 22/* Description : Contains abstraction for threads, mutex and semaphores*/ 23/* */ 24/* List of Functions : */ 25/* */ 26/* Issues / Problems : None */ 27/* */ 28/* Revision History : */ 29/* */ 30/* DD MM YYYY Author(s) Changes */ 31/* 07 09 2012 Harish Initial Version */ 32/*****************************************************************************/ 33/*****************************************************************************/ 34/* File Includes */ 35/*****************************************************************************/ 36#include <string.h> 37#include "ihevc_typedefs.h" 38#include "ithread.h" 39#include <sys/types.h> 40 41#ifndef X86_MSVC 42//#define PTHREAD_AFFINITY 43//#define SYSCALL_AFFINITY 44 45#ifdef PTHREAD_AFFINITY 46#define _GNU_SOURCE 47#define __USE_GNU 48#endif 49 50#include <pthread.h> 51#include <sched.h> 52#include <semaphore.h> 53#include <unistd.h> 54 55 56#endif 57 58 59 60 61#ifdef X86_MSVC 62 63#include <windows.h> 64#define SEM_MAX_COUNT 100 65#define SEM_INCREMENT_COUNT 1 66 67UWORD32 ithread_get_handle_size(void) 68{ 69 return (sizeof(HANDLE)); 70} 71 72UWORD32 ithread_get_mutex_lock_size(void) 73{ 74 return (sizeof(HANDLE)); 75} 76 77WORD32 ithread_create(void *thread_handle, void *attribute, void *strt, void *argument) 78{ 79 HANDLE *ppv_thread_handle; 80 HANDLE thread_handle_value; 81 82 if(0 == thread_handle) 83 return -1; 84 85 ppv_thread_handle = (HANDLE *)thread_handle; 86 thread_handle_value = (void *)CreateThread 87 (NULL, /* Attributes */ 88 1024 * 128, /* Stack size */ 89 (LPTHREAD_START_ROUTINE)strt, /* Thread function */ 90 argument, /* Parameters */ 91 0, /* Creation flags */ 92 NULL); /* Thread ID */ 93 *ppv_thread_handle = (HANDLE)thread_handle_value; 94 95 return 0; 96} 97 98WORD32 ithread_join(void *thread_handle, void **val_ptr) 99{ 100 HANDLE *ppv_thread_handle; 101 HANDLE thread_handle_value; 102 103 if(0 == thread_handle) 104 return -1; 105 106 ppv_thread_handle = (HANDLE *)thread_handle; 107 thread_handle_value = *ppv_thread_handle; 108 109 if(WAIT_OBJECT_0 == WaitForSingleObject(thread_handle_value, INFINITE)) 110 { 111 CloseHandle(thread_handle_value); 112 } 113 114 return 0; 115} 116 117void ithread_exit(void *thread_handle) 118{ 119 HANDLE *ppv_thread_handle; 120 HANDLE thread_handle_value; 121 DWORD thread_exit_code; 122 123 if(0 == thread_handle) 124 return; 125 126 ppv_thread_handle = (HANDLE *)thread_handle; 127 thread_handle_value = *ppv_thread_handle; 128 /* Get exit code for thread. If the return value is 0, means thread is busy */ 129 if(0 != GetExitCodeThread(thread_handle_value, &thread_exit_code)) 130 { 131 TerminateThread(thread_handle_value, thread_exit_code); 132 } 133 134 return; 135} 136 137WORD32 ithread_get_mutex_struct_size(void) 138{ 139 return (sizeof(HANDLE)); 140} 141 142WORD32 ithread_mutex_init(void *mutex) 143{ 144 HANDLE *ppv_mutex_handle; 145 HANDLE mutex_handle_value; 146 147 if(0 == mutex) 148 return -1; 149 150 ppv_mutex_handle = (HANDLE *)mutex; 151 mutex_handle_value = CreateSemaphore(NULL, 1, 1, NULL); 152 *ppv_mutex_handle = mutex_handle_value; 153 return 0; 154} 155 156WORD32 ithread_mutex_destroy(void *mutex) 157{ 158 HANDLE *ppv_mutex_handle; 159 HANDLE mutex_handle_value; 160 161 if(0 == mutex) 162 return -1; 163 164 ppv_mutex_handle = (HANDLE *)mutex; 165 mutex_handle_value = *ppv_mutex_handle; 166 CloseHandle(mutex_handle_value); 167 return 0; 168} 169 170WORD32 ithread_mutex_lock(void *mutex) 171{ 172 HANDLE *ppv_mutex_handle; 173 HANDLE mutex_handle_value; 174 DWORD result = 0; 175 176 if(0 == mutex) 177 return -1; 178 179 ppv_mutex_handle = (HANDLE *)mutex; 180 mutex_handle_value = *ppv_mutex_handle; 181 result = WaitForSingleObject(mutex_handle_value, INFINITE); 182 183 if(WAIT_OBJECT_0 == result) 184 return 0; 185 186 return 1; 187 188} 189 190WORD32 ithread_mutex_unlock(void *mutex) 191{ 192 HANDLE *ppv_mutex_handle; 193 HANDLE mutex_handle_value; 194 DWORD result = 0; 195 196 if(0 == mutex) 197 return -1; 198 199 ppv_mutex_handle = (HANDLE *)mutex; 200 mutex_handle_value = *ppv_mutex_handle; 201 result = ReleaseSemaphore(mutex_handle_value, 1, NULL); 202 203 if(0 == result) 204 return -1; 205 206 return 0; 207} 208 209void ithread_yield(void) { } 210 211void ithread_usleep(UWORD32 u4_time_us) 212{ 213 UWORD32 u4_time_ms = u4_time_us / 1000; 214 Sleep(u4_time_ms); 215} 216 217void ithread_msleep(UWORD32 u4_time_ms) 218{ 219 Sleep(u4_time_ms); 220} 221 222 223void ithread_sleep(UWORD32 u4_time) 224{ 225 UWORD32 u4_time_ms = u4_time * 1000; 226 Sleep(u4_time_ms); 227} 228 229UWORD32 ithread_get_sem_struct_size(void) 230{ 231 return (sizeof(HANDLE)); 232} 233 234WORD32 ithread_sem_init(void *sem, WORD32 pshared, UWORD32 value) 235{ 236 HANDLE *sem_handle = (HANDLE *)sem; 237 HANDLE sem_handle_value; 238 239 if(0 == sem) 240 return -1; 241 242 sem_handle_value = CreateSemaphore(NULL, /* Security Attribute*/ 243 value, /* Initial count */ 244 SEM_MAX_COUNT, /* Max value */ 245 NULL); /* Name, not used */ 246 *sem_handle = sem_handle_value; 247 return 0; 248} 249 250WORD32 ithread_sem_post(void *sem) 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 = *sem_handle; 259 260 /* Post on Semaphore by releasing the lock on mutex */ 261 if(ReleaseSemaphore(sem_handle_value, SEM_INCREMENT_COUNT, NULL)) 262 return 0; 263 264 return -1; 265} 266 267WORD32 ithread_sem_wait(void *sem) 268{ 269 DWORD result = 0; 270 HANDLE *sem_handle = (HANDLE *)sem; 271 HANDLE sem_handle_value; 272 273 if(0 == sem) 274 return -1; 275 276 sem_handle_value = *sem_handle; 277 278 /* Wait on Semaphore object infinitly */ 279 result = WaitForSingleObject(sem_handle_value, INFINITE); 280 281 /* If lock on semaphore is acquired, return SUCCESS */ 282 if(WAIT_OBJECT_0 == result) 283 return 0; 284 285 /* If call timeouts, return FAILURE */ 286 if(WAIT_TIMEOUT == result) 287 return -1; 288 289 return 0; 290} 291 292WORD32 ithread_sem_destroy(void *sem) 293{ 294 HANDLE *sem_handle = (HANDLE *)sem; 295 HANDLE sem_handle_value; 296 297 if(0 == sem) 298 return -1; 299 300 sem_handle_value = *sem_handle; 301 302 if(FALSE == CloseHandle(sem_handle_value)) 303 { 304 return -1; 305 } 306 return 0; 307} 308 309WORD32 ithread_set_affinity(WORD32 core_id) 310{ 311 return 1; 312} 313 314#else 315UWORD32 ithread_get_handle_size(void) 316{ 317 return sizeof(pthread_t); 318} 319 320UWORD32 ithread_get_mutex_lock_size(void) 321{ 322 return sizeof(pthread_mutex_t); 323} 324 325 326WORD32 ithread_create(void *thread_handle, void *attribute, void *strt, void *argument) 327{ 328 return pthread_create((pthread_t *)thread_handle, attribute, (void * (*)(void *))strt, argument); 329} 330 331WORD32 ithread_join(void *thread_handle, void **val_ptr) 332{ 333 pthread_t *pthread_handle = (pthread_t *)thread_handle; 334 return pthread_join(*pthread_handle, val_ptr); 335} 336 337void ithread_exit(void *val_ptr) 338{ 339 return pthread_exit(val_ptr); 340} 341 342WORD32 ithread_get_mutex_struct_size(void) 343{ 344 return (sizeof(pthread_mutex_t)); 345} 346WORD32 ithread_mutex_init(void *mutex) 347{ 348 return pthread_mutex_init((pthread_mutex_t *)mutex, NULL); 349} 350 351WORD32 ithread_mutex_destroy(void *mutex) 352{ 353 return pthread_mutex_destroy((pthread_mutex_t *)mutex); 354} 355 356WORD32 ithread_mutex_lock(void *mutex) 357{ 358 return pthread_mutex_lock((pthread_mutex_t *)mutex); 359} 360 361WORD32 ithread_mutex_unlock(void *mutex) 362{ 363 return pthread_mutex_unlock((pthread_mutex_t *)mutex); 364} 365 366void ithread_yield(void) 367{ 368 sched_yield(); 369} 370 371void ithread_sleep(UWORD32 u4_time) 372{ 373 usleep(u4_time * 1000 * 1000); 374} 375 376void ithread_msleep(UWORD32 u4_time_ms) 377{ 378 usleep(u4_time_ms * 1000); 379} 380 381void ithread_usleep(UWORD32 u4_time_us) 382{ 383 usleep(u4_time_us); 384} 385 386UWORD32 ithread_get_sem_struct_size(void) 387{ 388 return (sizeof(sem_t)); 389} 390 391 392WORD32 ithread_sem_init(void *sem, WORD32 pshared, UWORD32 value) 393{ 394 return sem_init((sem_t *)sem, pshared, value); 395} 396 397WORD32 ithread_sem_post(void *sem) 398{ 399 return sem_post((sem_t *)sem); 400} 401 402 403WORD32 ithread_sem_wait(void *sem) 404{ 405 return sem_wait((sem_t *)sem); 406} 407 408 409WORD32 ithread_sem_destroy(void *sem) 410{ 411 return sem_destroy((sem_t *)sem); 412} 413 414 415WORD32 ithread_set_affinity(WORD32 core_id) 416{ 417 418#ifdef PTHREAD_AFFINITY 419 cpu_set_t cpuset; 420 int num_cores = sysconf(_SC_NPROCESSORS_ONLN); 421 pthread_t cur_thread = pthread_self(); 422 423 if(core_id >= num_cores) 424 return -1; 425 426 CPU_ZERO(&cpuset); 427 CPU_SET(core_id, &cpuset); 428 429 return pthread_setaffinity_np(cur_thread, sizeof(cpu_set_t), &cpuset); 430 431#elif SYSCALL_AFFINITY 432 WORD32 i4_sys_res; 433 434 pid_t pid = gettid(); 435 436 437 i4_sys_res = syscall(__NR_sched_setaffinity, pid, sizeof(i4_mask), &i4_mask); 438 if(i4_sys_res) 439 { 440 //WORD32 err; 441 //err = errno; 442 //perror("Error in setaffinity syscall PERROR : "); 443 //LOG_ERROR("Error in the syscall setaffinity: mask=0x%x err=0x%x", i4_mask, i4_sys_res); 444 return -1; 445 } 446#endif 447 448 return core_id; 449 450} 451#endif 452