/******************************************************************** DMW_MsgQue.c OS API¿¡ ÀÇÁ¸ÇÏÁö ¾Ê´Â General Purpose MW Message Queue Á¦°ø Copyright 2006 Digital STREAM Technology, Inc. All Rights Reserved cafrii@dstreamtech.com ********************************************************************/ #include "DMW_Platform.h" #include "DHL_OSAL.h" #include "DMW_Status.h" #include "DMW_MsgQue.h" //#include #define max(a,b) (((a) > (b)) ? (a) : (b)) #define min(a,b) (((a) < (b)) ? (a) : (b)) /* cafrii 090119 change policy mutex°¡ ¾Æ´Ñ ¹æ½ÄÀ¸·Î º¸È£ ±â´É ±¸ÇöÀ» À§ÇØ OS_LockTask() ·ùÀÇ ÇÔ¼ö ´ë½Å DHL_OS_DisableInterrupts() ·ùÀÇ ÇÔ¼ö »ç¿ë. »çÀ¯: º¸È£µÇ´Â ±¸°£ ³»¿¡ °¢Á¾ callbackµéÀÌ È£ÃâµÇ´Âµ¥, OS Scheduler disable »óÅ¿¡¼­ Pending API°¡ ºÒ¸®´Â °æ¿ì ¹®Á¦°¡ »ý±æ ¼ö ÀÖÀ½. */ //---------------------------------------------------------------- // // todo // AllocateMsgQue ¹æ½ÄÀÇ API Á¦°ø // // BOOL g_bUseInterruptMasking = 0; // 060303 ÇöÀç interrupt ¸ðµå·Î µ¿ÀÛ½ÃÄ×À» ¶§ º° ¹®Á¦¾øÀÌ µ¿ÀÛÇÏ¿´À½. // interrupt°¡ disable µÈ »óÅ¿¡¼­ ½Ã°£ÀÌ ¿À·¡ °É¸®´Â ÀÛ¾÷À» Çϸé // ¹®Á¦°¡ »ý±æ¼ö ÀÖÀ¸¹Ç·Î Á¶½ÉÇÒ °Í. // // ¾ÆÁ÷ mutex ¸ðµå·Î Å×½ºÆ®´Â ÇØº¸Áö ¾Ê¾ÒÀ½. // // 091221, cafrii 1->0 // linux usermode¿¡¼­´Â ISR lock »óÅ¿¡¼­ mem alloc/free¸¦ Çã¿ëÇÏÁö ¾Ê´Â´Ù. // DMC message Áß¿¡´Â mem free (ex: FreePMT)¸¦ ¼öÇàÇÏ´Â cleanupÀ» µ¿¹ÝÇÏ´Â °ÍÀÌ À־ // isr disable ¹æ½ÄÀº »ç¿ëÀÌ ºÒ°¡´ÉÇÔ. // #define MSG_ENTRY(idx) &(hMsgQue->MsgBuf[(idx)*(hMsgQue->nMsgSize)]) #define MSG_NAME(idx,fnName) ((fnName) ? (fnName)(MSG_ENTRY(idx)) : "") #define MSG_NAME2(idx) MSG_NAME((idx),(hMsgQue->pfnMsgName)) STATUS DMW_SYS_InitMsgQue(DMW_MSGQUE *hMsgQue, int nMsgSize, int nInitialQueSize, char *(*pfnMsgName)(void *)) { if (hMsgQue == NULL) return statusInvalidArgument; if (nMsgSize == 0) nMsgSize = hMsgQue->nMsgSize; if (nInitialQueSize == 0) nInitialQueSize = hMsgQue->nMaxQueSize; // msg size should be 4 bytes alignment.. // if (nMsgSize & 3) nMsgSize = (nMsgSize+3)/4*4; hMsgQue->nMsgSize = nMsgSize; hMsgQue->nMaxQueSize = nInitialQueSize; hMsgQue->nNumberMsg = 0; hMsgQue->Mutex = DHL_OS_CreateMutexSemaphore("MsgQMutex"); hMsgQue->Sema4 = DHL_OS_CreateCountingSemaphore("MsgQSem", OS_SEM_PRIO, 0); hMsgQue->pfnMsgName = pfnMsgName; hMsgQue->MsgBuf = DHL_OS_Malloc(nMsgSize * nInitialQueSize); if (hMsgQue->MsgBuf == NULL || hMsgQue->Mutex == (DHL_OS_SEMA_ID)DHL_INVALID_SEMA_ID) { return statusOutOfResource; } memset(hMsgQue->MsgBuf, 0, nMsgSize * nInitialQueSize); return statusOK; } STATUS DMW_SYS_ResizeMsgQue() { return statusNotImpl; } // User Message Queue API // STATUS DMW_SYS_AddUserMsg(DMW_MSGQUE *hMsgQue, void *pMsg) { // UserQueue¿¡ DMC message¸¦ insertÇÑ´Ù. ArrayÀÇ Á¦ÀÏ µÞÂÊ¿¡ ³Ö´Â´Ù. // BOOL bOverflow = FALSE; if (hMsgQue == NULL || pMsg == NULL) return statusInvalidArgument; if (hMsgQue->Mutex == 0 || hMsgQue->Sema4 == 0 || hMsgQue->MsgBuf == NULL) { DHL_OS_Printf("!! DMW_SYS_GetUserMsg (0x%x) not init\n", hMsgQue); return statusNotInitialized; } if (1) { UINT32 mask = 0; if (g_bUseInterruptMasking) mask = DHL_OS_DisableInterrupts(); else DHL_OS_TakeSemaphore(hMsgQue->Mutex, DHL_TIMEOUT_FOREVER); if (hMsgQue->nNumberMsg >= hMsgQue->nMaxQueSize-1) { bOverflow = TRUE; } else { // QueueÀÇ Á¦ÀÏ µÚÂÊ¿¡ ºÙÀδÙ. memcpy(MSG_ENTRY(hMsgQue->nNumberMsg), pMsg, hMsgQue->nMsgSize); hMsgQue->nNumberMsg++; } if (g_bUseInterruptMasking) DHL_OS_RestoreInterrupts(mask); else DHL_OS_GiveSemaphore(hMsgQue->Mutex); } if (bOverflow) { DHL_OS_Printf("!! MsgQue overflow. msg 0x%x (%s) ignored.\n", pMsg, hMsgQue->pfnMsgName ? hMsgQue->pfnMsgName(pMsg) : ""); return statusOverflow; } else { DHL_OS_GiveSemaphore(hMsgQue->Sema4); } return statusOK; } STATUS DMW_SYS_GetUserMsg(DMW_MSGQUE *hMsgQue, void *pMsg, UINT32 uTimeoutTicks) { // UserQueue¿¡¼­ DMC message¸¦ °¡Á®¿Â´Ù. // ¾Õ¿¡¼­ 1°³¸¦ »©°í ºó °ø°£Àº shift½ÃÄѼ­ ¸Þ²Û´Ù. // STATUS status = statusOK; BOOL bEmptyError = FALSE; if (hMsgQue == NULL || pMsg == NULL) return statusInvalidArgument; if (hMsgQue->Sema4 == 0 || hMsgQue->MsgBuf == NULL) { DHL_OS_Printf("!! DMW_SYS_GetUserMsg (0x%x) not init\n", hMsgQue); return statusNotInitialized; } if (uTimeoutTicks == 0) { // no wait mode.. if (DHL_OS_TakeSemaphore(hMsgQue->Sema4, 0)) status = statusNotFound; } else if (uTimeoutTicks == DHL_TIMEOUT_FOREVER) { DHL_OS_TakeSemaphore(hMsgQue->Sema4, DHL_TIMEOUT_FOREVER); } else { if (DHL_OS_TakeSemaphore(hMsgQue->Sema4, uTimeoutTicks)) status = statusTimeout; } if (status) { return status; } else // if we successfully take semaphore, we are sure there is message. { UINT32 mask = 0; if (g_bUseInterruptMasking) mask = DHL_OS_DisableInterrupts(); else DHL_OS_TakeSemaphore(hMsgQue->Mutex, DHL_TIMEOUT_FOREVER); if (hMsgQue->nNumberMsg > 0) { // ¾Õ¿¡¼­ºÎÅÍ Çϳª¾¿ »©°£´Ù. memcpy(pMsg, MSG_ENTRY(0), hMsgQue->nMsgSize); // ºó °ø°£À» ä¿ì±â À§ÇØ shift.. #if 0 // Çϳª¾¿ º¹»ç.. //for (i=1; inNumberMsg; i++) // memcpy(MSG_ENTRY[i-1] = MSG_ENTRY[i]; #else hMsgQue->nNumberMsg--; if (hMsgQue->nNumberMsg) memmove(MSG_ENTRY(0), MSG_ENTRY(1), hMsgQue->nNumberMsg * hMsgQue->nMsgSize); #endif } else { bEmptyError = TRUE; } if (g_bUseInterruptMasking) DHL_OS_RestoreInterrupts(mask); else DHL_OS_GiveSemaphore(hMsgQue->Mutex); } if (bEmptyError) { DHL_OS_Printf("!! Sema4 taken but Que empty?\n"); //DHL_OS_GiveSemaphore(hMsgQue->Sema4); return statusNotFound; } return statusOK; } BOOL DMW_SYS_UserMsgExist(DMW_MSGQUE *hMsgQue) { if (hMsgQue == NULL) return FALSE; if (hMsgQue->Mutex == 0 || hMsgQue->Sema4 == 0 || hMsgQue->MsgBuf == NULL) { DHL_OS_Printf("!! DMW_SYS_GetUserMsg (0x%x) not init\n", hMsgQue); return FALSE; } // °£´ÜÇÑ ÇÔ¼öÀ̹ǷΠlockÀ» ÇÏÁö ¾Ê°í ÂüÁ¶.. // return hMsgQue->nNumberMsg > 0 ? TRUE : FALSE; } STATUS DMW_SYS_DeleteMsgConditionally(DMW_MSGQUE *hMsgQue, DMW_FN_MSG_CHECK fnCondition, UINT32 param, DMW_FN_MSG_DELETE fnDelete) { int i, errCnt = 0; int nMsgDeleted = 0; UINT32 mask = 0; if (fnCondition == NULL) return statusInvalidArgument; //DHL_OS_Printf("delete %d msgs..\n", hMsgQue->nNumberMsg); if (g_bUseInterruptMasking) mask = DHL_OS_DisableInterrupts(); else DHL_OS_TakeSemaphore(hMsgQue->Mutex, DHL_TIMEOUT_FOREVER); for (i=0; inNumberMsg; i++) { if (fnCondition(MSG_ENTRY(i), param) == FALSE) continue; //DHL_OS_Printf("\t *** delete msg[%d] (%s) \n", i, MSG_NAME2(i)); // cafrii 060831 add // fnDelete¸¦ ÁöÁ¤ÇÏÁö ¾ÊÀ¸¸é ±×³É »ç¶óÁø´Ù. if (fnDelete) fnDelete(MSG_ENTRY(i)); // queueÀÇ ¸¶Áö¸· index´Â hMsgQue->nNumberMsg - 1 ÀÌ´Ù. // if (i < hMsgQue->nNumberMsg - 1) memmove(MSG_ENTRY(i), MSG_ENTRY(i+1), (hMsgQue->nNumberMsg-1-i) * hMsgQue->nMsgSize); // Çϳª Áö¿üÀ¸´Ï±î index¸¦ Á¶Á¤.. hMsgQue->nNumberMsg--; i--; nMsgDeleted++; errCnt += (DHL_OS_TakeSemaphore(hMsgQue->Sema4, 0) ? 1 : 0); } if (g_bUseInterruptMasking) DHL_OS_RestoreInterrupts(mask); else DHL_OS_GiveSemaphore(hMsgQue->Mutex); if (errCnt) DHL_OS_Printf("!! MsgQue: count semaphore err %d times\n", errCnt); //DHL_OS_Printf("\t total %d msg deleted\n", nMsgDeleted); return statusOK; } BOOL DMW_SYS_CheckSpecificMsgExist(DMW_MSGQUE *hMsgQue, DMW_FN_MSG_CHECK fnCheck, UINT32 param) { int i; BOOL bExist = FALSE; UINT32 mask = 0; if (fnCheck == NULL) return FALSE; if (g_bUseInterruptMasking) mask = DHL_OS_DisableInterrupts(); else DHL_OS_TakeSemaphore(hMsgQue->Mutex, DHL_TIMEOUT_FOREVER); for (i=0; inNumberMsg; i++) { if (fnCheck(MSG_ENTRY(i), param)) { bExist = TRUE; break; } } if (g_bUseInterruptMasking) DHL_OS_RestoreInterrupts(mask); else DHL_OS_GiveSemaphore(hMsgQue->Mutex); return bExist; } void DMW_SYS_PrintUserMsgs(DMW_MSGQUE *hMsgQue, DMW_FN_MSG_NAME fnName) { int i; char buf[300], *pName; UINT32 mask = 0; if (g_bUseInterruptMasking) mask = DHL_OS_DisableInterrupts(); else DHL_OS_TakeSemaphore(hMsgQue->Mutex, DHL_TIMEOUT_FOREVER); buf[0] = 0; for (i=0; inNumberMsg, 20); i++) { pName = fnName ? MSG_NAME(i,fnName) : MSG_NAME2(i); if (strlen(buf) + strlen(pName) + 10 >= 300) // margin 10 break; sprintf(buf+strlen(buf), "%s ", pName); } if (g_bUseInterruptMasking) DHL_OS_RestoreInterrupts(mask); else DHL_OS_GiveSemaphore(hMsgQue->Mutex); DHL_OS_Printf("MsgQue: %d msgs\n", hMsgQue->nNumberMsg); DHL_OS_Printf(" [ %s]\n", buf); } #if 0 ____Example____() #endif #if 0 1. DMW_MSGQUE ¸Þ¸ð¸® (°ø°£) ÇÒ´ç MsgQue object¸¦ µ¿ÀûÀ¸·Î ÇÒ´çÇÏ´Â ¹æ½ÄÀº ¾Æ´Ï°í ÀÏ´Ü space´Â caller°¡ Á¦°øÇÑ´Ù. (stackÀº ¾ÈµÇ°í, BSS³ª DATA, HEAP »ç¿ëÇØ¾ß ÇÔ) DMW_MSGQUE MsgQueObject, *g_MsgQue = &MsgQueObject; ¶Ç´Â g_pMsgQue = OS_Malloc(sizeof(DMW_MSGQUE)); 2. ¸Þ½ÃÁö ŸÀÔ Á¤ÀÇ ±×´ÙÀ½¿¡ Message·Î »ç¿ëÇÒ structure¸¦ define. typedef struct { int id; ... } MyMsgType; 3. ÃʱâÈ­ // ÃʱâÈ­ DMW_SYS_InitMsgQue(g_MsgQue, sizeof(MyMsgType), 10, (DMW_FN_MSG_NAME) MsgName); ¸Ç µÚÀÇ ÀÎÀÚ´Â debugging¿¡ ¿ëÀÌÇϵµ·Ï °¢ Message¿¡ namingÀ» ÇÏ¿© Ç¥½ÃÇÒ ¶§ »ç¿ëµÈ´Ù. ÇÊ¿ä¾øÀ¸¸é NULLÀ» ÁöÁ¤ÇÏ¸é µÈ´Ù. ¿¹: char *MsgName(MyMsgType *pMsg) { switch (pMsg->id) { case 0 : return "msg_init"; case 1 : return "msg_start"; case 2 : return "msg_resume"; .. } } 4. ¸Þ½ÃÁö Å¥¿¡ ³Ö±â MsgType msg; msg.id = 1; .. DMW_SYS_AddUserMsg(g_MsgQue, &msg); 5. ¸Þ½ÃÁö Å¥¿¡¼­ »©³»±â MsgType msg; DMW_SYS_GetUserMsg(g_MsgQue, &msg, 0); #endif