C++程序  |  708行  |  38.29 KB

/******************************************************************************
 *
 * 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);
}