Home | History | Annotate | Download | only in common
      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