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 67 UWORD32 ithread_get_handle_size(void) 68 { 69 return (sizeof(HANDLE)); 70 } 71 72 UWORD32 ithread_get_mutex_lock_size(void) 73 { 74 return (sizeof(HANDLE)); 75 } 76 77 WORD32 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 98 WORD32 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 117 void 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 137 WORD32 ithread_get_mutex_struct_size(void) 138 { 139 return (sizeof(HANDLE)); 140 } 141 142 WORD32 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 156 WORD32 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 170 WORD32 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 190 WORD32 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 209 void ithread_yield(void) { } 210 211 void ithread_usleep(UWORD32 u4_time_us) 212 { 213 UWORD32 u4_time_ms = u4_time_us / 1000; 214 Sleep(u4_time_ms); 215 } 216 217 void ithread_msleep(UWORD32 u4_time_ms) 218 { 219 Sleep(u4_time_ms); 220 } 221 222 223 void ithread_sleep(UWORD32 u4_time) 224 { 225 UWORD32 u4_time_ms = u4_time * 1000; 226 Sleep(u4_time_ms); 227 } 228 229 UWORD32 ithread_get_sem_struct_size(void) 230 { 231 return (sizeof(HANDLE)); 232 } 233 234 WORD32 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 250 WORD32 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 267 WORD32 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 292 WORD32 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 309 WORD32 ithread_set_affinity(WORD32 core_id) 310 { 311 return 1; 312 } 313 314 #else 315 UWORD32 ithread_get_handle_size(void) 316 { 317 return sizeof(pthread_t); 318 } 319 320 UWORD32 ithread_get_mutex_lock_size(void) 321 { 322 return sizeof(pthread_mutex_t); 323 } 324 325 326 WORD32 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 331 WORD32 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 337 void ithread_exit(void *val_ptr) 338 { 339 return pthread_exit(val_ptr); 340 } 341 342 WORD32 ithread_get_mutex_struct_size(void) 343 { 344 return (sizeof(pthread_mutex_t)); 345 } 346 WORD32 ithread_mutex_init(void *mutex) 347 { 348 return pthread_mutex_init((pthread_mutex_t *)mutex, NULL); 349 } 350 351 WORD32 ithread_mutex_destroy(void *mutex) 352 { 353 return pthread_mutex_destroy((pthread_mutex_t *)mutex); 354 } 355 356 WORD32 ithread_mutex_lock(void *mutex) 357 { 358 return pthread_mutex_lock((pthread_mutex_t *)mutex); 359 } 360 361 WORD32 ithread_mutex_unlock(void *mutex) 362 { 363 return pthread_mutex_unlock((pthread_mutex_t *)mutex); 364 } 365 366 void ithread_yield(void) 367 { 368 sched_yield(); 369 } 370 371 void ithread_sleep(UWORD32 u4_time) 372 { 373 usleep(u4_time * 1000 * 1000); 374 } 375 376 void ithread_msleep(UWORD32 u4_time_ms) 377 { 378 usleep(u4_time_ms * 1000); 379 } 380 381 void ithread_usleep(UWORD32 u4_time_us) 382 { 383 usleep(u4_time_us); 384 } 385 386 UWORD32 ithread_get_sem_struct_size(void) 387 { 388 return (sizeof(sem_t)); 389 } 390 391 392 WORD32 ithread_sem_init(void *sem, WORD32 pshared, UWORD32 value) 393 { 394 return sem_init((sem_t *)sem, pshared, value); 395 } 396 397 WORD32 ithread_sem_post(void *sem) 398 { 399 return sem_post((sem_t *)sem); 400 } 401 402 403 WORD32 ithread_sem_wait(void *sem) 404 { 405 return sem_wait((sem_t *)sem); 406 } 407 408 409 WORD32 ithread_sem_destroy(void *sem) 410 { 411 return sem_destroy((sem_t *)sem); 412 } 413 414 415 WORD32 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