/**************************************************************************** * Copyright (c) 2006 DST Technologies Inc. All Rights Reserved. * * Module: OS_QUEUE * * Description: Unified APIs for interfacing with different operating systems * (WinCE) * * Notes: This module implement APIs to interface with the following * operating system's objects: * - Queues * * This implementation provide fixed-length-message queues. The * message can be of any size, selected by the caller who creates * the queue. However, these queues can not be shared between * multiple processes and can not be used from an ISR. * ***************************************************************************/ /*========================== * Includes *=========================*/ #include "dsthallocal.h" #include "os.h" #include "os_prive.h" #include #ifdef DMALLOC #include #endif #define DEBUG 0 //yzyeo #define MSGQ_SIZE #ifdef MSGQ_SIZE typedef struct { DS_U32 msg_size; DS_U8 msg[0]; } MSG_DATA,*pMSG_DATA; #endif /*========================= * Defines *========================*/ typedef struct { DS_U32 Name; DS_U32 ByteSize; /* Size of the queue in bytes */ DS_U32 MsgSize; /* Message size in bytes */ DS_U32 Head; /* Head offset from queue start */ DS_U32 Tail; /* Tail offset from queue start */ CORE_MUTEX_ID QMutex; /* Queue mutex */ CORE_EVENT_ID QEvent; /* Queue event */ DS_U8 *StartPtr; /* Pointer to queue start */ DS_U32 curCount; DS_U32 maxCount; DS_U32 Limit; }MSG_QUEUE; /*========================= * Local variables *========================*/ /*^^*************************************************************************** * CORE_QUEUE_ID DstCore_QueueCreate (DS_U32 QueueName, DS_U32 MaxMsgCount, * DS_U32 MsgDwordLen) * * Description: Create a fixed length message queue. * * Entry : QueueName = Unique number identifying the Queue. Must be set * to NULL since this implementation does not support * process-shared queues. * MaxMagCount = Max number of messages the queue can hold. * MsgDwordLen = Message length in DWORDs. (e.g, if the max message * length is 16 bytes, this parameter must be set to 4) * * * * Return: Queue ID or * NULL if any error * * Notes : The queue will be created empty with priority order pending. * The entry QueueName is currently not used since queues can not be * shared between multiple processes. **************************************************************************^^*/ CORE_QUEUE_ID DstCore_QueueCreate (DS_U32 QueueName, DS_U32 MaxMsgCount, DS_U32 MsgDwordLen) { CORE_MUTEX_ID Qmutex; CORE_EVENT_ID Qevent; MSG_QUEUE *Qptr; DS_U32 MsgLen; /* Message byte length */ MaxMsgCount++; /* Queue is full if only one entry free */ //yzyeo #ifndef MSGQ_SIZE MsgLen = MsgDwordLen * 4; #else MsgLen = sizeof(MSG_DATA) + (MsgDwordLen); #endif /*================================================ * Create memory, mutex and event for the queue *===============================================*/ Qptr = (MSG_QUEUE *) malloc ( sizeof (MSG_QUEUE) + (MaxMsgCount * MsgLen)); #if 0 if ( Qptr == (MSG_QUEUE *)0x10132008 ) { if ( QueueName ) { char *ptr = (char *)QueueName; printf("Q Name = %s\n", ptr); } Qptr = (MSG_QUEUE *) malloc ( sizeof (MSG_QUEUE) + (MaxMsgCount * MsgLen) ); } #endif if (Qptr == NULL) { return (0); } Qmutex = DstCore_MutexCreate (0); if (Qmutex == 0) { free (Qptr); return (0); } Qevent = DstCore_EventCreate (0, _FALSE_); if (Qevent == 0) { DstCore_MutexDelete (Qmutex); free (Qptr); return (0); } /*========================================== * Initialize the queue *=========================================*/ DstCore_MutexLock (Qmutex, OS_WAIT_FOREVER); Qptr->Name = QueueName; Qptr->ByteSize = MaxMsgCount * MsgLen; Qptr->MsgSize = MsgLen; Qptr->Head = 0; Qptr->Tail = 0; Qptr->QMutex = Qmutex; Qptr->QEvent = Qevent; Qptr->StartPtr = (DS_U8 *) (((DS_U32)Qptr) + sizeof (MSG_QUEUE)); Qptr->curCount = 0; Qptr->maxCount = MaxMsgCount; Qptr->Limit = ((DS_U32)Qptr) + sizeof (MSG_QUEUE) + (MaxMsgCount * MsgLen); #if DEBUG printf("QId=0x%08lX, StartPtr=0x%08lX, Limit=0x%08lX,", (DS_U32)Qptr, (DS_U32)Qptr->StartPtr, (DS_U32)Qptr->Limit); printf("ByteSize=0x%08lX, MsgSize=0x%08lX, MaxMsgCount=0x%08lX\n", Qptr->ByteSize, Qptr->MsgSize, MaxMsgCount); #endif DstCore_MutexUnlock (Qmutex); return ((CORE_QUEUE_ID)Qptr); } /*^^*************************************************************************** * DS_U32 DstCore_QueuePost (CORE_QUEUE_ID QueueId, DS_U32 Message) * * Description: Post a message to a fixed-length message queue. * * Entry : QueueId = Returned by QueueCreate * Message = Pointer to the message to put at end of queue. Message * size must be equal to the queue message size * * Return: OS_OK * OS_FAIL * * Notes : **************************************************************************^^*/ DS_U32 DstCore_QueuePost (CORE_QUEUE_ID QueueId, DS_U32 *Message #ifdef MSGQ_SIZE , DS_U32 msg_size #endif ) { CORE_MUTEX_ID Qmutex; MSG_QUEUE *Qptr; DS_U32 RetVal = OS_FAIL; DS_U32 Head, Tail, Avail; /*========================================== * Get queue mutex *=========================================*/ if (QueueId == 0) { return (OS_FAIL); } Qptr = (MSG_QUEUE *) QueueId; Qmutex = Qptr->QMutex; DstCore_MutexLock (Qmutex, OS_WAIT_FOREVER); /*========================================== * Get available space in the queue *=========================================*/ Head = Qptr->Head; Tail = Qptr->Tail; if (Head > Tail) { Avail = Head - Tail; } else { Avail = Qptr->ByteSize - (Tail - Head); } /*==================================== * If there's space for two messages *===================================*/ if (Avail >= (Qptr->MsgSize * 2)) { #ifdef MSGQ_SIZE pMSG_DATA pData; pData = (pMSG_DATA)((DS_U8*)Qptr->StartPtr + Tail); if(msg_size > Qptr->MsgSize){ printf("ERROR: message queue sending data size is overflow(%ld > %ld) \n",msg_size,Qptr->MsgSize); msg_size = Qptr->MsgSize; } pData->msg_size = msg_size; //Tail += sizeof(MSG_DATA); if ( ((DS_U32)(pData->msg) + msg_size) > Qptr->Limit ) { printf("|%s| ERROR: LINE=%d\n", __FUNCTION__, __LINE__); } #if DEBUG printf("|%s| Current Ptr = 0x%08lX\n", __FUNCTION__, (DS_U32)pData->msg); #endif memcpy(pData->msg, Message, msg_size); #else memcpy (Qptr->StartPtr + Tail, Message, Qptr->MsgSize); #endif Tail+= Qptr->MsgSize; if (Tail >= Qptr->ByteSize) { Tail = 0; } Qptr->Tail = Tail; RetVal = OS_OK; DstCore_EventSet (Qptr->QEvent); /* Set the queue event */ Qptr->curCount++; if ( Qptr->curCount >= Qptr->maxCount ) { printf("|%s:%d| ERROR: Queue Count is over than maxCount! Qptr->curCount=%d, Qptr->maxCount=%d\n", __FUNCTION__, __LINE__, (int)Qptr->curCount, (int)Qptr->maxCount ); } } DstCore_MutexUnlock (Qmutex); return (RetVal); } /*^^*************************************************************************** * DS_U32 DstCore_QueueWait (CORE_QUEUE_ID QueueId, DS_U32 *Msg, DS_U32 Timeout) * * Description: Wait for a message in a queue. * * Entry : QueueId = Returned by QueueCreate * Msg = Pointer to buffer to receive message of queue msg length * Timeout = In 1/100 of a second increments. This is ONLY accurate * if the OS provides a way of getting system ticks/second. * = 0 to return immidiately if the resource not available * = OS_WAIT_FOREVER to wait forever on the resource * * Return: OS_OK * OS_TIMEOUT * OS_FAIL * * Notes : **************************************************************************^^*/ DS_U32 DstCore_QueueWait (CORE_QUEUE_ID QueueId, DS_U32 *Msg, DS_U32 Timeout #ifdef MSGQ_SIZE , DS_U32 * MsgSize #endif ) { CORE_MUTEX_ID Qmutex; MSG_QUEUE *Qptr; DS_U32 RetVal = OS_OK; DS_U32 Head = 0, Tail; /*========================================== * Get queue mutex *=========================================*/ if (QueueId == 0) { return (OS_FAIL); } Qptr = (MSG_QUEUE *) QueueId; Qmutex = Qptr->QMutex; #ifdef ONE_RX_THR Head = Qptr->Head; Tail = Qptr->Tail; #else Tail = Head + 1; /* Make head != tail */ #endif /*============================================= * Wait until there's messages in the queue *============================================*/ while (_TRUE_) { if (Head == Tail) { RetVal = DstCore_EventWait (Qptr->QEvent, _TRUE_, Timeout); } #ifndef ONE_RX_THR DstCore_MutexLock (Qmutex, OS_WAIT_FOREVER); Head = Qptr->Head; #endif Tail = Qptr->Tail; if ((Head != Tail) || (RetVal != OS_OK)) { break; } /*========================================= * Got event but no messages in the queue *========================================*/ #ifndef ONE_RX_THR DstCore_MutexUnlock (Qmutex); #endif } /*============================================= * If there's messages in the queue *============================================*/ if (RetVal == OS_OK) { /*============================================= * If we have a message *============================================*/ if (Head != Tail) { #ifdef MSGQ_SIZE pMSG_DATA pData; unsigned int msg_size; pData = (pMSG_DATA)((DS_U8*)Qptr->StartPtr + Head); msg_size = pData->msg_size; //Head += sizeof(MSG_DATA); if(msg_size > Qptr->MsgSize){ printf("ERROR: message queue sending data size is overflow(%ld > %ld) \n",(long)msg_size,Qptr->MsgSize); msg_size = Qptr->MsgSize; } #if DEBUG printf("|%s| Current Ptr = 0x%08lX\n", __FUNCTION__, (DS_U32)pData->msg); #endif memcpy(Msg, pData->msg, msg_size); *MsgSize = msg_size; #else memcpy(Msg, Qptr->StartPtr + Head, Qptr->MsgSize); #endif Head+= Qptr->MsgSize; if (Head >= Qptr->ByteSize) { Head = 0; } Qptr->Head = Head; DstCore_EventReset (Qptr->QEvent); if ( Qptr->curCount == 0 ) { printf("|%s:%d| ERROR: Queue Count is now -1.\n", __FUNCTION__, __LINE__); } Qptr->curCount--; } else { RetVal = OS_FAIL; } } #ifndef ONE_RX_THR DstCore_MutexUnlock (Qmutex); #endif return (RetVal); } /*^^*************************************************************************** * DS_U32 DstCore_QueueReset (CORE_QUEUE_ID QueueId) * * Description: Removes all messages from fixed-length message queue. * * Entry : QueueId = Returned by QueueCreate * * Return: OS_OK * OS_FAIL * * Notes : The queue will be empty after this call. **************************************************************************^^*/ DS_U32 DstCore_QueueReset (CORE_QUEUE_ID QueueId) { CORE_MUTEX_ID Qmutex; MSG_QUEUE *Qptr; /*========================================== * Get queue mutex *=========================================*/ if (QueueId == 0) { return (OS_FAIL); } Qptr = (MSG_QUEUE *) QueueId; Qmutex = Qptr->QMutex; /*============================================= * Reset queue head and tail *============================================*/ DstCore_MutexLock (Qmutex, OS_WAIT_FOREVER); Qptr->Head = 0; Qptr->Tail = 0; Qptr->curCount = 0; DstCore_EventReset (Qptr->QEvent); DstCore_MutexUnlock (Qmutex); return (OS_OK); } /*^^*************************************************************************** * DS_U32 DstCore_QueueDelete (CORE_QUEUE_ID QueueId) * * Description: Delete a fixed-length message queue. * * Entry : QueueId = Returned by QueueCreate * * Return: OS_OK * OS_FAIL * * Notes : **************************************************************************^^*/ DS_U32 DstCore_QueueDelete (CORE_QUEUE_ID QueueId) { CORE_MUTEX_ID Qmutex; MSG_QUEUE *Qptr; /*========================================== * Get queue mutex *=========================================*/ if (QueueId == 0) { return (OS_FAIL); } Qptr = (MSG_QUEUE *) QueueId; Qmutex = Qptr->QMutex; /*============================================= * Delete queue event, mutex and memory *============================================*/ DstCore_MutexLock (Qmutex, OS_WAIT_FOREVER); DstCore_EventDelete (Qptr->QEvent); free (Qptr); DstCore_MutexUnlock (Qmutex); DstCore_MutexDelete (Qmutex); return (OS_OK); } /*^^*************************************************************************** * DS_BOOL Os_QueueInit (DS_BOOL Init) * * Description: Queues local data initialization * * Entry : Init = _TRUE_ to init * _FALSE_ to free * * Return: _TRUE_ if success * * Notes : * **************************************************************************^^*/ DS_BOOL Os_QueueInit (DS_BOOL Init) { return (_TRUE_); }