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