| /****************************************************************************** |
| * |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at: |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| ***************************************************************************** |
| * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore |
| */ |
| |
| /*****************************************************************************/ |
| /* */ |
| /* File Name : osal_thread.c */ |
| /* */ |
| /* Description : This file contains Thread API's implemented for */ |
| /* different platforms. */ |
| /* */ |
| /* List of Functions : osal_thread_create */ |
| /* osal_thread_destroy */ |
| /* osal_func */ |
| /* osal_set_thread_priority */ |
| /* osal_set_thread_core_affinity */ |
| /* osal_thread_sleep */ |
| /* osal_thread_yield */ |
| /* osal_thread_suspend */ |
| /* osal_thread_resume */ |
| /* osal_thread_wait */ |
| /* osal_get_thread_handle */ |
| /* osal_get_time */ |
| /* osal_get_time_usec */ |
| /* osal_get_last_error */ |
| /* osal_print_last_error */ |
| /* */ |
| /* Issues / Problems : None */ |
| /* */ |
| /* Revision History : */ |
| /* */ |
| /* DD MM YYYY Author(s) Changes (Describe the changes made) */ |
| /* 06 03 2006 Ittiam Draft */ |
| /* */ |
| /*****************************************************************************/ |
| |
| /*****************************************************************************/ |
| /* File Includes */ |
| /*****************************************************************************/ |
| |
| /* System include files */ |
| #include <stdio.h> |
| |
| #include <semaphore.h> |
| #include <pthread.h> |
| #include <errno.h> |
| #include <sys/time.h> |
| #include <sys/resource.h> |
| |
| #include <unistd.h> |
| #include <math.h> |
| #include <sched.h> /*for CPU_SET, etc.. */ |
| #include <linux/unistd.h> |
| #include <sys/syscall.h> |
| |
| /* User include files */ |
| #include "cast_types.h" |
| #include "osal.h" |
| #include "osal_handle.h" |
| #include "osal_thread.h" |
| #include "osal_errno.h" |
| |
| /*****************************************************************************/ |
| /* Static Function Declarations */ |
| /*****************************************************************************/ |
| |
| static void osal_func(void *param); |
| |
| /*****************************************************************************/ |
| /* */ |
| /* Function Name : osal_thread_create */ |
| /* */ |
| /* Description : This function create a new thread. */ |
| /* */ |
| /* Inputs : OSAL handle */ |
| /* Memory Manager Handle */ |
| /* Thread creation attributes */ |
| /* */ |
| /* Globals : None */ |
| /* */ |
| /* Processing : This function calls OS specific thread create API's and */ |
| /* creates a new thread with specified attributes. */ |
| /* */ |
| /* Outputs : Status of thread creation */ |
| /* */ |
| /* Returns : On SUCCESS - 0 */ |
| /* On FAILURE - -1 */ |
| /* */ |
| /* Issues : Only supports creating threads with default attributes */ |
| /* */ |
| /* Revision History: */ |
| /* */ |
| /* DD MM YYYY Author(s) Changes (Describe the changes made) */ |
| /* 06 03 2006 Ittiam Draft */ |
| /* */ |
| /*****************************************************************************/ |
| |
| void *osal_thread_create(IN void *osal_handle, IN osal_thread_attr_t *attr) |
| { |
| osal_t *handle = (osal_t *)osal_handle; |
| WORD32 priority = 0; |
| void *mmr_handle = 0; |
| |
| /* If Handle or attributes are not valid, return ERRORED. */ |
| if(0 == attr) |
| return 0; |
| |
| if(0 == handle || 0 == handle->alloc || 0 == handle->free) |
| return 0; |
| |
| /* Initialize MMR handle */ |
| mmr_handle = handle->mmr_handle; |
| |
| { |
| pthread_attr_t tattr; |
| thread_handle_t *hdl = 0; |
| |
| attr->sched_policy = OSAL_SCHED_RR; |
| |
| /* Allocate memory for thread handle */ |
| hdl = handle->alloc(mmr_handle, sizeof(thread_handle_t)); |
| if(0 == hdl) |
| return 0; |
| |
| /* Initialize thread handle parameters */ |
| hdl->mmr_handle = mmr_handle; |
| hdl->hdl = handle; |
| hdl->exit_code = attr->exit_code; |
| hdl->priority = priority; |
| hdl->thread_func = attr->thread_func; |
| hdl->thread_param = attr->thread_param; |
| |
| /* initialized with default attributes */ |
| if(0 != pthread_attr_init(&tattr)) |
| { |
| handle->free(hdl->mmr_handle, hdl); |
| return 0; |
| } |
| |
| /* Create the thread */ |
| hdl->thread_id = pthread_create( |
| &(hdl->thread_handle), /* Thread Handle */ |
| &tattr, /* Attributes */ |
| (void *(*)(void *))osal_func, |
| hdl); /* Parameters */ |
| |
| /* In case of error in thread creationn, Free the handle memory and */ |
| /* return error. */ |
| if(0 != hdl->thread_id) |
| { |
| handle->free(hdl->mmr_handle, hdl); |
| return 0; |
| } |
| |
| pthread_attr_destroy(&tattr); |
| |
| return hdl; |
| } |
| } |
| |
| /*****************************************************************************/ |
| /* */ |
| /* Function Name : osal_thread_destroy */ |
| /* */ |
| /* Description : This function calls OS specific API's to close a thread */ |
| /* which is represented by specified handle. */ |
| /* */ |
| /* Inputs : Initialized thread handle */ |
| /* */ |
| /* Globals : None */ |
| /* */ |
| /* Processing : Closing other threads is supported only in windows. So, */ |
| /* only windows platform supports this API. */ |
| /* */ |
| /* Outputs : Status of thread close */ |
| /* */ |
| /* Returns : On SUCCESS - 0 */ |
| /* On FAILURE - -1 */ |
| /* */ |
| /* Issues : None */ |
| /* */ |
| /* Revision History: */ |
| /* */ |
| /* DD MM YYYY Author(s) Changes (Describe the changes made) */ |
| /* 06 03 2006 Ittiam Draft */ |
| /* */ |
| /*****************************************************************************/ |
| |
| WORD32 osal_thread_destroy(IN void *thread_handle) |
| { |
| /* If thread handle is not valid, return error */ |
| if(0 == thread_handle) |
| return OSAL_ERROR; |
| |
| { |
| thread_handle_t *hdl = (thread_handle_t *)thread_handle; |
| |
| /* Free memory allocated for Thread handle */ |
| ((osal_t *)hdl->hdl)->free(hdl->mmr_handle, hdl); |
| |
| return OSAL_SUCCESS; |
| } |
| } |
| |
| /*****************************************************************************/ |
| /* */ |
| /* Function Name : osal_func */ |
| /* */ |
| /* Description : This function calls the registered threads calling */ |
| /* function */ |
| /* */ |
| /* Inputs : Thread Handle */ |
| /* */ |
| /* Globals : None */ |
| /* */ |
| /* Processing : Calls each registered thread function */ |
| /* */ |
| /* Outputs : None */ |
| /* Returns : None */ |
| /* */ |
| /* Issues : None */ |
| /* */ |
| /* Revision History: */ |
| /* */ |
| /* DD MM YYYY Author(s) Changes (Describe the changes made) */ |
| /* 10 05 2006 Ittiam Draft */ |
| /* */ |
| /*****************************************************************************/ |
| |
| void osal_func(IN void *param) |
| { |
| thread_handle_t *hdl = (thread_handle_t *)param; |
| |
| while(1) |
| { |
| /* Untill thread returns exit code, invoke the thread function */ |
| if(hdl->exit_code == hdl->thread_func(hdl->thread_param)) |
| break; |
| } |
| |
| /* On Linux platforms call pthread_exit() to release all the resources */ |
| /* allocated. */ |
| pthread_exit(NULL); |
| } |
| |
| /*****************************************************************************/ |
| /* */ |
| /* Function Name : osal_thread_sleep */ |
| /* */ |
| /* Description : This function calls OS specific API and makes thread */ |
| /* sleep for specified number of milli seconds. */ |
| /* */ |
| /* Inputs : Initialized thread handle */ |
| /* Time to sleep in millisceonds */ |
| /* */ |
| /* Globals : None */ |
| /* */ |
| /* Processing : Calls API to sleep for specified number of milli seconds */ |
| /* */ |
| /* Outputs : Status of sleep */ |
| /* */ |
| /* Returns : On SUCCESS - 0 */ |
| /* On FAILURE - -1 */ |
| /* */ |
| /* Issues : None */ |
| /* */ |
| /* Revision History: */ |
| /* */ |
| /* DD MM YYYY Author(s) Changes (Describe the changes made) */ |
| /* 06 03 2006 Ittiam Draft */ |
| /* */ |
| /*****************************************************************************/ |
| |
| WORD32 osal_thread_sleep(IN UWORD32 milli_seconds) |
| { |
| { |
| struct timespec timer; |
| |
| /* Convert time in milliseconds into seconds and nano seconds */ |
| timer.tv_sec = milli_seconds / 1000; |
| milli_seconds -= (timer.tv_sec * 1000); |
| timer.tv_nsec = milli_seconds * MEGA_CONST; |
| |
| /* Using Monotonic clock to sleep, also flag is set to 0 for relative */ |
| /* time to current clock time */ |
| if(0 == clock_nanosleep(CLOCK_MONOTONIC, 0, &timer, NULL)) |
| { |
| return OSAL_SUCCESS; |
| } |
| |
| return OSAL_ERROR; |
| } |
| } |
| |
| /*****************************************************************************/ |
| /* */ |
| /* Function Name : osal_thread_yield */ |
| /* */ |
| /* Description : This function causes the yield its execution. */ |
| /* */ |
| /* Inputs : Thread Handle */ |
| /* */ |
| /* Globals : None */ |
| /* */ |
| /* Processing : Calls OS specific yield calls. */ |
| /* */ |
| /* Outputs : Status of Thread Yield */ |
| /* */ |
| /* Returns : On SUCCESS - 0 */ |
| /* On FAILURE - -1 */ |
| /* */ |
| /* Issues : Yield in WIN32 (whihc is a 16 - bit API) is still present*/ |
| /* only to maintian backward compatibility. Can get */ |
| /* deprecated in future. */ |
| /* */ |
| /* Revision History: */ |
| /* */ |
| /* DD MM YYYY Author(s) Changes (Describe the changes made) */ |
| /* 06 03 2006 Ittiam Draft */ |
| /* */ |
| /*****************************************************************************/ |
| |
| WORD32 osal_thread_yield() |
| { |
| if(0 == sched_yield()) |
| return OSAL_SUCCESS; |
| |
| return OSAL_ERROR; |
| } |
| |
| /*****************************************************************************/ |
| /* */ |
| /* Function Name : osal_thread_suspend */ |
| /* */ |
| /* Description : This function causes the suspension its execution. */ |
| /* */ |
| /* Inputs : Thread Handle */ |
| /* */ |
| /* Globals : None */ |
| /* */ |
| /* Processing : Calls OS specific suspend calls. */ |
| /* */ |
| /* Outputs : Status of Thread Suspend */ |
| /* */ |
| /* Returns : On SUCCESS - 0 */ |
| /* On FAILURE - -1 */ |
| /* */ |
| /* Issues : API not supported in Redhat Linux. Refer Redhat */ |
| /* documentation in: */ |
| /* http://www.redhat.com/docs/wp/solaris_port/c1347.html */ |
| /* */ |
| /* Revision History: */ |
| /* */ |
| /* DD MM YYYY Author(s) Changes (Describe the changes made) */ |
| /* 30 03 2006 Ittiam Draft */ |
| /* */ |
| /*****************************************************************************/ |
| |
| WORD32 osal_thread_suspend(IN void *thread_handle) |
| { |
| /* If thread handle is not valid, return error */ |
| if(0 == thread_handle) |
| return OSAL_ERROR; |
| |
| { |
| /* Thread suspend are not supported in Redhat Linux. Refer link */ |
| /* http://www.redhat.com/docs/wp/solaris_port/c1347.html */ |
| |
| return OSAL_NOT_SUPPORTED; |
| } |
| } |
| |
| /*****************************************************************************/ |
| /* */ |
| /* Function Name : osal_thread_resume */ |
| /* */ |
| /* Description : This function causes the resumption its execution. */ |
| /* */ |
| /* Inputs : Thread Handle */ |
| /* */ |
| /* Globals : None */ |
| /* */ |
| /* Processing : Calls OS specific resume calls. */ |
| /* */ |
| /* Outputs : Status of Thread Suspend */ |
| /* */ |
| /* Returns : On SUCCESS - 0 */ |
| /* On FAILURE - -1 */ |
| /* */ |
| /* Issues : API not supported in Redhat Linux. Refer Redhat */ |
| /* documentation in: */ |
| /* http://www.redhat.com/docs/wp/solaris_port/c1347.html */ |
| /* */ |
| /* Revision History: */ |
| /* */ |
| /* DD MM YYYY Author(s) Changes (Describe the changes made) */ |
| /* 30 03 2006 Ittiam Draft */ |
| /* */ |
| /*****************************************************************************/ |
| |
| WORD32 osal_thread_resume(IN void *thread_handle) |
| { |
| /* If thread handle is not valid, return error */ |
| if(0 == thread_handle) |
| return OSAL_ERROR; |
| |
| { |
| /* Thread suspend are not supported in Redhat Linux. Refer link */ |
| /* http://www.redhat.com/docs/wp/solaris_port/c1347.html */ |
| |
| return OSAL_NOT_SUPPORTED; |
| } |
| } |
| |
| /*****************************************************************************/ |
| /* */ |
| /* Function Name : osal_thread_wait */ |
| /* */ |
| /* Description : This function causes the wait untill called thread */ |
| /* finishes execution */ |
| /* */ |
| /* Inputs : Thread Handle */ |
| /* */ |
| /* Globals : None */ |
| /* */ |
| /* Processing : Calls OS specific wait call for wait on another thread */ |
| /* */ |
| /* Outputs : Status of Thread wait */ |
| /* */ |
| /* Returns : On SUCCESS - 0 */ |
| /* On FAILURE - -1 */ |
| /* */ |
| /* Issues : None */ |
| /* */ |
| /* Revision History: */ |
| /* */ |
| /* DD MM YYYY Author(s) Changes (Describe the changes made) */ |
| /* 30 03 2006 Ittiam Draft */ |
| /* */ |
| /*****************************************************************************/ |
| |
| WORD32 osal_thread_wait(IN void *thread_handle) |
| { |
| if(0 == thread_handle) |
| return OSAL_ERROR; |
| |
| { |
| WORD32 result = 0; |
| void *status = 0; |
| |
| thread_handle_t *hdl = (thread_handle_t *)thread_handle; |
| |
| /* Join the thread to wait for thread to complete execution */ |
| result = pthread_join(hdl->thread_handle, (void **)&status); |
| |
| return result; |
| } |
| } |
| |
| /*****************************************************************************/ |
| /* */ |
| /* Function Name : osal_get_thread_handle */ |
| /* */ |
| /* Description : This function gets current thread handle. Currently not */ |
| /* supported */ |
| /* */ |
| /* Inputs : OSAL handle. */ |
| /* */ |
| /* Globals : None */ |
| /* */ |
| /* Processing : Gets all the thread properities and constructs a new */ |
| /* thread handle . */ |
| /* */ |
| /* Outputs : Thread handle to current thread. */ |
| /* */ |
| /* Returns : On SUCCESS - Current thread handle */ |
| /* On FAILURE - NULL */ |
| /* */ |
| /* Issues : Not supported on Linux and BIOS platforms. */ |
| /* */ |
| /* Revision History: */ |
| /* */ |
| /* DD MM YYYY Author(s) Changes (Describe the changes made) */ |
| /* 10 05 2006 Ittiam Draft */ |
| /* */ |
| /*****************************************************************************/ |
| |
| void *osal_get_thread_handle(IN void *osal_handle) |
| { |
| osal_t *handle = (osal_t *)osal_handle; |
| |
| if(0 == osal_handle) |
| return 0; |
| |
| { |
| thread_handle_t *hdl = handle->alloc(handle->mmr_handle, sizeof(thread_handle_t)); |
| WORD32 schedpolicy; |
| struct sched_param schedparam; |
| |
| if(0 == hdl) |
| return 0; |
| |
| hdl->mmr_handle = handle->mmr_handle; |
| hdl->hdl = handle; |
| hdl->exit_code = 0; |
| hdl->thread_func = 0; |
| hdl->thread_param = 0; |
| hdl->thread_handle = pthread_self(); |
| hdl->thread_id = 0; |
| hdl->priority = schedparam.sched_priority; |
| |
| /* Get thread priority from scheduling parameters */ |
| if(0 != pthread_getschedparam(hdl->thread_handle, &schedpolicy, &schedparam)) |
| { |
| return 0; |
| } |
| |
| return hdl; |
| } |
| } |
| |
| /*****************************************************************************/ |
| /* */ |
| /* Function Name : osal_get_time */ |
| /* */ |
| /* Description : This function returns absolute time in milli seconds */ |
| /* */ |
| /* Inputs : None */ |
| /* Globals : None */ |
| /* */ |
| /* Processing : Gets the absolute time by calling OS specific API's. */ |
| /* */ |
| /* Outputs : Absolute time in milli seconds. */ |
| /* */ |
| /* Returns : +ve 32 bit value */ |
| /* */ |
| /* Issues : None */ |
| /* */ |
| /* Revision History: */ |
| /* */ |
| /* DD MM YYYY Author(s) Changes (Describe the changes made) */ |
| /* 06 03 2006 Ittiam Draft */ |
| /* */ |
| /*****************************************************************************/ |
| |
| UWORD32 osal_get_time() |
| { |
| { |
| struct timespec time_val; |
| int cur_time; |
| |
| /* Get the Monotonic time */ |
| clock_gettime(CLOCK_MONOTONIC, &time_val); |
| |
| /* Convert time in seconds and micro seconds into milliseconds time */ |
| cur_time = time_val.tv_sec * 1000 + time_val.tv_nsec / 1000000; |
| return cur_time; |
| } |
| } |
| |
| /*****************************************************************************/ |
| /* */ |
| /* Function Name : osal_get_time_usec */ |
| /* */ |
| /* Description : This function returns absolute time in micro seconds */ |
| /* */ |
| /* Inputs : None */ |
| /* Globals : None */ |
| /* */ |
| /* Processing : Gets the absolute time by calling OS specific API's. */ |
| /* */ |
| /* Outputs : Absolute time in micro seconds. */ |
| /* */ |
| /* Returns : +ve 32 bit value */ |
| /* */ |
| /* Issues : None */ |
| /* */ |
| /* Revision History: */ |
| /* */ |
| /* DD MM YYYY Author(s) Changes (Describe the changes made) */ |
| /* 06 03 2009 Ittiam Draft */ |
| /* */ |
| /*****************************************************************************/ |
| |
| WORD32 osal_get_time_usec(UWORD32 *sec, UWORD32 *usec) |
| { |
| if((0 == sec) || (0 == usec)) |
| return OSAL_ERROR; |
| |
| { |
| struct timespec time_val; |
| |
| /* Get the Monotonic time */ |
| clock_gettime(CLOCK_MONOTONIC, &time_val); |
| |
| /* Convert time in seconds and micro seconds into milliseconds time */ |
| *sec = time_val.tv_sec; |
| *usec = time_val.tv_nsec / 1000; |
| |
| return OSAL_SUCCESS; |
| } |
| } |
| |
| /*****************************************************************************/ |
| /* */ |
| /* Function Name : osal_get_last_error */ |
| /* */ |
| /* Description : This function gets the last error code. */ |
| /* */ |
| /* Inputs : None */ |
| /* Globals : None */ |
| /* */ |
| /* Processing : Gets the last occured error code by calling OS specific */ |
| /* API call. */ |
| /* */ |
| /* Outputs : Error Number */ |
| /* */ |
| /* Returns : If no error - 0 */ |
| /* Else - +ve number */ |
| /* */ |
| /* Issues : None */ |
| /* */ |
| /* Revision History: */ |
| /* */ |
| /* DD MM YYYY Author(s) Changes (Describe the changes made) */ |
| /* 06 03 2006 Ittiam Draft */ |
| /* */ |
| /*****************************************************************************/ |
| |
| UWORD32 osal_get_last_error() |
| { |
| UWORD32 get_linux_error(void); |
| return get_linux_error(); |
| } |
| |
| /*****************************************************************************/ |
| /* */ |
| /* Function Name : osal_print_last_error */ |
| /* */ |
| /* Description : This function prints the last error message. */ |
| /* */ |
| /* Inputs : None */ |
| /* Globals : None */ |
| /* */ |
| /* Processing : Gets the last occured error code by calling OS specific */ |
| /* API call. It prints argument string (if not NULL), */ |
| /* followed by ': ' then the error_string and <new_line>. */ |
| /* */ |
| /* Outputs : None */ |
| /* */ |
| /* Returns : None */ |
| /* */ |
| /* Issues : None */ |
| /* */ |
| /* Revision History: */ |
| /* */ |
| /* DD MM YYYY Author(s) Changes (Describe the changes made) */ |
| /* 10 03 2006 Ittiam Draft */ |
| /* */ |
| /*****************************************************************************/ |
| |
| void osal_print_last_error(IN const STRWORD8 *string) |
| { |
| perror(string); |
| } |
| |
| /*****************************************************************************/ |
| /* */ |
| /* Function Name : osal_get_current_tid */ |
| /* */ |
| /* Description : Gets the tid of the thread in whose context this call */ |
| /* was made */ |
| /* */ |
| /* Inputs : None */ |
| /* Globals : None */ |
| /* Processing : None */ |
| /* Outputs : None */ |
| /* Returns : Thread ID, as a WORD32 */ |
| /* Issues : None */ |
| /* */ |
| /* Revision History: */ |
| /* */ |
| /* DD MM YYYY Author(s) Changes (Describe the changes made) */ |
| /* 07 05 2015 Ittiam Draft */ |
| /* */ |
| /*****************************************************************************/ |
| |
| WORD32 osal_get_current_tid(void) |
| { |
| return syscall(__NR_gettid); |
| } |