📄 osapi_linux.cpp
字号:
/*****************************************************************************
******************************************************************************
** **
** Copyright (c) 2002 Videon Central, Inc. **
** All rights reserved. **
** **
** The computer program contained herein contains proprietary information **
** which is the property of Videon Central, Inc. The program may be used **
** and/or copied only with the written permission of Videon Central, Inc. **
** or in accordance with the terms and conditions stipulated in the **
** agreement/contract under which the programs have been supplied. **
** **
******************************************************************************
*****************************************************************************/
/**
* @file osapi_linux.cpp
*
* $Revision: 1.63 $
*
* Operating System API (OSAPI) source file. Provides an abstraction from the
* operating system.
*
* This is the implementation for Linux
*
*/
#define POSIX_SEMAPHORE
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <errno.h>
#include <signal.h>
#include "vdvd_types.h"
#include "osapi.h"
#include "dbgprint.h"
#ifdef DMALLOC
#include "dmalloc.h"
#endif
/* MACROS AND DEFINES */
#define DBG_OSAPI DBG_ERROR
#define DBG_ON(x) (DBG_OSAPI >= x)
#define MAX_NAME_SIZE 16
#define OS_MSG_Q_HEAD 0
#define OS_MSG_Q_TAIL 1
//#define __CALC_PEAK_ALLOCATION
/* TYPEDEFS */
#ifdef __CALC_PEAK_ALLOCATION
typedef struct tag_mem_info
{
PVOID pvAddr;
ULONG size;
} mem_info;
#endif
/*
* Thread record
*/
typedef struct tagThreadRecord /* prefix: thread */
{
PVOID pvFunction;
PVOID pvParam;
PVOID pvStackBase;
pthread_t pthread;
pthread_attr_t attr;
} OS_TASK;
/*
* Semaphore record
*/
typedef struct tagSemaphoreRecord /* prefix: sem */
{
ULONG ulSemType;
char strName[MAX_NAME_SIZE];
ULONG ulCount;
ULONG ulMaxCount;
pthread_cond_t condWait; /* Signal waiting threads */
pthread_mutex_t mutex; /* Critical sections */
} OS_SEMAPHORE;
/*
* Message Box record
*/
typedef struct tagMessageBoxRecord /* prefix: mbox */
{
ULONG ulDepth; /* message queue depth */
ULONG ulSize; /* message size */
ULONG ulHead;
ULONG ulTail;
BYTE *pbBuffers; /* buffer for messages */
pthread_cond_t condWaitFull; /* Signal waiting threads */
pthread_cond_t condWaitEmpty; /* Signal waiting threads */
pthread_mutex_t mutex; /* Critical sections */
} OS_MBOX;
typedef struct tagTimerRecord
{
PVOID pvFunction;
PVOID pvParam;
timer_t timerID;
} OS_TIMER;
/*
* Memory Pool ID record
*/
typedef struct tagMemPoolRecord
{
ULONG ulPgSize; /* Size of each page of memory */
ULONG ulNumPages; /* Number of memory pages */
struct Page /* A page from a memory pool */
{
PVOID pvPgAddr; /* Pointer to memory address */
LONG lAttached; /* Number of pages attached with page *
* (including itself) */
} *memPage;
} OS_MEMPOOL;
/* GLOABALS */
pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
#ifdef __CALC_PEAK_ALLOCATION
mem_info test[512];
BOOLEAN fFirstAlloc = TRUE;
ULONG ulCurrentAllocations = 0;
ULONG ulPeakAllocations = 0;
#endif
/* private function prototypes */
static PVOID linuxThread(PVOID);
static void linuxTimer(union sigval sigval);
#ifdef VC_TIMERS
int vc_timer_delete(timer_t timerid);
int vc_timer_create(clockid_t clock_id, struct sigevent *evp, timer_t *timerid);
int vc_timer_settime(timer_t timerid, int flags, const struct itimerspec *value, struct itimerspec *ovalue);
int vc_timer_gettime(timer_t timerid, struct itimerspec *value);
static ULONG TimerThreadProc( PVOID pvParam );
#define timer_delete vc_timer_delete
#define timer_create vc_timer_create
#define timer_settime vc_timer_settime
#define timer_gettime vc_timer_gettime
#endif
static OS_STATUS OS_MsgQReceiveOption(OS_MSG_Q_ID mqId, char *strMsg, ULONG ulSize, int iTimeout, int iOption);
/******************************************************************************
*******************************************************************************
** **
** Task function definitions **
** **
*******************************************************************************
******************************************************************************/
/**
* OS Task Spawn function.
*
* @param
* char *strName - task name
*
* @param
* int iPrio - task priority
*
* @param
* int iStackSize - task stack size
*
* @param
* OS_FUNCPTR func - task procedure function
*
* @retval
* int pthreadRecord - pointer to the task record, if successful
* OS_FAILURE if not successful.
*/
OS_STATUS OS_TaskSpawn(char *strName,
int iPrio,
int iStackSize,
OS_FUNCPTR func
)
{
return (OS_TaskSpawnParam( strName, iPrio, iStackSize, (OS_FUNCPTR_PARAM)func, NULL, NULL ));
}
/**
* OS Task Spawn Parameter function.
*
* @param
* char *strName - task name
*
* @param
* int iPrio - task priority
*
* @param
* int iStackSize - task stack size
*
* @param
* OS_FUNCPTR func - task procedure function
*
* @param
* PVOID pvParam - task input parameter
*
* @param
* PVOID pvStackBaseParam - stack pointer, allows stack base to be passed
* in rather than OS_Malloc'd.
*
* @retval
* int pthreadRecord - pointer to the task record, if successful
* OS_FAILURE if not successful.
*/
OS_STATUS OS_TaskSpawnParam(char *strName,
int iPrio,
int iStackSize,
OS_FUNCPTR_PARAM func,
PVOID pvParam,
PVOID pvStackBaseParam
)
{
OS_TASK *pthreadRecord;
int iRetStatus = 0;
/* Allocate a record for the thread */
pthreadRecord = (OS_TASK *)OS_MemAlloc(sizeof(OS_TASK));
if (pthreadRecord == NULL)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("OS_TaskSpawn: Could not allocate thread record!\n"));
goto error_handler;
}
/* Check the validity of the given priority */
if ( (iPrio < OS_TASK_MIN_PRIORITY) || (iPrio > OS_TASK_MAX_PRIORITY) )
{
DBGPRINT(DBG_ON(DBG_ERROR), ("%s: Invalid thread priority (%d)!\n", __FUNCTION__, iPrio));
goto error_handler;
}
/* Save the paramater */
pthreadRecord->pvParam = pvParam;
/* Record the pointer to the thread stack base in the thread record */
pthreadRecord->pvStackBase = pvStackBaseParam;
/* Record the function pointer */
pthreadRecord->pvFunction = (PVOID)func;
/* Create the thread attributes */
iRetStatus = pthread_attr_init(&pthreadRecord->attr);
if (iRetStatus != 0)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("%s: ATTRIBUTE CREATION FAILED!\n", __FUNCTION__));
goto error_handler;
}
/* Specify the threads stack size */
pthread_attr_setstacksize(&pthreadRecord->attr, iStackSize);
if (iRetStatus != 0)
{
/* this is not a critical error so just let it be known and continue
* setting up the thread */
DBGPRINT(DBG_ON(DBG_ERROR), ("%s: Could not set our stack size, Using default!\n", __FUNCTION__));
}
/* Create the thread */
iRetStatus = pthread_create(&pthreadRecord->pthread, &pthreadRecord->attr, linuxThread, (PVOID)pthreadRecord);
if (iRetStatus != 0)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("%s: Handle is NULL!\n", __FUNCTION__));
goto error_handler;
}
/* Return the thread record as an integer */
return ( (int)pthreadRecord );
error_handler:
if (NULL != pthreadRecord)
{
OS_MemFree(pthreadRecord);
}
return (OS_FAILURE);
}
/**
* OS Task Delete function.
*
* @param
* int taskId - task identifier
*
* @retval
* This function will print a status message if it was not successful.
*/
void OS_TaskDelete(int taskId)
{
OS_TASK *pthreadRecord;
int iRetStatus;
/* Cast the given task identifier to a pointer to a task record */
pthreadRecord = (OS_TASK *)taskId;
if (pthreadRecord != 0)
{
/* Delete the given thread */
iRetStatus = pthread_cancel(pthreadRecord->pthread);
/* wait for the task to exit */
OS_TaskJoin(taskId);
/* delete the pthread attributes */
iRetStatus = pthread_attr_destroy(&pthreadRecord->attr);
/* Delete the thread record */
OS_MemFree(pthreadRecord);
}
}
/**
* OS Task Exit function.
*
* @param
* None.
*
* @retval
* None.
*/
void OS_TaskExit(void)
{
pthread_exit(0);
}
/**
* Restarts the task from the beginning of the function passed into the spawn command.
*
* @param
* int taskId - task identifier
*
* @retval
* Returns OS_OK.
* This function is always successful.
*/
OS_STATUS OS_TaskReset(int taskId)
{
return (OS_NOT_IMPLEMENTED);
}
/**
* OS Task Suspend function.
*
* @param
* int taskId - task identifier
*
* @retval
* Returns OS_OK.
* This function is always successful.
*/
OS_STATUS OS_TaskSuspend(int taskId)
{
return (OS_NOT_IMPLEMENTED);
}
/**
* Resume a task after a suspend. This replaces OS_TaskRestart!
*
* @param
* int taskId - task identifier
*
* @retval
* Returns OS_OK.
* This function is always successful.
*/
OS_STATUS OS_TaskResume(int taskId)
{
return (OS_NOT_IMPLEMENTED);
}
/**
* OS Task Join function.
*
* @param
* int taskId - task identifier
*
* @retval
* Returns OS_OK.
* This function is always successful.
*/
OS_STATUS OS_TaskJoin(int taskId)
{
OS_STATUS status = OS_OK;
OS_TASK *pthreadRecord;
/* Cast the given task identifier to a pointer to a task record */
pthreadRecord = (OS_TASK *)taskId;
if (pthreadRecord != 0)
{
/* Join the given thread */
if (pthread_join(pthreadRecord->pthread, NULL) != 0)
{
status = OS_FAILURE;
}
}
else
{
status = OS_FAILURE;
}
return (status);
}
/**
* OS Task Yield function.
*
* @param
* None.
*
* @retval
* This function is always successful.
*/
void OS_TaskYield(void)
{
if (sched_yield() == -1)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("failed to yield\n"));
}
}
/**
* OS Task Delay function.
*
* @param
* int iTicks - time to delay the current task, in ticks
*
* @retval
* This function is always successful.
*/
void OS_TaskDelay(int iTicks)
{
#if (CLOCKS_PER_SEC == 1000000)
usleep(iTicks);
#else
ULONGLONG microseconds;
microseconds = (ULONGLONG)iTicks;
microseconds *= 1000000;
microseconds /= CLOCKS_PER_SEC;
usleep( (unsigned long)microseconds );
#endif
}
/**
* OS Task Delay function.
*
* @param
* milliseconds - time to delay the current task, in milliseconds
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -