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