1 /******************************************************************************
2 *
3 * Copyright (C) 2018 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 /* */
23 /* File Name : osal_thread.c */
24 /* */
25 /* Description : This file contains Thread API's implemented for */
26 /* different platforms. */
27 /* */
28 /* List of Functions : osal_thread_create */
29 /* osal_thread_destroy */
30 /* osal_func */
31 /* osal_set_thread_priority */
32 /* osal_set_thread_core_affinity */
33 /* osal_thread_sleep */
34 /* osal_thread_yield */
35 /* osal_thread_suspend */
36 /* osal_thread_resume */
37 /* osal_thread_wait */
38 /* osal_get_thread_handle */
39 /* osal_get_time */
40 /* osal_get_time_usec */
41 /* osal_get_last_error */
42 /* osal_print_last_error */
43 /* */
44 /* Issues / Problems : None */
45 /* */
46 /* Revision History : */
47 /* */
48 /* DD MM YYYY Author(s) Changes (Describe the changes made) */
49 /* 06 03 2006 Ittiam Draft */
50 /* */
51 /*****************************************************************************/
52
53 /*****************************************************************************/
54 /* File Includes */
55 /*****************************************************************************/
56
57 /* System include files */
58 #include <stdio.h>
59
60 #include <semaphore.h>
61 #include <pthread.h>
62 #include <errno.h>
63 #include <sys/time.h>
64 #include <sys/resource.h>
65
66 #include <unistd.h>
67 #include <math.h>
68 #include <sched.h> /*for CPU_SET, etc.. */
69 #include <linux/unistd.h>
70 #include <sys/syscall.h>
71
72 /* User include files */
73 #include "cast_types.h"
74 #include "osal.h"
75 #include "osal_handle.h"
76 #include "osal_thread.h"
77 #include "osal_errno.h"
78
79 /*****************************************************************************/
80 /* Static Function Declarations */
81 /*****************************************************************************/
82
83 static void osal_func(void *param);
84
85 /*****************************************************************************/
86 /* */
87 /* Function Name : osal_thread_create */
88 /* */
89 /* Description : This function create a new thread. */
90 /* */
91 /* Inputs : OSAL handle */
92 /* Memory Manager Handle */
93 /* Thread creation attributes */
94 /* */
95 /* Globals : None */
96 /* */
97 /* Processing : This function calls OS specific thread create API's and */
98 /* creates a new thread with specified attributes. */
99 /* */
100 /* Outputs : Status of thread creation */
101 /* */
102 /* Returns : On SUCCESS - 0 */
103 /* On FAILURE - -1 */
104 /* */
105 /* Issues : Only supports creating threads with default attributes */
106 /* */
107 /* Revision History: */
108 /* */
109 /* DD MM YYYY Author(s) Changes (Describe the changes made) */
110 /* 06 03 2006 Ittiam Draft */
111 /* */
112 /*****************************************************************************/
113
osal_thread_create(IN void * osal_handle,IN osal_thread_attr_t * attr)114 void *osal_thread_create(IN void *osal_handle, IN osal_thread_attr_t *attr)
115 {
116 osal_t *handle = (osal_t *)osal_handle;
117 WORD32 priority = 0;
118 void *mmr_handle = 0;
119
120 /* If Handle or attributes are not valid, return ERRORED. */
121 if(0 == attr)
122 return 0;
123
124 if(0 == handle || 0 == handle->alloc || 0 == handle->free)
125 return 0;
126
127 /* Initialize MMR handle */
128 mmr_handle = handle->mmr_handle;
129
130 {
131 pthread_attr_t tattr;
132 thread_handle_t *hdl = 0;
133
134 attr->sched_policy = OSAL_SCHED_RR;
135
136 /* Allocate memory for thread handle */
137 hdl = handle->alloc(mmr_handle, sizeof(thread_handle_t));
138 if(0 == hdl)
139 return 0;
140
141 /* Initialize thread handle parameters */
142 hdl->mmr_handle = mmr_handle;
143 hdl->hdl = handle;
144 hdl->exit_code = attr->exit_code;
145 hdl->priority = priority;
146 hdl->thread_func = attr->thread_func;
147 hdl->thread_param = attr->thread_param;
148
149 /* initialized with default attributes */
150 if(0 != pthread_attr_init(&tattr))
151 {
152 handle->free(hdl->mmr_handle, hdl);
153 return 0;
154 }
155
156 /* Create the thread */
157 hdl->thread_id = pthread_create(
158 &(hdl->thread_handle), /* Thread Handle */
159 &tattr, /* Attributes */
160 (void *(*)(void *))osal_func,
161 hdl); /* Parameters */
162
163 /* In case of error in thread creationn, Free the handle memory and */
164 /* return error. */
165 if(0 != hdl->thread_id)
166 {
167 handle->free(hdl->mmr_handle, hdl);
168 return 0;
169 }
170
171 pthread_attr_destroy(&tattr);
172
173 return hdl;
174 }
175 }
176
177 /*****************************************************************************/
178 /* */
179 /* Function Name : osal_thread_destroy */
180 /* */
181 /* Description : This function calls OS specific API's to close a thread */
182 /* which is represented by specified handle. */
183 /* */
184 /* Inputs : Initialized thread handle */
185 /* */
186 /* Globals : None */
187 /* */
188 /* Processing : Closing other threads is supported only in windows. So, */
189 /* only windows platform supports this API. */
190 /* */
191 /* Outputs : Status of thread close */
192 /* */
193 /* Returns : On SUCCESS - 0 */
194 /* On FAILURE - -1 */
195 /* */
196 /* Issues : None */
197 /* */
198 /* Revision History: */
199 /* */
200 /* DD MM YYYY Author(s) Changes (Describe the changes made) */
201 /* 06 03 2006 Ittiam Draft */
202 /* */
203 /*****************************************************************************/
204
osal_thread_destroy(IN void * thread_handle)205 WORD32 osal_thread_destroy(IN void *thread_handle)
206 {
207 /* If thread handle is not valid, return error */
208 if(0 == thread_handle)
209 return OSAL_ERROR;
210
211 {
212 thread_handle_t *hdl = (thread_handle_t *)thread_handle;
213
214 /* Free memory allocated for Thread handle */
215 ((osal_t *)hdl->hdl)->free(hdl->mmr_handle, hdl);
216
217 return OSAL_SUCCESS;
218 }
219 }
220
221 /*****************************************************************************/
222 /* */
223 /* Function Name : osal_func */
224 /* */
225 /* Description : This function calls the registered threads calling */
226 /* function */
227 /* */
228 /* Inputs : Thread Handle */
229 /* */
230 /* Globals : None */
231 /* */
232 /* Processing : Calls each registered thread function */
233 /* */
234 /* Outputs : None */
235 /* Returns : None */
236 /* */
237 /* Issues : None */
238 /* */
239 /* Revision History: */
240 /* */
241 /* DD MM YYYY Author(s) Changes (Describe the changes made) */
242 /* 10 05 2006 Ittiam Draft */
243 /* */
244 /*****************************************************************************/
245
osal_func(IN void * param)246 void osal_func(IN void *param)
247 {
248 thread_handle_t *hdl = (thread_handle_t *)param;
249
250 while(1)
251 {
252 /* Untill thread returns exit code, invoke the thread function */
253 if(hdl->exit_code == hdl->thread_func(hdl->thread_param))
254 break;
255 }
256
257 /* On Linux platforms call pthread_exit() to release all the resources */
258 /* allocated. */
259 pthread_exit(NULL);
260 }
261
262 /*****************************************************************************/
263 /* */
264 /* Function Name : osal_thread_sleep */
265 /* */
266 /* Description : This function calls OS specific API and makes thread */
267 /* sleep for specified number of milli seconds. */
268 /* */
269 /* Inputs : Initialized thread handle */
270 /* Time to sleep in millisceonds */
271 /* */
272 /* Globals : None */
273 /* */
274 /* Processing : Calls API to sleep for specified number of milli seconds */
275 /* */
276 /* Outputs : Status of sleep */
277 /* */
278 /* Returns : On SUCCESS - 0 */
279 /* On FAILURE - -1 */
280 /* */
281 /* Issues : None */
282 /* */
283 /* Revision History: */
284 /* */
285 /* DD MM YYYY Author(s) Changes (Describe the changes made) */
286 /* 06 03 2006 Ittiam Draft */
287 /* */
288 /*****************************************************************************/
289
osal_thread_sleep(IN UWORD32 milli_seconds)290 WORD32 osal_thread_sleep(IN UWORD32 milli_seconds)
291 {
292 {
293 struct timespec timer;
294
295 /* Convert time in milliseconds into seconds and nano seconds */
296 timer.tv_sec = milli_seconds / 1000;
297 milli_seconds -= (timer.tv_sec * 1000);
298 timer.tv_nsec = milli_seconds * MEGA_CONST;
299
300 /* Using Monotonic clock to sleep, also flag is set to 0 for relative */
301 /* time to current clock time */
302 if(0 == clock_nanosleep(CLOCK_MONOTONIC, 0, &timer, NULL))
303 {
304 return OSAL_SUCCESS;
305 }
306
307 return OSAL_ERROR;
308 }
309 }
310
311 /*****************************************************************************/
312 /* */
313 /* Function Name : osal_thread_yield */
314 /* */
315 /* Description : This function causes the yield its execution. */
316 /* */
317 /* Inputs : Thread Handle */
318 /* */
319 /* Globals : None */
320 /* */
321 /* Processing : Calls OS specific yield calls. */
322 /* */
323 /* Outputs : Status of Thread Yield */
324 /* */
325 /* Returns : On SUCCESS - 0 */
326 /* On FAILURE - -1 */
327 /* */
328 /* Issues : Yield in WIN32 (whihc is a 16 - bit API) is still present*/
329 /* only to maintian backward compatibility. Can get */
330 /* deprecated in future. */
331 /* */
332 /* Revision History: */
333 /* */
334 /* DD MM YYYY Author(s) Changes (Describe the changes made) */
335 /* 06 03 2006 Ittiam Draft */
336 /* */
337 /*****************************************************************************/
338
osal_thread_yield()339 WORD32 osal_thread_yield()
340 {
341 if(0 == sched_yield())
342 return OSAL_SUCCESS;
343
344 return OSAL_ERROR;
345 }
346
347 /*****************************************************************************/
348 /* */
349 /* Function Name : osal_thread_suspend */
350 /* */
351 /* Description : This function causes the suspension its execution. */
352 /* */
353 /* Inputs : Thread Handle */
354 /* */
355 /* Globals : None */
356 /* */
357 /* Processing : Calls OS specific suspend calls. */
358 /* */
359 /* Outputs : Status of Thread Suspend */
360 /* */
361 /* Returns : On SUCCESS - 0 */
362 /* On FAILURE - -1 */
363 /* */
364 /* Issues : API not supported in Redhat Linux. Refer Redhat */
365 /* documentation in: */
366 /* http://www.redhat.com/docs/wp/solaris_port/c1347.html */
367 /* */
368 /* Revision History: */
369 /* */
370 /* DD MM YYYY Author(s) Changes (Describe the changes made) */
371 /* 30 03 2006 Ittiam Draft */
372 /* */
373 /*****************************************************************************/
374
osal_thread_suspend(IN void * thread_handle)375 WORD32 osal_thread_suspend(IN void *thread_handle)
376 {
377 /* If thread handle is not valid, return error */
378 if(0 == thread_handle)
379 return OSAL_ERROR;
380
381 {
382 /* Thread suspend are not supported in Redhat Linux. Refer link */
383 /* http://www.redhat.com/docs/wp/solaris_port/c1347.html */
384
385 return OSAL_NOT_SUPPORTED;
386 }
387 }
388
389 /*****************************************************************************/
390 /* */
391 /* Function Name : osal_thread_resume */
392 /* */
393 /* Description : This function causes the resumption its execution. */
394 /* */
395 /* Inputs : Thread Handle */
396 /* */
397 /* Globals : None */
398 /* */
399 /* Processing : Calls OS specific resume calls. */
400 /* */
401 /* Outputs : Status of Thread Suspend */
402 /* */
403 /* Returns : On SUCCESS - 0 */
404 /* On FAILURE - -1 */
405 /* */
406 /* Issues : API not supported in Redhat Linux. Refer Redhat */
407 /* documentation in: */
408 /* http://www.redhat.com/docs/wp/solaris_port/c1347.html */
409 /* */
410 /* Revision History: */
411 /* */
412 /* DD MM YYYY Author(s) Changes (Describe the changes made) */
413 /* 30 03 2006 Ittiam Draft */
414 /* */
415 /*****************************************************************************/
416
osal_thread_resume(IN void * thread_handle)417 WORD32 osal_thread_resume(IN void *thread_handle)
418 {
419 /* If thread handle is not valid, return error */
420 if(0 == thread_handle)
421 return OSAL_ERROR;
422
423 {
424 /* Thread suspend are not supported in Redhat Linux. Refer link */
425 /* http://www.redhat.com/docs/wp/solaris_port/c1347.html */
426
427 return OSAL_NOT_SUPPORTED;
428 }
429 }
430
431 /*****************************************************************************/
432 /* */
433 /* Function Name : osal_thread_wait */
434 /* */
435 /* Description : This function causes the wait untill called thread */
436 /* finishes execution */
437 /* */
438 /* Inputs : Thread Handle */
439 /* */
440 /* Globals : None */
441 /* */
442 /* Processing : Calls OS specific wait call for wait on another thread */
443 /* */
444 /* Outputs : Status of Thread wait */
445 /* */
446 /* Returns : On SUCCESS - 0 */
447 /* On FAILURE - -1 */
448 /* */
449 /* Issues : None */
450 /* */
451 /* Revision History: */
452 /* */
453 /* DD MM YYYY Author(s) Changes (Describe the changes made) */
454 /* 30 03 2006 Ittiam Draft */
455 /* */
456 /*****************************************************************************/
457
osal_thread_wait(IN void * thread_handle)458 WORD32 osal_thread_wait(IN void *thread_handle)
459 {
460 if(0 == thread_handle)
461 return OSAL_ERROR;
462
463 {
464 WORD32 result = 0;
465 void *status = 0;
466
467 thread_handle_t *hdl = (thread_handle_t *)thread_handle;
468
469 /* Join the thread to wait for thread to complete execution */
470 result = pthread_join(hdl->thread_handle, (void **)&status);
471
472 return result;
473 }
474 }
475
476 /*****************************************************************************/
477 /* */
478 /* Function Name : osal_get_thread_handle */
479 /* */
480 /* Description : This function gets current thread handle. Currently not */
481 /* supported */
482 /* */
483 /* Inputs : OSAL handle. */
484 /* */
485 /* Globals : None */
486 /* */
487 /* Processing : Gets all the thread properities and constructs a new */
488 /* thread handle . */
489 /* */
490 /* Outputs : Thread handle to current thread. */
491 /* */
492 /* Returns : On SUCCESS - Current thread handle */
493 /* On FAILURE - NULL */
494 /* */
495 /* Issues : Not supported on Linux and BIOS platforms. */
496 /* */
497 /* Revision History: */
498 /* */
499 /* DD MM YYYY Author(s) Changes (Describe the changes made) */
500 /* 10 05 2006 Ittiam Draft */
501 /* */
502 /*****************************************************************************/
503
osal_get_thread_handle(IN void * osal_handle)504 void *osal_get_thread_handle(IN void *osal_handle)
505 {
506 osal_t *handle = (osal_t *)osal_handle;
507
508 if(0 == osal_handle)
509 return 0;
510
511 {
512 thread_handle_t *hdl = handle->alloc(handle->mmr_handle, sizeof(thread_handle_t));
513 WORD32 schedpolicy;
514 struct sched_param schedparam;
515
516 if(0 == hdl)
517 return 0;
518
519 hdl->mmr_handle = handle->mmr_handle;
520 hdl->hdl = handle;
521 hdl->exit_code = 0;
522 hdl->thread_func = 0;
523 hdl->thread_param = 0;
524 hdl->thread_handle = pthread_self();
525 hdl->thread_id = 0;
526 hdl->priority = schedparam.sched_priority;
527
528 /* Get thread priority from scheduling parameters */
529 if(0 != pthread_getschedparam(hdl->thread_handle, &schedpolicy, &schedparam))
530 {
531 return 0;
532 }
533
534 return hdl;
535 }
536 }
537
538 /*****************************************************************************/
539 /* */
540 /* Function Name : osal_get_time */
541 /* */
542 /* Description : This function returns absolute time in milli seconds */
543 /* */
544 /* Inputs : None */
545 /* Globals : None */
546 /* */
547 /* Processing : Gets the absolute time by calling OS specific API's. */
548 /* */
549 /* Outputs : Absolute time in milli seconds. */
550 /* */
551 /* Returns : +ve 32 bit value */
552 /* */
553 /* Issues : None */
554 /* */
555 /* Revision History: */
556 /* */
557 /* DD MM YYYY Author(s) Changes (Describe the changes made) */
558 /* 06 03 2006 Ittiam Draft */
559 /* */
560 /*****************************************************************************/
561
osal_get_time()562 UWORD32 osal_get_time()
563 {
564 {
565 struct timespec time_val;
566 int cur_time;
567
568 /* Get the Monotonic time */
569 clock_gettime(CLOCK_MONOTONIC, &time_val);
570
571 /* Convert time in seconds and micro seconds into milliseconds time */
572 cur_time = time_val.tv_sec * 1000 + time_val.tv_nsec / 1000000;
573 return cur_time;
574 }
575 }
576
577 /*****************************************************************************/
578 /* */
579 /* Function Name : osal_get_time_usec */
580 /* */
581 /* Description : This function returns absolute time in micro seconds */
582 /* */
583 /* Inputs : None */
584 /* Globals : None */
585 /* */
586 /* Processing : Gets the absolute time by calling OS specific API's. */
587 /* */
588 /* Outputs : Absolute time in micro seconds. */
589 /* */
590 /* Returns : +ve 32 bit value */
591 /* */
592 /* Issues : None */
593 /* */
594 /* Revision History: */
595 /* */
596 /* DD MM YYYY Author(s) Changes (Describe the changes made) */
597 /* 06 03 2009 Ittiam Draft */
598 /* */
599 /*****************************************************************************/
600
osal_get_time_usec(UWORD32 * sec,UWORD32 * usec)601 WORD32 osal_get_time_usec(UWORD32 *sec, UWORD32 *usec)
602 {
603 if((0 == sec) || (0 == usec))
604 return OSAL_ERROR;
605
606 {
607 struct timespec time_val;
608
609 /* Get the Monotonic time */
610 clock_gettime(CLOCK_MONOTONIC, &time_val);
611
612 /* Convert time in seconds and micro seconds into milliseconds time */
613 *sec = time_val.tv_sec;
614 *usec = time_val.tv_nsec / 1000;
615
616 return OSAL_SUCCESS;
617 }
618 }
619
620 /*****************************************************************************/
621 /* */
622 /* Function Name : osal_get_last_error */
623 /* */
624 /* Description : This function gets the last error code. */
625 /* */
626 /* Inputs : None */
627 /* Globals : None */
628 /* */
629 /* Processing : Gets the last occured error code by calling OS specific */
630 /* API call. */
631 /* */
632 /* Outputs : Error Number */
633 /* */
634 /* Returns : If no error - 0 */
635 /* Else - +ve number */
636 /* */
637 /* Issues : None */
638 /* */
639 /* Revision History: */
640 /* */
641 /* DD MM YYYY Author(s) Changes (Describe the changes made) */
642 /* 06 03 2006 Ittiam Draft */
643 /* */
644 /*****************************************************************************/
645
osal_get_last_error()646 UWORD32 osal_get_last_error()
647 {
648 UWORD32 get_linux_error(void);
649 return get_linux_error();
650 }
651
652 /*****************************************************************************/
653 /* */
654 /* Function Name : osal_print_last_error */
655 /* */
656 /* Description : This function prints the last error message. */
657 /* */
658 /* Inputs : None */
659 /* Globals : None */
660 /* */
661 /* Processing : Gets the last occured error code by calling OS specific */
662 /* API call. It prints argument string (if not NULL), */
663 /* followed by ': ' then the error_string and <new_line>. */
664 /* */
665 /* Outputs : None */
666 /* */
667 /* Returns : None */
668 /* */
669 /* Issues : None */
670 /* */
671 /* Revision History: */
672 /* */
673 /* DD MM YYYY Author(s) Changes (Describe the changes made) */
674 /* 10 03 2006 Ittiam Draft */
675 /* */
676 /*****************************************************************************/
677
osal_print_last_error(IN const STRWORD8 * string)678 void osal_print_last_error(IN const STRWORD8 *string)
679 {
680 perror(string);
681 }
682
683 /*****************************************************************************/
684 /* */
685 /* Function Name : osal_get_current_tid */
686 /* */
687 /* Description : Gets the tid of the thread in whose context this call */
688 /* was made */
689 /* */
690 /* Inputs : None */
691 /* Globals : None */
692 /* Processing : None */
693 /* Outputs : None */
694 /* Returns : Thread ID, as a WORD32 */
695 /* Issues : None */
696 /* */
697 /* Revision History: */
698 /* */
699 /* DD MM YYYY Author(s) Changes (Describe the changes made) */
700 /* 07 05 2015 Ittiam Draft */
701 /* */
702 /*****************************************************************************/
703
osal_get_current_tid(void)704 WORD32 osal_get_current_tid(void)
705 {
706 return syscall(__NR_gettid);
707 }
708