/*
 * IPRPC - Inter Process Remote Procedure Call
 *
 * Copyright (C) 2012-2013 by Hiroyuki KAJIURA. All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 *
 *     1:Redistributions of source code must retain the above copyright notice, 
 *       this list of conditions and the following disclaimer.
 *     2:Redistributions in binary form must reproduce the above copyright notice, 
 *       this list of conditions and the following disclaimer in the documentation 
 *       and/or other materials provided with the distribution.
 *     3:Neither the name of copyright owner nor the names of its contributors 
 *       may be used to endorse or promote products derived from this software 
 *       without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#define	IPC_STUB_MAIN

#ifdef HAVE_CONFIG_H
#  include "config.h"
#endif

#include	"ipcInfo.h"
#include	"ipcType.h"
#include	"ipcLog.h"
#include	"ipcSyscall.h"
#include	"ipcLib.h"
#include	"rpcFunc.h"
#include	"rpcMsg.h"
#include	"ipcMsg.h"
#include	"ipcShm.h"
#include	"ipcQue.h"
#include	"ipcShmDB.h"
#include	"ipcStub.h"
#include	"ipcMarshal.h"

#define	IPC_STUB_INVALID_SEQ_NUM			(0)

typedef struct {
	uint32_t queId;
	RpcResourceState_t queState;
} IpcStubQueResourceDBEntry_t;

typedef struct {
	RpcTaskID_t taskId;
	RpcTaskAttribute_t taskAttr;
	RpcTaskControl_t tskCntl;
	RpcResourceState_t taskState;
} IpcStubCBTaskResourceDBEntry_t;

#ifdef	USE_MULTICAST_RPC

typedef struct {
	RpcTaskControl_t tskCntl;
	RpcTaskID_t taskId;
	RpcResourceState_t mltcstState;
} IpcStubMltcstResourceDBEntry_t;

#endif	/* USE_MULTICAST_RPC */

typedef struct {
	RpcList_t *stubQueResourceList;
	RpcList_t *stubCBTaskResourceList;
#ifdef	USE_MULTICAST_RPC
	RpcList_t *stubMltcstResourceList;
#endif	/* USE_MULTICAST_RPC */
	RpcMutexID_t mutexId;
	RpcMutexAttribute_t mutexAttr;
} IpcStubResourceDBManage_t;

typedef struct {
	uint32_t queId;
	RpcTaskID_t cbTaskId;
	struct timeval absTime;
	IPC_CallbackFunc_t callbackFunc;
} IpcStubCBInfo_t;

typedef struct {
	IpcFunctionType_t funcType;
	RpcFuncId_t funcId;
	uint32_t seqNum;
	RpcTaskID_t taskId;
	RpcTaskID_t orgTaskId;
	IpcStubCBInfo_t cbInfo;
} IpcStubFuncInfo_t;

#ifdef	USE_MULTICAST_RPC

typedef struct {
	void *outParams;
	uint32_t outParamsSize;
	uint32_t errCode;
	uint32_t seqNum;
	uint32_t dstPid;
} IpcFuncRetVal_t;

typedef struct {
	RpcList_t *funcRetVals;
	uint32_t numOfCall;
	uint32_t numOfCallback;
	uint32_t mltcstFuncId;
	IpcFunctionType_t funcType;
	RpcTaskID_t callTaskId;
	IpcStubMltcstResourceDBEntry_t *mltcstMutex;
	IPC_MultticastCallbackFunc_t callbackFunc;
	uint32_t seqNum;
} IpcMltcstRetCntl_t;

typedef struct {
	RpcList_t *stubMltcstList;
	RpcMutexID_t mutexId;
	RpcMutexAttribute_t mutexAttr;
} IpcStubMltcstCntl_t;

#endif	/* USE_MULTICAST_RPC */

typedef struct {
	RpcList_t *stubFuncDBList;
	RpcMutexID_t mutexId;
	RpcMutexAttribute_t mutexAttr;
} IpcStubDBManage_t;

static IpcStubResourceDBManage_t IpcStubRcsDBManage;
static IpcStubDBManage_t IpcStubDataManage;
#ifdef	USE_MULTICAST_RPC
static IpcStubMltcstCntl_t IpcStubMltcstCntl;
#endif	/* USE_MULTICAST_RPC */

static RpcResult_t IPC_initStubResourceDB(void);
static RpcResult_t IPC_initStubDB(void);

static void *IPC_CBTaskMain(void *arg1);
static RpcResult_t IPC_execCancelFunc(uint32_t funcId,uint32_t seqNum,uint32_t *errCode);

static IpcStubFuncInfo_t *IPC_addStubDBEntry(IpcFunctionType_t funcType,RpcFuncId_t funcId,uint32_t seqNum,RpcTaskID_t taskId,	RpcTaskID_t orgTaskId, uint32_t queId,RpcTaskID_t cbTaskId, struct timeval *absTime,IPC_CallbackFunc_t callbackFunc);
static void IPC_deleteStubDBEntry(IpcStubFuncInfo_t *entry);
static IpcStubFuncInfo_t *IPC_searchStubDBEntryBySeqNum(uint32_t seqNum);
static IpcStubFuncInfo_t *IPC_searchStubDBEntryByOrgTaskId(RpcTaskID_t orgTaskId);
static IpcStubFuncInfo_t *IPC_searchStubDBEntryByCBTaskId(RpcTaskID_t cbTaskId);
static RpcBool_t IPC_compareStubFuncDBBySeqNum(RpcList_t *list,uint32_t seqNum);
#if	__WORDSIZE == 64
static RpcBool_t IPC_compareStubFuncDBByOrgTaskId(RpcList_t *list,uint64_t orgTaskId);
static RpcBool_t IPC_compareStubFuncDBByCBTaskId(RpcList_t *list,uint64_t cbTaskId);
#else	/* __WORDSIZE */
static RpcBool_t IPC_compareStubFuncDBByOrgTaskId(RpcList_t *list,uint32_t orgTaskId);
static RpcBool_t IPC_compareStubFuncDBByCBTaskId(RpcList_t *list,uint32_t cbTaskId);
#endif	/* __WORDSIZE */

static RpcResult_t IPC_allocCBTaskFromStubResourceDB(RpcTaskID_t *taskId,RpcTaskControl_t **tskCntl);
static RpcResult_t IPC_freeCBTaskFromStubResourceDB(RpcTaskID_t taskId);
static IpcStubCBTaskResourceDBEntry_t *IPC_getIdleStubCBTaskResource(void);

static RpcResult_t IPC_allocQueFromStubResourceDB(uint32_t *queId);
static RpcResult_t IPC_freeQueFromStubResourceDB(uint32_t queId);
static IpcStubQueResourceDBEntry_t *IPC_getIdleStubQueResource(void);

static RpcBool_t IPC_compareQueResourceByQueId(RpcList_t *list,uint32_t queId);
static RpcBool_t IPC_compareQueResourceByState(RpcList_t *list,uint32_t state);
#if	__WORDSIZE == 64
static RpcBool_t IPC_compareCBTaskResourceByTaskId(RpcList_t *list,uint64_t taskId);
#else	/* __WORDSIZE */
static RpcBool_t IPC_compareCBTaskResourceByTaskId(RpcList_t *list,uint32_t taskId);
#endif	/* __WORDSIZE */
static RpcBool_t IPC_compareCBTaskResourceByState(RpcList_t *list,uint32_t state);

static RpcResult_t IPC_allocStubCBTaskResource(IpcStubCBTaskResourceDBEntry_t *entry);
static RpcResult_t IPC_allocStubQueResource(IpcStubQueResourceDBEntry_t *entry);

static uint32_t IPC_assignNewSequenceNubmer(void);
static void IPC_cleanStubQueue(uint32_t queId);

#ifdef	USE_MULTICAST_RPC
static RpcResult_t IPC_initStubMltcstCntl(void);
static RpcResult_t IPC_callSyncMulticastFunction(RpcTaskID_t callTaskId,uint32_t mltcstFuncId,void *inParams,uint32_t inParamsSize,uint32_t *numOfCalls,uint32_t *numOfRet,IpcMulticastRetData_t **retData,uint32_t timeOut,uint32_t *errCode);
static RpcResult_t IPC_callAsyncMulticastFunction(RpcTaskID_t callTaskId,uint32_t mltcstFuncId,void *inParams,uint32_t inParamsSize,uint32_t *numOfCalls,uint32_t timeOut,IPC_MultticastCallbackFunc_t mltcstCallback,uint32_t *seqNum,uint32_t *errCode);
static void IPC_mltcstCallback(uint32_t seqNum,void *outData,uint32_t outSize,uint32_t errCode);
static IpcMltcstRetCntl_t *IPC_addStubMltcstCntlEntry(IpcFunctionType_t funcType, uint32_t mltcstFuncId,RpcTaskID_t callTaskId, IpcStubMltcstResourceDBEntry_t *mltcstMutex,IPC_MultticastCallbackFunc_t callbackFunc);
static void IPC_deleteStubMltcstCntlEntry(IpcMltcstRetCntl_t *entry);
static IpcFuncRetVal_t *IPC_searchStubMltcstCntlEntryBySeqNum(uint32_t seqNum,IpcMltcstRetCntl_t **mltcstRetCntl);
static RpcResult_t IPC_allocMltcstFromStubResourceDB(RpcTaskID_t taskId,IpcStubMltcstResourceDBEntry_t **entry);
static RpcResult_t IPC_freeMltcstFromStubResourceDB(RpcTaskID_t taskId);
static IpcStubMltcstResourceDBEntry_t *IPC_getIdleStubMltcstResource(void);
static RpcResult_t IPC_allocStubMltcstResource(IpcStubMltcstResourceDBEntry_t *mEntry);
static RpcBool_t IPC_compareMltcstResourceByState(RpcList_t *list,uint32_t state);
#if	__WORDSIZE == 64
static RpcBool_t IPC_compareMltcstResourceByTaskId(RpcList_t *list,uint64_t taskId);
#else	/* __WORDSIZE */
static RpcBool_t IPC_compareMltcstResourceByTaskId(RpcList_t *list,uint32_t taskId);
#endif	/* __WORDSIZE */
//static RpcBool_t IPC_compareStubMltcstCntlByMltcstFuncId(RpcList_t *list,uint32_t mltcstFuncId);
static RpcBool_t IPC_compareStubMltcstRetValBySeqNum(RpcList_t *list,uint32_t seqNum);
#endif	/* USE_MULTICAST_RPC */

/* ----- Global Functions ----- */

extern RpcResult_t IPC_InitStub(RpcBool_t masterProcess) {
	RpcResult_t ret = RPC_SUCCESS;

#if	0	/* INIT LOG, INIT SHM, INIT SHM DB, INIT EXT PARAM, AND INIT QUE SYSTEM ARE IN MAIN */
	/* INIT LOG SYSTEM */
	if((ret = RPC_LogInit()) != RPC_SUCCESS) {
		return ret;
	}
	if((ret = RpcResult_t RPC_LogSetAll(RPC_LOG_LEVEL_ERROR)) != RPC_SUCCESS) {
		return ret;
	}
	if((ret = RPC_LogSetLevel(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_WARNING)) {
		return ret;
	}
	/* INIT SHM */
	if((ret = IPC_InitSharedMem(masterProcess)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_FATAL, "FATAL ERROR in IPC_InitSharedMem RET:%s;",RPC_LogConvertResultCode(ret));
		return ret;
	}
	if((ret = IPC_AttachSharedMem()) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_FATAL, "FATAL ERROR in IPC_AttachSharedMem RET:%s;",RPC_LogConvertResultCode(ret));
		goto goError0;
	}
	/* INIT SHM DB */
	if((ret = RPC_InitShmDB(masterProcess)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_FATAL, "FATAL ERROR in RPC_InitShmDB RET:%s;",RPC_LogConvertResultCode(ret));
		goto goError1;
	}
	/* INIT MARSHAL */
	if((ret = RPC_initMarshal(masterProcess)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_FATAL, "FATAL ERROR in RPC_initMarshal RET:%s;",RPC_LogConvertResultCode(ret));
		goto goError1;
	}
	/* INIT QUE SYSTEM */
	if((ret = RPC_InitQue(masterProcess,RPC_TRUE)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_FATAL, "FATAL ERROR in RPC_InitQue - EXTERNAL RET:%s;",RPC_LogConvertResultCode(ret));
		goto goError1;
	}
	if((ret = RPC_InitQue(masterProcess,RPC_FALSE)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_FATAL, "FATAL ERROR in RPC_InitQue - INTERNAL RET:%s;",RPC_LogConvertResultCode(ret));
		goto goError1;
	}
#endif	/* 0 */
	if((ret = IPC_initStubResourceDB()) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_FATAL, "FATAL ERROR in IPC_initStubResourceDB RET:%s;",RPC_LogConvertResultCode(ret));
		goto goError2;
	}
	if((ret = IPC_initStubDB()) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_FATAL, "FATAL ERROR in IPC_initStubDB RET:%s;",RPC_LogConvertResultCode(ret));
		goto goError2;		
	}
#ifdef	USE_MULTICAST_RPC
	if((ret = IPC_initStubMltcstCntl()) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_FATAL, "FATAL ERROR in IPC_initStubMltcstCntl RET:%s;",RPC_LogConvertResultCode(ret));
		goto goError2;		
	}
#endif	/* USE_MULTICAST_RPC */
	return ret;

goError2:
	;
#if	0
goError1:
#endif	/* 0 */
	(void)IPC_DettachSharedMem();
#if	0
goError0:
#endif	/* 0 */
	(void)IPC_DestroySharedMem();
	return ret;
}

extern RpcResult_t IPC_CallStubSync(uint32_t funcID, void *inData, uint32_t inSize, void **outData, uint32_t *outSize, uint32_t timeOut, uint32_t *errCode) {
	RpcResult_t ret = RPC_SUCCESS;uint32_t dstProcessId;RpcTaskID_t dstTaskId;uint32_t dstQueId;
	RpcMsgParam_t msgParam;uint32_t srcProcessId;uint32_t srcQueId;uint32_t seqNum;
	RpcMsgId_t msgId;struct timeval absTime;
	IpcStubFuncInfo_t *funcInfo;RpcTaskID_t orgTaskId;
#ifdef	USE_CANCEL_TASK
	int oldState;
#endif	/* USE_CANCEL_TASK */

//	(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_DEBUG1,"IN IPC_CallStubSync PID:0x%x; funcID:0x%x; inData:0x%x; inSize:%d; outData:0x%x; outSize:0x%x; timeOut:%d;",
//		     RPC_GetPid(), funcID, inData, inSize, outData, outSize, timeOut);
	*errCode = RPC_NO_ERROR;
	if((outData == (void**)NULL)||(outSize == (uint32_t*)NULL)||(errCode == (uint32_t*)NULL)) {
		if(inData != (void*)NULL)
			IPC_FreeMarshaledSharedData(inData);
		return RPC_PARAM_ERROR;
	}
#ifdef	USE_CANCEL_TASK
	(void)RPC_SetCancelState(PTHREAD_CANCEL_DISABLE,&oldState);
#endif	/* USE_CANCEL_TASK */
	if(timeOut == 0) {
		timeOut = IPC_STUB_DEFAULT_TIMEOUT;
	}
	if(!RPC_SetTimeout(timeOut,&absTime)) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, " CAN NOT GET CURRENT TIME");
		ret = RPC_SYSCALL_ERROR;
		goto errorOut3;
	}
	if((ret = IPC_SerachProcessIdFromFuncDB(funcID,&dstProcessId)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, " CAN NOT FIND FUNCTION RET:%s;",RPC_LogConvertResultCode(ret));
		*errCode = RPC_ERR_OTHER;
		goto errorOut3;
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_DEBUG2, "  FIND PROCESS ID FROM FUNCID FUNCID:0x%x; PID:0x%x;",funcID,dstProcessId);
	if((ret = IPC_SearchSkeltonDB(dstProcessId,(RpcTaskID_t*)&dstTaskId,&dstQueId)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, " AN NOT FIND SKELTON RET:%s;",RPC_LogConvertResultCode(ret));
		*errCode = RPC_ERR_OTHER;
		goto errorOut3;
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_DEBUG2, "  FIND DESTINATION FROM DST-PROCESS-ID PID:0x%x; dstTaskId:0x%x; dstQueId:0x%x;", dstProcessId, dstTaskId, dstQueId);
	if((ret = IPC_allocQueFromStubResourceDB(&srcQueId)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, " CAN NOT ALLOCATE RESOURCE RET:%s;",RPC_LogConvertResultCode(ret));
		*errCode = RPC_ERR_OTHER;
		goto errorOut3;
	}
	srcProcessId = RPC_GetPid();
	IPC_cleanStubQueue(srcQueId);
	seqNum = IPC_assignNewSequenceNubmer();
	orgTaskId = RPC_TaskSelf();
//	(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_DEBUG2, "  ASSIGN SRC-QUE AND SEQ-NUM PID:0x%x; QUEID:0x%x; SEQ-NUM:0x%x;", srcProcessId, srcQueId, seqNum);
	if((funcInfo = IPC_addStubDBEntry(IPC_BLOCKING_FUNCTION,(RpcFuncId_t)funcID,seqNum,dstTaskId,orgTaskId,srcQueId,(RpcTaskID_t)NULL,&absTime,NULL)) == (IpcStubFuncInfo_t*)NULL) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, " CAN NOT ALLOCATE STUB DB");
		ret = RPC_TIMEOUT_ERROR;
		goto errorOut4;						
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_DEBUG2, "  REGISTER STUB INFO FUNCID:0x%x; SEQ-NUM:0x%x; dstRpcTaskID_t:0x%Lx; orgTaskID:0x%Lx; SRC-QUEID:0x%x;",
//		funcID,seqNum,dstTaskId, orgTaskId,srcQueId);
	if(!RPC_GetRestTimeout(&absTime,&timeOut)) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, " OCCUR TIMEOUT");
		ret = RPC_TIMEOUT_ERROR;
		*errCode = RPC_ERR_ETIMEDOUT;
		goto errorOut5;				
	}
	IPC_SetMsgParam(&msgParam,funcID,srcProcessId,srcQueId,seqNum,timeOut,inData);
//	(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_DEBUG2, "  PUT MSG TO DST-PID:0x%x; DST-QUEID:0x%x; MSG:0x%x;",
//		dstProcessId,dstQueId,IPC_MSG_ID_FUNCTION_REQUEST);
	if((ret = IPC_PutMsgToExtQue(dstQueId,IPC_MSG_ID_FUNCTION_REQUEST,&msgParam,timeOut)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, " CAN NOT SEND REQUEST MSG RET:%s;",RPC_LogConvertResultCode(ret));
		goto errorOut5;
	}
	if(!RPC_GetRestTimeout(&absTime,&timeOut)) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, " OCCUR TIMEOUT");
		ret = RPC_TIMEOUT_ERROR;
		*errCode = RPC_ERR_ETIMEDOUT;
		goto errorOut1;			
	}
	for(;;) {
		if((ret = IPC_GetMsgFromExtQue(srcQueId,&msgId,&msgParam,timeOut)) != RPC_SUCCESS) {
			(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, " CAN NOT RECEIVE MSG in IPC_CallStubSync RET:%s;",RPC_LogConvertResultCode(ret));
			if(ret == RPC_TIMEOUT_ERROR)
				*errCode = RPC_ERR_ETIMEDOUT;
			else
				*errCode = RPC_ERR_OTHER;
			goto errorOut1;
		}
		if(msgParam.u.msgParam.seqNum != seqNum) {
			(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, "RECEIVE IREGAL SEQ-NUM MESSAGAE");
		}
		else {
//			(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_DEBUG2,"  RECEIVE MSG IN STUB-TASK PID:0x%x; QUEID:0x%x; ID:0x%x; funcId:0x%x; srcPid:0x%x; srcQueId:0x%x, seqNum:0x%x; extData:0x%x;",
//				RPC_GetPid(),srcQueId, msgId, msgParam.u.msgParam.funcId, msgParam.u.msgParam.srcPid, msgParam.u.msgParam.srcQueId, msgParam.u.msgParam.seqNum, msgParam.u.msgParam.extData);
			switch(msgId) {
			case IPC_MSG_ID_FUNCTION_ACCEPT:
//				(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_DEBUG1, "RECEIVE ACCEPT MESSAGAE");
				if(msgParam.u.msgParam.extData != (uint32_t)RPC_SUCCESS) {
					(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, "RECEIVE IREGAL ACCEPT MESSAGAE");
					*errCode = msgParam.u.msgParam.extData;
					ret = RPC_CAN_NOT_EXEC;
					goto errorOut2;				
				}
				break;
			case IPC_MSG_ID_FUNCTION_REJECT:
//				(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_DEBUG1, "RECEIVE REJECT MESSAGAE");
				*errCode = msgParam.u.msgParam.extData;
				ret = RPC_CAN_NOT_EXEC;
				goto errorOut2;
			case IPC_MSG_ID_FUNCTION_RESPONSE:
//				(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_DEBUG1, "RECEIVE RESPONSE MESSAGAE");
				*outData = msgParam.u.msgParam.extParam;
				*outSize = IPC_GetMarshaledDataSize(msgParam.u.msgParam.extParam);
				*errCode = msgParam.u.msgParam.extData;
				goto goOut;
			default:
				(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_FATAL, " RECEIVE NOT ACCEPTABLE MESSAGE:%s;",RPC_LogConvertResultCode(ret));
				break;
			}
		}
		if(msgParam.u.msgParam.extParam != (void*)NULL) {
			IPC_FreeMarshaledSharedData(msgParam.u.msgParam.extParam);	
		}
		if(!RPC_GetRestTimeout(&absTime,&timeOut)) {
			(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, " OCCUR TIMEOUT");
			ret = RPC_TIMEOUT_ERROR;
			*errCode = RPC_ERR_ETIMEDOUT;
			goto errorOut1;				
		}
	}
goOut:
	(void)IPC_freeQueFromStubResourceDB(srcQueId);
	IPC_deleteStubDBEntry(funcInfo);
#ifdef	USE_CANCEL_TASK
	(void)RPC_SetCancelState(oldState,(int*)NULL);
#endif	/* USE_CANCEL_TASK */
//	(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_DEBUG1,"OUT IPC_CallStubSync PID:0x%x; funcID:0x%x; outData:0x%x; outSize:%d;",
//		RPC_GetPid(), funcID, *outData, *outSize);
	return ret;

errorOut5:
	IPC_deleteStubDBEntry(funcInfo);
errorOut4:
	*outData = (void*)NULL;*outSize = 0;
	(void)IPC_freeQueFromStubResourceDB(srcQueId);
errorOut3:
	if(inData != (void*)NULL)
		IPC_FreeMarshaledSharedData(inData);
#ifdef	USE_CANCEL_TASK
	(void)RPC_SetCancelState(oldState,(int*)NULL);
#endif	/* USE_CANCEL_TASK */
	return ret;

errorOut2:
	if(msgParam.u.msgParam.extParam != (void*)NULL) {
		IPC_FreeMarshaledSharedData(msgParam.u.msgParam.extParam);	
	}
errorOut1:
	*outData = (void*)NULL;*outSize = 0;
	(void)IPC_freeQueFromStubResourceDB(srcQueId);
	IPC_deleteStubDBEntry(funcInfo);
#ifdef	USE_CANCEL_TASK
	(void)RPC_SetCancelState(oldState,(int*)NULL);
#endif	/* USE_CANCEL_TASK */
	return ret;
}

extern RpcResult_t IPC_CallStubAsync(uint32_t funcID, void *inData, uint32_t inSize, uint32_t timeOut, IPC_CallbackFunc_t callbackFunc, uint32_t *seqNum,uint32_t *errCode) {
	RpcResult_t ret = RPC_SUCCESS;uint32_t dstProcessId;RpcTaskID_t dstTaskId;uint32_t dstQueId;
	RpcMsgParam_t msgParam;uint32_t srcProcessId;uint32_t srcQueId;
	RpcMsgId_t msgId;struct timeval absTime;
	IpcStubFuncInfo_t *funcInfo;RpcTaskID_t orgTaskId;
	RpcTaskID_t cbTaskId;RpcTaskControl_t *tskCntl;
#ifdef	USE_CANCEL_TASK
	int oldState;
#endif	/* USE_CANCEL_TASK */

//	(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_DEBUG1,"IN IPC_CallStubAsync PID:0x%x; funcID:0x%x;, inData:0x%x; inSize:%d; timeOut:%d; callbackFunc:0x%x;",
//		     RPC_GetPid(), funcID, inData, inSize, timeOut, callbackFunc);
	*errCode = RPC_NO_ERROR;
	if((callbackFunc == NULL)||(seqNum == (uint32_t*)NULL)||(errCode == (uint32_t*)NULL)) {
		if(inData != (void*)NULL)
			IPC_FreeMarshaledSharedData(inData);
		return RPC_PARAM_ERROR;
	}
#ifdef	USE_CANCEL_TASK
	(void)RPC_SetCancelState(PTHREAD_CANCEL_DISABLE,&oldState);
#endif	/* USE_CANCEL_TASK */
	if(timeOut == 0) {
		timeOut = IPC_STUB_DEFAULT_TIMEOUT;
	}
	if(!RPC_SetTimeout(timeOut,&absTime)) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, " CAN NOT GET CURRENT TIME");
		ret = RPC_SYSCALL_ERROR;
		goto errorOut3;
	}
	if((ret = IPC_SerachProcessIdFromFuncDB(funcID,&dstProcessId)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, " CAN NOT FIND FUNCTION RET:%s;",RPC_LogConvertResultCode(ret));
		*errCode = RPC_ERR_OTHER;
		goto errorOut3;
	}
	if((ret = IPC_SearchSkeltonDB(dstProcessId,(RpcTaskID_t*)&dstTaskId,&dstQueId)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, " CAN NOT FIND SKELTON RET:%s;",RPC_LogConvertResultCode(ret));
		*errCode = RPC_ERR_OTHER;
		goto errorOut3;
	}
	if((ret = IPC_allocQueFromStubResourceDB(&srcQueId)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, " CAN NOT ALLOCATE RESOURCE RET:%s;",RPC_LogConvertResultCode(ret));
		*errCode = RPC_ERR_OTHER;
		goto errorOut3;
	}
	srcProcessId = RPC_GetPid();
	IPC_cleanStubQueue(srcQueId);
	*seqNum = IPC_assignNewSequenceNubmer();
	orgTaskId = RPC_TaskSelf();
	if((ret = IPC_allocCBTaskFromStubResourceDB(&cbTaskId,&tskCntl)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, "RECEIVE CAN NOT ALLOCATE CALL-BACK TASK");
		goto errorOut4;
	}
	if((funcInfo = IPC_addStubDBEntry(IPC_NONBLOCKING_FUNCTION,(RpcFuncId_t)funcID,*seqNum,dstTaskId,orgTaskId,srcQueId,cbTaskId,&absTime,callbackFunc)) == (IpcStubFuncInfo_t*)NULL) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, " CAN NOT ALLOCATE STUB DB");
		ret = RPC_TIMEOUT_ERROR;
		goto errorOut5;						
	}
	if(!RPC_GetRestTimeout(&absTime,&timeOut)) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, " OCCUR TIMEOUT");
		ret = RPC_TIMEOUT_ERROR;
		*errCode = RPC_ERR_ETIMEDOUT;
		goto errorOut6;				
	}
	IPC_SetMsgParam(&msgParam,funcID,srcProcessId,srcQueId,*seqNum,timeOut,inData);
	if((ret = IPC_PutMsgToExtQue(dstQueId,IPC_MSG_ID_FUNCTION_REQUEST,&msgParam,timeOut)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, " CAN NOT SEND REQUEST MSG RET:%s;",RPC_LogConvertResultCode(ret));
		goto errorOut6;
	}
	if(!RPC_GetRestTimeout(&absTime,&timeOut)) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, " OCCUR TIMEOUT");
		ret = RPC_TIMEOUT_ERROR;
		*errCode = RPC_ERR_ETIMEDOUT;
		goto errorOut1;			
	}
	for(;;) {
		if((ret = IPC_GetMsgFromExtQue(srcQueId,&msgId,&msgParam,timeOut)) != RPC_SUCCESS) {
			(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, " CAN NOT RECEIVE MSG in IPC_CallStubAsync RET:%s;",RPC_LogConvertResultCode(ret));		
			if(ret == RPC_TIMEOUT_ERROR)
				*errCode = RPC_ERR_ETIMEDOUT;
			else
				*errCode = RPC_ERR_OTHER;
			goto errorOut1;
		}
		if(msgParam.u.msgParam.seqNum != *seqNum) {
			(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, "RECEIVE IREGAL SEQ-NUM MESSAGAE");
		}
		else {
//			(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_DEBUG2,"  RECEIVE MSG IN STUB-TASK PID:0x%x; QUEID:0x%x; ID:0x%x; funcId:0x%x; srcPid:0x%x; srcQueId:0x%x, seqNum:0x%x; extData:0x%x;",
//				RPC_GetPid(), srcQueId, msgId, msgParam.u.msgParam.funcId, msgParam.u.msgParam.srcPid, msgParam.u.msgParam.srcQueId, msgParam.u.msgParam.seqNum, msgParam.u.msgParam.extData);
			switch(msgId) {
			case IPC_MSG_ID_FUNCTION_ACCEPT:
//				(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_DEBUG1, "RECEIVE ACCEPT MESSAGAE");
				if(msgParam.u.msgParam.extData != (uint32_t)RPC_SUCCESS) {
					(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, "RECEIVE IREGAL ACCEPT MESSAGAE");
					*errCode = msgParam.u.msgParam.extData;
					ret = RPC_CAN_NOT_EXEC;
					goto errorOut2;
				}
				if((ret = RPC_TaskControlSignal(tskCntl)) != RPC_SUCCESS)
					goto errorOut2;
				goto goOut;
			case IPC_MSG_ID_FUNCTION_REJECT:
//				(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_DEBUG1, "RECEIVE REJECT MESSAGAE");
				*errCode = msgParam.u.msgParam.extData;
				ret = RPC_CAN_NOT_EXEC;
				goto errorOut2;
			default:
				(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_FATAL, " RECEIVE NOT ACCEPTABLE MESSAGE:%s;",RPC_LogConvertResultCode(ret));
				break;
			}
		}
		if(msgParam.u.msgParam.extParam != (void*)NULL) {
			IPC_FreeMarshaledSharedData(msgParam.u.msgParam.extParam);
		}
		if(!RPC_GetRestTimeout(&absTime,&timeOut)) {
			(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, " OCCUR TIMEOUT");
			ret = RPC_TIMEOUT_ERROR;
			*errCode = RPC_ERR_ETIMEDOUT;
			goto errorOut1;				
		}
	}
goOut:
	if(msgParam.u.msgParam.extParam != (void*)NULL) {
		IPC_FreeMarshaledSharedData(msgParam.u.msgParam.extParam);
	}
#ifdef	USE_CANCEL_TASK
	(void)RPC_SetCancelState(oldState,(int*)NULL);
#endif	/* USE_CANCEL_TASK */
//	(void)IPC_freeQueFromStubResourceDB(srcQueId);
//	IPC_deleteStubDBEntry(funcInfo);
//	(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_DEBUG1,"OUT IPC_CallStubAsync PID:0x%x; funcID:0x%x;",
//		RPC_GetPid(), funcID);
	return ret;

errorOut6:
	IPC_deleteStubDBEntry(funcInfo);
errorOut5:
	(void)IPC_freeCBTaskFromStubResourceDB(cbTaskId);
errorOut4:
	(void)IPC_freeQueFromStubResourceDB(srcQueId);
errorOut3:
	*seqNum = 0;
	if(inData != (void*)NULL)
		IPC_FreeMarshaledSharedData(inData);
#ifdef	USE_CANCEL_TASK
	(void)RPC_SetCancelState(oldState,(int*)NULL);
#endif	/* USE_CANCEL_TASK */
	return ret;

errorOut2:
	if(msgParam.u.msgParam.extParam != (void*)NULL) {
		IPC_FreeMarshaledSharedData(msgParam.u.msgParam.extParam);	
	}
errorOut1:
	*seqNum = 0;
	(void)IPC_freeQueFromStubResourceDB(srcQueId);
	(void)IPC_freeCBTaskFromStubResourceDB(cbTaskId);
	IPC_deleteStubDBEntry(funcInfo);
#ifdef	USE_CANCEL_TASK
	(void)RPC_SetCancelState(oldState,(int*)NULL);
#endif	/* USE_CANCEL_TASK */
	return ret;
}

extern RpcResult_t IPC_StubSyncCancel(RpcTaskID_t taskId,uint32_t *errCode) {
	uint32_t seqNum;IpcStubFuncInfo_t *funcInfo;uint32_t funcId;
	RpcResult_t ret;
#ifdef	USE_CANCEL_TASK
	int oldState;
#endif	/* USE_CANCEL_TASK */

	if((funcInfo = IPC_searchStubDBEntryByOrgTaskId(taskId)) == (IpcStubFuncInfo_t*)NULL) {
		*errCode = RPC_ERR_OTHER;
		return RPC_PARAM_ERROR;
	}
	seqNum = funcInfo->seqNum;
	funcId = funcInfo->funcId;
#ifdef	USE_CANCEL_TASK
	(void)RPC_SetCancelState(PTHREAD_CANCEL_DISABLE,&oldState);
#endif	/* USE_CANCEL_TASK */
	ret = IPC_execCancelFunc(funcId,seqNum,errCode);
#ifdef	USE_CANCEL_TASK
	(void)RPC_SetCancelState(oldState,(int*)NULL);
#endif	/* USE_CANCEL_TASK */
	return ret;
}

extern RpcResult_t IPC_StbuAsyncCancel(uint32_t seqNum,uint32_t *errCode) {
	IpcStubFuncInfo_t *funcInfo;uint32_t funcId;RpcResult_t ret;
#ifdef	USE_CANCEL_TASK
	int oldState;
#endif	/* USE_CANCEL_TASK */

	if((funcInfo = IPC_searchStubDBEntryBySeqNum(seqNum)) == (IpcStubFuncInfo_t*)NULL) {
		*errCode = RPC_ERR_OTHER;
		return RPC_PARAM_ERROR;
	}
	seqNum = funcInfo->seqNum;
	funcId = funcInfo->funcId;
#ifdef	USE_CANCEL_TASK
	(void)RPC_SetCancelState(PTHREAD_CANCEL_DISABLE,&oldState);
#endif	/* USE_CANCEL_TASK */
	ret = IPC_execCancelFunc(funcId,seqNum,errCode);
#ifdef	USE_CANCEL_TASK
	(void)RPC_SetCancelState(oldState,(int*)NULL);
#endif	/* USE_CANCEL_TASK */
	return ret;
}

#ifdef	USE_MULTICAST_RPC
extern RpcResult_t IPC_CallStubSyncMulticast(uint32_t mltcstFuncId,void *inParams,uint32_t inParamsSize,uint32_t *numOfRet,IpcMulticastRetData_t **retData,uint32_t timeOut,uint32_t *errCode) {
	RpcTaskID_t taskId;uint32_t numOfCalls = 0;RpcResult_t ret;
#ifdef	USE_CANCEL_TASK
	int oldState;
#endif	/* USE_CANCEL_TASK */

	if((retData == (IpcMulticastRetData_t**)NULL)||(numOfRet == (uint32_t*)NULL)||(errCode == (uint32_t*)NULL)) {
		if(inParams != (void*)NULL)
			IPC_FreeMarshaledSharedData(inParams);
		return RPC_PARAM_ERROR;
	}
	if(timeOut == 0) {
		timeOut = IPC_STUB_DEFAULT_TIMEOUT;
	}
	taskId = RPC_TaskSelf();
#ifdef	USE_CANCEL_TASK
	(void)RPC_SetCancelState(PTHREAD_CANCEL_DISABLE,&oldState);
#endif	/* USE_CANCEL_TASK */
	ret = IPC_callSyncMulticastFunction(taskId,mltcstFuncId,inParams, inParamsSize, &numOfCalls,numOfRet,retData,timeOut,errCode);
#ifdef	USE_CANCEL_TASK
	(void)RPC_SetCancelState(oldState,(int*)NULL);
#endif	/* USE_CANCEL_TASK */
	return ret;
}

extern RpcResult_t IPC_CallStubAsyncMulticast(uint32_t mltcstFuncId,void *inParams,uint32_t inParamsSize,uint32_t timeOut,IPC_MultticastCallbackFunc_t mltcstCallback, uint32_t *seqNum, uint32_t *errCode) {
	RpcTaskID_t taskId;uint32_t numOfCalls = 0;RpcResult_t ret;
#ifdef	USE_CANCEL_TASK
	int oldState;
#endif	/* USE_CANCEL_TASK */

	if((mltcstCallback == NULL)||(seqNum == (uint32_t*)NULL)||(errCode == (uint32_t*)NULL)) {
		if(inParams != (void*)NULL)
			IPC_FreeMarshaledSharedData(inParams);
		return RPC_PARAM_ERROR;
	}
	if(timeOut == 0) {
		timeOut = IPC_STUB_DEFAULT_TIMEOUT;
	}
	taskId = RPC_TaskSelf();
#ifdef	USE_CANCEL_TASK
	(void)RPC_SetCancelState(PTHREAD_CANCEL_DISABLE,&oldState);
#endif	/* USE_CANCEL_TASK */
	ret = IPC_callAsyncMulticastFunction(taskId,mltcstFuncId,inParams,inParamsSize,&numOfCalls,timeOut, mltcstCallback,seqNum,errCode);
#ifdef	USE_CANCEL_TASK
	(void)RPC_SetCancelState(oldState,(int*)NULL);
#endif	/* USE_CANCEL_TASK */
	return ret;
}

extern void IPC_FreeMulticastOutParams(IpcMulticastRetData_t *retData) {
	if(retData != (IpcMulticastRetData_t*)NULL)
		RPC_FreeMem((void*)retData);
}

#endif	/* USE_MULTICAST_RPC */

/* ----- Internal Functions ----- */

static RpcResult_t IPC_initStubResourceDB(void) {
	int i;RpcResult_t ret;IpcStubQueResourceDBEntry_t *qEntry;IpcStubCBTaskResourceDBEntry_t *tEntry;
#ifdef	USE_MULTICAST_RPC
	IpcStubMltcstResourceDBEntry_t *mEntry;
#endif	/* USE_MULTICAST_RPC */

//	(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_DEBUG2,"IN IPC_initStubResourceDB PID:0x%x;",RPC_GetPid());
	memset(&IpcStubRcsDBManage,0,sizeof(IpcStubResourceDBManage_t));
	if(RPC_MutexAttrInit(&(IpcStubRcsDBManage.mutexAttr)) != RPC_SUCCESS) {
		return RPC_FATAL_ERROR;
	}
#ifdef	_LINUX_
	if(RPC_MutexAttrSetType(&(IpcStubRcsDBManage.mutexAttr), PTHREAD_MUTEX_ADAPTIVE_NP) != RPC_SUCCESS) {
		return RPC_FATAL_ERROR;
	}
#else	/* _LINUX_ */
	if(RPC_MutexAttrSetType(&(IpcStubRcsDBManage.mutexAttr), PTHREAD_MUTEX_RECURSIVE) != RPC_SUCCESS) {
		return RPC_FATAL_ERROR;
	}
#endif	/* _LINUX_ */
	if(RPC_MutexAttrSetPshared(&(IpcStubRcsDBManage.mutexAttr), PTHREAD_PROCESS_PRIVATE) != RPC_SUCCESS) {
		return RPC_FATAL_ERROR;
	}
	if(RPC_InitMutex(&(IpcStubRcsDBManage.mutexId),&(IpcStubRcsDBManage.mutexAttr)) != RPC_SUCCESS) {
		return RPC_FATAL_ERROR;
	}
	for(i = 0;i < IPC_STUB_START_NUM_OF_QUE_RESOURCE;i++) {
		if((qEntry = (IpcStubQueResourceDBEntry_t*)RPC_AllocListData(&(IpcStubRcsDBManage.stubQueResourceList),sizeof(IpcStubQueResourceDBEntry_t),0,RPC_LclAllocMemWrapper,RPC_LclFreeMemWrapper)) == (IpcStubQueResourceDBEntry_t*)NULL) {
			return RPC_NO_MORE_RESOURCE;
		}
//		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_DEBUG3,"  ALLOCATED LIST DATA FOR STUB QUE  LIST-TOP:0x%x;",IpcStubRcsDBManage.stubQueResourceList);
		if((ret = IPC_allocStubQueResource(qEntry)) != RPC_SUCCESS) {
			return ret;
		}
	}
	for(i = 0;i < IPC_STUB_START_NUM_OF_CB_TASK_RESOURCE;i++) {
		if((tEntry = (IpcStubCBTaskResourceDBEntry_t*)RPC_AllocListData(&(IpcStubRcsDBManage.stubCBTaskResourceList),sizeof(IpcStubCBTaskResourceDBEntry_t),0,RPC_LclAllocMemWrapper,RPC_LclFreeMemWrapper)) == (IpcStubCBTaskResourceDBEntry_t*)NULL) {
			return RPC_NO_MORE_RESOURCE;
		}
//		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_DEBUG3,"  ALLOCATED LIST DATA FOR STUB CB LIST-TOP:0x%x;",IpcStubRcsDBManage.stubCBTaskResourceList);
		if((ret = IPC_allocStubCBTaskResource(tEntry)) != RPC_SUCCESS) {
			return ret;
		}
	}
#ifdef	USE_MULTICAST_RPC
	for(i = 0;i < IPC_STUB_START_NUM_OF_MLTCST_RESOURCE;i++) {
		if((mEntry = (IpcStubMltcstResourceDBEntry_t*)RPC_AllocListData(&(IpcStubRcsDBManage.stubMltcstResourceList),sizeof(IpcStubMltcstResourceDBEntry_t),0,RPC_LclAllocMemWrapper,RPC_LclFreeMemWrapper)) == (IpcStubMltcstResourceDBEntry_t*)NULL) {
			return RPC_NO_MORE_RESOURCE;
		}
//		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_DEBUG3,"  ALLOCATED LIST DATA FOR STUB MLTCST RCS LIST-TOP:0x%x;",IpcStubRcsDBManage.stubMltcstResourceList);
		if((ret = IPC_allocStubMltcstResource(mEntry)) != RPC_SUCCESS) {
			return ret;
		}
	}
#endif	/* USE_MULTICAST_RPC */
//	(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_DEBUG2,"OUT IPC_initStubResourceDB PID:0x%x;",RPC_GetPid());
	return RPC_SUCCESS;
}

static RpcResult_t IPC_initStubDB(void) {
//	(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_DEBUG1,"IN IPC_initStubDB PID:0x%x;",RPC_GetPid());
	memset(&IpcStubDataManage,0,sizeof(IpcStubDBManage_t));
	if(RPC_MutexAttrInit(&(IpcStubDataManage.mutexAttr)) != RPC_SUCCESS) {
		return RPC_FATAL_ERROR;
	}
#ifdef	_LINUX_
	if(RPC_MutexAttrSetType(&(IpcStubDataManage.mutexAttr), PTHREAD_MUTEX_ADAPTIVE_NP) != RPC_SUCCESS) {
		return RPC_FATAL_ERROR;
	}
#else	/* _LINUX_ */
	if(RPC_MutexAttrSetType(&(IpcStubDataManage.mutexAttr), PTHREAD_MUTEX_RECURSIVE) != RPC_SUCCESS) {
		return RPC_FATAL_ERROR;
	}
#endif	/* _LINUX_ */
	if(RPC_MutexAttrSetPshared(&(IpcStubDataManage.mutexAttr), PTHREAD_PROCESS_PRIVATE) != RPC_SUCCESS) {
		return RPC_FATAL_ERROR;
	}
	if(RPC_InitMutex(&(IpcStubDataManage.mutexId),&(IpcStubDataManage.mutexAttr)) != RPC_SUCCESS) {
		return RPC_FATAL_ERROR;
	}
	IpcStubDataManage.stubFuncDBList = (RpcList_t*)NULL;
//	(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_DEBUG1,"OUT IPC_initStubDB PID:0x%x;", RPC_GetPid());
	return RPC_SUCCESS;
}

static void *IPC_CBTaskMain(void *arg1) {
	RpcTaskControl_t *tskCntl;RpcTaskID_t myTaskId;
	RpcResult_t ret;IpcStubFuncInfo_t *stubInfo;uint32_t errCode;
	void *outData;uint32_t outSize;uint32_t seqNum;
	uint32_t msgId;RpcMsgParam_t msgParam;//uint32_t pid;
	uint32_t restTimeout;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_DEBUG1,"IN IPC_CBTaskMain PID:0x%x; arg1:0x%x;",RPC_GetPid(),arg1);
//	pid = (uint32_t)RPC_GetPid();
	(void)RPC_SetCancelState(PTHREAD_CANCEL_DISABLE,(int*)NULL);
	(void)RPC_SetCancelType(PTHREAD_CANCEL_DEFERRED ,NULL);
	tskCntl = (RpcTaskControl_t*)(arg1);
	myTaskId = RPC_TaskSelf();
	for(;;) {
		if((ret = RPC_TaskControlWait(tskCntl)) != RPC_SUCCESS)
			continue;
//		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_DEBUG2,"  WAKE UP TASK IN STUB-CB-TASK PID:0x%Lx; TaskId:0x%Lx; TaskCntl:0x%Lx;",RPC_GetPid(),myTaskId,tskCntl);
		if((stubInfo = IPC_searchStubDBEntryByCBTaskId(myTaskId)) == (IpcStubFuncInfo_t*)NULL) {
			(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_FATAL, " ERROR in IPC_searchStubDBEntryByCBTaskId");
			continue;
		}
		if((stubInfo->funcType != IPC_NONBLOCKING_FUNCTION)||(stubInfo->cbInfo.callbackFunc == NULL)) {
			(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_FATAL, " ERROR in NOT NONBLOCKING FUNC OR NOT SET CALLBACK FUNC");
			continue;			
		}
		if(!RPC_GetRestTimeout(&(stubInfo->cbInfo.absTime),&restTimeout)) {
			(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_FATAL, " OCCUR TIMEOUT");
			errCode = RPC_ERR_ETIMEDOUT;
			stubInfo->cbInfo.callbackFunc(stubInfo->seqNum,(void*)NULL,0,errCode);
			goto goOut;
		}
		errCode = RPC_NO_ERROR;
		for(;;) {
			if((ret = IPC_GetMsgFromExtQue(stubInfo->cbInfo.queId,&msgId,&msgParam,restTimeout)) != RPC_SUCCESS) {
				(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, " CAN NOT RECEIVE MSG in IPC_CBTaskMain RET:%s;",RPC_LogConvertResultCode(ret));
				if(ret == RPC_TIMEOUT_ERROR)
					errCode = RPC_ERR_ETIMEDOUT;
				else
					errCode = RPC_ERR_OTHER;
				stubInfo->cbInfo.callbackFunc(stubInfo->seqNum,(void*)NULL,0,errCode);
				goto goOut;
			}
			if(msgParam.u.msgParam.seqNum != stubInfo->seqNum) {
				(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, "RECEIVE IREGAL SEQ-NUM MESSAGAE");
			}
			else {
//				(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_DEBUG2,"  RECEIVE MSG IN STUB-CB-TASK PID:0x%x; QUEID:0x%x; ID:0x%x; funcId:0x%x; srcPid:0x%x; srcQueId:0x%x, seqNum:0x%x; extData:0x%x;",
//					RPC_GetPid(), stubInfo->cbInfo.queId, msgId, msgParam.u.msgParam.funcId, msgParam.u.msgParam.srcPid, msgParam.u.msgParam.srcQueId, msgParam.u.msgParam.seqNum, msgParam.u.msgParam.extData);
				switch(msgId) {
				case IPC_MSG_ID_FUNCTION_RESPONSE:
//					(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_DEBUG1, "RECEIVE RESPONSE MESSAGAE");
					seqNum = msgParam.u.msgParam.seqNum;
					outData = msgParam.u.msgParam.extParam;
					outSize = IPC_GetMarshaledDataSize(msgParam.u.msgParam.extParam);
					errCode = msgParam.u.msgParam.extData;
					stubInfo->cbInfo.callbackFunc(seqNum,outData,outSize,errCode);
					goto goOut;
				default:
					(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_FATAL, " RECEIVE NOT ACCEPTABLE MESSAGE:%s;",RPC_LogConvertResultCode(ret));
					break;
				}
			}
			if(msgParam.u.msgParam.extParam != (void*)NULL) {
				IPC_FreeMarshaledSharedData(msgParam.u.msgParam.extParam);
			}
			if(!RPC_GetRestTimeout(&(stubInfo->cbInfo.absTime),&restTimeout)) {
				(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_FATAL, " OCCUR TIMEOUT");
				errCode = RPC_ERR_ETIMEDOUT;
				stubInfo->cbInfo.callbackFunc(stubInfo->seqNum,(void*)NULL,0,errCode);
				goto goOut;
			}
		}
goOut:
//		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_DEBUG1,"END WORK IN IPC_CBTaskMain PID:0x%x;",RPC_GetPid());
		(void)IPC_freeQueFromStubResourceDB(stubInfo->cbInfo.queId);
		IPC_deleteStubDBEntry(stubInfo);
		(void)IPC_freeCBTaskFromStubResourceDB(myTaskId);
	}
	return (void*)NULL;
}

static RpcResult_t IPC_execCancelFunc(uint32_t funcId,uint32_t seqNum,uint32_t *errCode) {
	RpcResult_t ret = RPC_SUCCESS;RpcMsgParam_t msgParam;uint32_t srcProcessId;uint32_t srcQueId;
	RpcMsgId_t msgId;uint32_t dstProcessId;RpcTaskID_t dstTaskId;uint32_t dstQueId;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_DEBUG1,"IN IPC_execCancelFunc PID:0x%x; funcId:0x%x; seqNum:0x%x;",RPC_GetPid(),funcId,seqNum);
	if((ret = IPC_SerachProcessIdFromFuncDB(funcId,&dstProcessId)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, " CAN NOT FIND FUNCTION RET:%s;",RPC_LogConvertResultCode(ret));
		*errCode = RPC_ERR_OTHER;
		return RPC_PARAM_ERROR;
	}
	if((ret = IPC_SearchSkeltonDB(dstProcessId,&dstTaskId,&dstQueId)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, " CAN NOT FIND SKELTON RET:%s;",RPC_LogConvertResultCode(ret));
		*errCode = RPC_ERR_OTHER;
		return RPC_PARAM_ERROR;
	}
	if((ret = IPC_allocQueFromStubResourceDB(&srcQueId)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, " CAN NOT ALLOCATE RESOURCE RET:%s;",RPC_LogConvertResultCode(ret));
		*errCode = RPC_ERR_OTHER;
		return ret;
	}
	srcProcessId = RPC_GetPid();
	IPC_cleanStubQueue(srcQueId);
	IPC_SetMsgParam(&msgParam,funcId,srcProcessId,srcQueId,seqNum,0,(void*)NULL);
	if((ret = IPC_PutMsgToExtQue(dstQueId,IPC_MSG_ID_CANCEL_REQUEST,&msgParam,IPC_MSG_QUE_WAIT_FOREVER)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, " CAN NOT SEND REQUEST MSG RET:%s;",RPC_LogConvertResultCode(ret));
		(void)IPC_freeQueFromStubResourceDB(srcQueId);
		*errCode = RPC_ERR_OTHER;
		return ret;
	}
	for(;;) {
		if((ret = IPC_GetMsgFromExtQue(srcQueId,&msgId,&msgParam,IPC_MSG_QUE_WAIT_FOREVER)) != RPC_SUCCESS) {
			(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, " CAN NOT RECEIVE MSG RET:%s;",RPC_LogConvertResultCode(ret));		
			*errCode = RPC_ERR_OTHER;
			goto errorOut1;
		}
		if(msgParam.u.msgParam.seqNum != seqNum) {
			(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, "RECEIVE IREGAL SEQ-NUM MESSAGAE");
		}
		else {
			switch(msgId) {
			case IPC_MSG_ID_CANCEL_ACCEPT:
//				(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_DEBUG2, "RECEIVE CANCEL ACCEPT MESSAGAE");
				if(msgParam.u.msgParam.extData != (uint32_t)RPC_SUCCESS) {
					(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_ERROR, "RECEIVE IREGAL ACCEPT MESSAGAE");
					*errCode = msgParam.u.msgParam.extData;
					ret = RPC_CAN_NOT_EXEC;
					goto errorOut2;
				}
				*errCode = RPC_NO_ERROR;
				goto goOut;
			case IPC_MSG_ID_CANCEL_REJECT:
//				(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_DEBUG2, "RECEIVE CANCEL REJECT MESSAGAE");
				*errCode = msgParam.u.msgParam.extData;
				ret = RPC_CAN_NOT_EXEC;
				goto errorOut2;
			default:
				(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_FATAL, " RECEIVE NOT ACCEPTABLE MESSAGE:%s;",RPC_LogConvertResultCode(ret));
				break;
			}
			if(msgParam.u.msgParam.extParam != (void*)NULL) {
				IPC_FreeMarshaledSharedData(msgParam.u.msgParam.extParam);	
			}
		}
	}
goOut:
	(void)IPC_freeQueFromStubResourceDB(srcQueId);
//	(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_DEBUG1,"OUT IPC_execCancelFunc PID:0x%x;",RPC_GetPid());
	return ret;

errorOut2:
	if(msgParam.u.msgParam.extParam != (void*)NULL) {
		IPC_FreeMarshaledSharedData(msgParam.u.msgParam.extParam);	
	}
errorOut1:
	(void)IPC_freeQueFromStubResourceDB(srcQueId);
	return ret;
}

static IpcStubFuncInfo_t *IPC_addStubDBEntry(IpcFunctionType_t funcType,RpcFuncId_t funcId,uint32_t seqNum,RpcTaskID_t taskId,	RpcTaskID_t orgTaskId, uint32_t queId, RpcTaskID_t cbTaskId, struct timeval *absTime,IPC_CallbackFunc_t callbackFunc) {
	IpcStubFuncInfo_t *funcInfo;

	if(RPC_MutexLock(&(IpcStubDataManage.mutexId)) != RPC_SUCCESS) {
		return (IpcStubFuncInfo_t*)NULL;
	}
	if((funcInfo = (IpcStubFuncInfo_t*)RPC_AllocListData(&(IpcStubDataManage.stubFuncDBList),sizeof(IpcStubFuncInfo_t),0,RPC_LclAllocMemWrapper,RPC_LclFreeMemWrapper)) == (IpcStubFuncInfo_t*)NULL) {
		(void)RPC_MutexUnlock(&(IpcStubDataManage.mutexId));
		return (IpcStubFuncInfo_t*)NULL;
	}
	funcInfo->funcType = funcType;
	funcInfo->funcId = funcId;
	funcInfo->seqNum = seqNum;
	funcInfo->taskId = taskId;
	funcInfo->orgTaskId = orgTaskId;
	funcInfo->cbInfo.queId = queId;
	funcInfo->cbInfo.cbTaskId = cbTaskId;
	memcpy((void*)&(funcInfo->cbInfo.absTime),(void*)absTime,sizeof(struct timeval));
	funcInfo->cbInfo.callbackFunc = callbackFunc;
	(void)RPC_MutexUnlock(&(IpcStubDataManage.mutexId));
	return funcInfo;
}

static void IPC_deleteStubDBEntry(IpcStubFuncInfo_t *entry) {
	if(RPC_MutexLock(&(IpcStubDataManage.mutexId)) != RPC_SUCCESS) {
		return;
	}
	RPC_FreeListData(&(IpcStubDataManage.stubFuncDBList),(void*)entry,0,RPC_LclFreeMemWrapper);
	RPC_MutexUnlock(&(IpcStubDataManage.mutexId));
}

static IpcStubFuncInfo_t *IPC_searchStubDBEntryBySeqNum(uint32_t seqNum) {
	IpcStubFuncInfo_t *funcInfo;

	if(RPC_MutexLock(&(IpcStubDataManage.mutexId)) != RPC_SUCCESS) {
		return (IpcStubFuncInfo_t*)NULL;
	}
	if((funcInfo = RPC_SearchListEntryById(IpcStubDataManage.stubFuncDBList,seqNum,IPC_compareStubFuncDBBySeqNum)) != (IpcStubFuncInfo_t*)NULL) {
		RPC_MutexUnlock(&(IpcStubDataManage.mutexId));
		return funcInfo;
	}
	else {
		RPC_MutexUnlock(&(IpcStubDataManage.mutexId));
		return (IpcStubFuncInfo_t*)NULL;
	}
}

static IpcStubFuncInfo_t *IPC_searchStubDBEntryByOrgTaskId(RpcTaskID_t orgTaskId) {
	IpcStubFuncInfo_t *funcInfo;

	if(RPC_MutexLock(&(IpcStubDataManage.mutexId)) != RPC_SUCCESS) {
		return (IpcStubFuncInfo_t*)NULL;
	}
#if	__WORDSIZE == 64
	if((funcInfo = RPC_SearchListEntryByDwordId(IpcStubDataManage.stubFuncDBList,(uint64_t)orgTaskId,IPC_compareStubFuncDBByOrgTaskId)) != (IpcStubFuncInfo_t*)NULL) {
#else	/* __WORDSIZE */
	if((funcInfo = RPC_SearchListEntryById(IpcStubDataManage.stubFuncDBList,(uint32_t)orgTaskId,IPC_compareStubFuncDBByOrgTaskId)) != (IpcStubFuncInfo_t*)NULL) {
#endif	/* __WORDSIZE */
		RPC_MutexUnlock(&(IpcStubDataManage.mutexId));
		return funcInfo;
	}
	else {
		RPC_MutexUnlock(&(IpcStubDataManage.mutexId));
		return (IpcStubFuncInfo_t*)NULL;
	}
}

static IpcStubFuncInfo_t *IPC_searchStubDBEntryByCBTaskId(RpcTaskID_t cbTaskId) {
	IpcStubFuncInfo_t *funcInfo;

	if(RPC_MutexLock(&(IpcStubDataManage.mutexId)) != RPC_SUCCESS) {
		return (IpcStubFuncInfo_t*)NULL;
	}
#if	__WORDSIZE == 64
	if((funcInfo = RPC_SearchListEntryByDwordId(IpcStubDataManage.stubFuncDBList,(uint64_t)cbTaskId,IPC_compareStubFuncDBByCBTaskId)) != (IpcStubFuncInfo_t*)NULL) {
#else	/* __WORDSIZE */
	if((funcInfo = RPC_SearchListEntryById(IpcStubDataManage.stubFuncDBList,(uint32_t)cbTaskId,IPC_compareStubFuncDBByCBTaskId)) != (IpcStubFuncInfo_t*)NULL) {
#endif	/* __WORDSIZE */
		RPC_MutexUnlock(&(IpcStubDataManage.mutexId));
		return funcInfo;
	}
	else {
		RPC_MutexUnlock(&(IpcStubDataManage.mutexId));
		return (IpcStubFuncInfo_t*)NULL;
	}
}

static RpcBool_t IPC_compareStubFuncDBBySeqNum(RpcList_t *list,uint32_t seqNum) {
	if(((IpcStubFuncInfo_t*)(list->entry))->seqNum == seqNum)
		return RPC_TRUE;
	else
		return RPC_FALSE;
}

#if	__WORDSIZE == 64
static RpcBool_t IPC_compareStubFuncDBByOrgTaskId(RpcList_t *list,uint64_t orgTaskId) {
	if(((IpcStubFuncInfo_t*)(list->entry))->orgTaskId == (RpcTaskID_t)orgTaskId)
		return RPC_TRUE;
	else
		return RPC_FALSE;
}

static RpcBool_t IPC_compareStubFuncDBByCBTaskId(RpcList_t *list,uint64_t cbTaskId) {
	if(((IpcStubFuncInfo_t*)(list->entry))->cbInfo.cbTaskId == (RpcTaskID_t)cbTaskId)
		return RPC_TRUE;
	else
		return RPC_FALSE;
}
#else	/* __WORDSIZE */
static RpcBool_t IPC_compareStubFuncDBByOrgTaskId(RpcList_t *list,uint32_t orgTaskId) {
	if(((IpcStubFuncInfo_t*)(list->entry))->orgTaskId == (RpcTaskID_t)orgTaskId)
		return RPC_TRUE;
	else
		return RPC_FALSE;
}

static RpcBool_t IPC_compareStubFuncDBByCBTaskId(RpcList_t *list,uint32_t cbTaskId) {
	if(((IpcStubFuncInfo_t*)(list->entry))->cbInfo.cbTaskId == (RpcTaskID_t)cbTaskId)
		return RPC_TRUE;
	else
		return RPC_FALSE;
}
#endif	/* __WORDSIZE */

static RpcResult_t IPC_allocCBTaskFromStubResourceDB(RpcTaskID_t *taskId,RpcTaskControl_t **tskCntl) {
	IpcStubCBTaskResourceDBEntry_t *entry;RpcResult_t ret;

	if((ret = RPC_MutexLock(&(IpcStubRcsDBManage.mutexId))) != RPC_SUCCESS) {
		return ret;
	}
	if((entry = IPC_getIdleStubCBTaskResource()) == (IpcStubCBTaskResourceDBEntry_t*)NULL) {
		(void)RPC_MutexUnlock(&(IpcStubRcsDBManage.mutexId));
		return RPC_NO_MORE_RESOURCE;
	}
	*taskId = (RpcTaskID_t)entry->taskId;
	*tskCntl = &(entry->tskCntl);
	entry->taskState = RPC_RESOURCE_BUSY_STATE;
	(void)RPC_MutexUnlock(&(IpcStubRcsDBManage.mutexId));
	return RPC_SUCCESS;
}

static RpcResult_t IPC_freeCBTaskFromStubResourceDB(RpcTaskID_t taskId) {
	IpcStubCBTaskResourceDBEntry_t *entry;RpcResult_t ret;

	if((ret = RPC_MutexLock(&(IpcStubRcsDBManage.mutexId))) != RPC_SUCCESS) {
		return ret;
	}
#if	__WORDSIZE == 64
	if((entry = (IpcStubCBTaskResourceDBEntry_t*)RPC_SearchListEntryByDwordId(IpcStubRcsDBManage.stubCBTaskResourceList,(uint64_t)taskId,IPC_compareCBTaskResourceByTaskId)) == (IpcStubCBTaskResourceDBEntry_t*)NULL) {
#else	/* __WORDSIZE */
	if((entry = (IpcStubCBTaskResourceDBEntry_t*)RPC_SearchListEntryById(IpcStubRcsDBManage.stubCBTaskResourceList,(uint32_t)taskId,IPC_compareCBTaskResourceByTaskId)) == (IpcStubCBTaskResourceDBEntry_t*)NULL) {
#endif	/* __WORDSIZE */
		(void)RPC_MutexUnlock(&(IpcStubRcsDBManage.mutexId));
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_ERROR,"CAN NOT FIND ENTRY BY TASKID:0x%Lx;",taskId);
		return RPC_PARAM_ERROR;
	}
	entry->taskState = RPC_RESOURCE_IDLE_STATE;
	(void)RPC_MutexUnlock(&(IpcStubRcsDBManage.mutexId));
	return RPC_SUCCESS;
}

static IpcStubCBTaskResourceDBEntry_t *IPC_getIdleStubCBTaskResource(void) {
	uint32_t num;
	IpcStubCBTaskResourceDBEntry_t *entry,*new;RpcResult_t ret;

	if(RPC_MutexLock(&(IpcStubDataManage.mutexId)) != RPC_SUCCESS) {
		return (IpcStubCBTaskResourceDBEntry_t*)NULL;
	}
	if((entry = (IpcStubCBTaskResourceDBEntry_t*)RPC_SearchListEntryById(IpcStubRcsDBManage.stubCBTaskResourceList,(uint32_t)RPC_RESOURCE_IDLE_STATE,IPC_compareCBTaskResourceByState)) != (IpcStubCBTaskResourceDBEntry_t*)NULL) {
//		IPC_ResetTaskControl(&(entry->tskCntl));
		(void)RPC_MutexUnlock(&(IpcStubDataManage.mutexId));
		return entry;
	}
	num = RPC_CountNumOfListEntry(IpcStubRcsDBManage.stubCBTaskResourceList);
	if(num >= IPC_STUB_START_NUM_OF_CB_TASK_RESOURCE) {
		(void)RPC_MutexUnlock(&(IpcStubDataManage.mutexId));
		return (IpcStubCBTaskResourceDBEntry_t*)NULL;
	}
	if((new = (IpcStubCBTaskResourceDBEntry_t*)RPC_AllocListData(&(IpcStubRcsDBManage.stubCBTaskResourceList),sizeof(IpcStubCBTaskResourceDBEntry_t),0,RPC_LclAllocMemWrapper,RPC_LclFreeMemWrapper)) != (IpcStubCBTaskResourceDBEntry_t*)NULL) {
		(void)RPC_MutexUnlock(&(IpcStubDataManage.mutexId));
		return (IpcStubCBTaskResourceDBEntry_t*)NULL;			
	}
	if((ret = IPC_allocStubCBTaskResource(new)) != RPC_SUCCESS) {
		RPC_FreeListData(&(IpcStubRcsDBManage.stubCBTaskResourceList),new,0,RPC_LclFreeMemWrapper);
		(void)RPC_MutexUnlock(&(IpcStubDataManage.mutexId));
		return (IpcStubCBTaskResourceDBEntry_t*)NULL;
	}
	(void)RPC_MutexUnlock(&(IpcStubDataManage.mutexId));
	return new;
}

static RpcResult_t IPC_allocQueFromStubResourceDB(uint32_t *queId) {
	IpcStubQueResourceDBEntry_t *entry;RpcResult_t ret;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_DEBUG2,"IN IPC_allocQueFromStubResourceDB PID:0x%x;",RPC_GetPid());
	if((ret = RPC_MutexLock(&(IpcStubRcsDBManage.mutexId))) != RPC_SUCCESS) {
		return ret;
	}
	if((entry = IPC_getIdleStubQueResource()) == (IpcStubQueResourceDBEntry_t*)NULL) {
		(void)RPC_MutexUnlock(&(IpcStubRcsDBManage.mutexId));
		return RPC_NO_MORE_RESOURCE;
	}
	*queId = (uint32_t)entry->queId;
	entry->queState = RPC_RESOURCE_BUSY_STATE;
	(void)RPC_MutexUnlock(&(IpcStubRcsDBManage.mutexId));
//	(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_DEBUG2,"OUT IPC_allocQueFromStubResourceDB PID:0x%x; QUE-ID:0x%x;",RPC_GetPid(),*queId);
	return RPC_SUCCESS;
}

static RpcResult_t IPC_freeQueFromStubResourceDB(uint32_t queId) {
	IpcStubQueResourceDBEntry_t *entry;RpcResult_t ret;

	if((ret = RPC_MutexLock(&(IpcStubRcsDBManage.mutexId))) != RPC_SUCCESS) {
		return ret;
	}
	if((entry = (IpcStubQueResourceDBEntry_t*)RPC_SearchListEntryById(IpcStubRcsDBManage.stubQueResourceList,queId,IPC_compareQueResourceByQueId)) == (IpcStubQueResourceDBEntry_t*)NULL) {
		(void)RPC_MutexUnlock(&(IpcStubRcsDBManage.mutexId));
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_ERROR,"NOT FIND ENTRY BY QUEID:0x%x;",queId);
		return RPC_PARAM_ERROR;
	}
	entry->queState = RPC_RESOURCE_IDLE_STATE;
	(void)RPC_MutexUnlock(&(IpcStubRcsDBManage.mutexId));
	return RPC_SUCCESS;
}

static IpcStubQueResourceDBEntry_t *IPC_getIdleStubQueResource(void) {
	uint32_t num;
	IpcStubQueResourceDBEntry_t *entry,*new;RpcResult_t ret;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_DEBUG2,"IN IPC_getIdleStubQueResource PID:0x%x; StubQueRsrcList:0x%x;",RPC_GetPid(),IpcStubRcsDBManage.stubQueResourceList);
	if(RPC_MutexLock(&(IpcStubDataManage.mutexId)) != RPC_SUCCESS) {
		return (IpcStubQueResourceDBEntry_t*)NULL;
	}
	if((entry = (IpcStubQueResourceDBEntry_t*)RPC_SearchListEntryById(IpcStubRcsDBManage.stubQueResourceList,(uint32_t)RPC_RESOURCE_IDLE_STATE,IPC_compareQueResourceByState)) != (IpcStubQueResourceDBEntry_t*)NULL) {
//		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_DEBUG2,"OUT IPC_getIdleStubQueResource FIND IDLE ENTRY PID:0x%x; entry:0x%x;",RPC_GetPid(),entry);
		(void)RPC_MutexUnlock(&(IpcStubDataManage.mutexId));
		return entry;
	}
	num = RPC_CountNumOfListEntry(IpcStubRcsDBManage.stubQueResourceList);
	if(num >= IPC_STUB_MAX_NUM_OF_QUE_RESOURCE) {
		(void)RPC_MutexUnlock(&(IpcStubDataManage.mutexId));
		return (IpcStubQueResourceDBEntry_t*)NULL;
	}
	if((new = (IpcStubQueResourceDBEntry_t*)RPC_AllocListData(&(IpcStubRcsDBManage.stubQueResourceList),sizeof(IpcStubQueResourceDBEntry_t),0,RPC_LclAllocMemWrapper,RPC_LclFreeMemWrapper)) == (IpcStubQueResourceDBEntry_t*)NULL) {
		(void)RPC_MutexUnlock(&(IpcStubDataManage.mutexId));
		return (IpcStubQueResourceDBEntry_t*)NULL;
	}
	if((ret = IPC_allocStubQueResource(new)) != RPC_SUCCESS) {
		RPC_FreeListData(&(IpcStubRcsDBManage.stubQueResourceList),new,0,RPC_LclFreeMemWrapper);
		(void)RPC_MutexUnlock(&(IpcStubDataManage.mutexId));
		return (IpcStubQueResourceDBEntry_t*)NULL;
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_DEBUG2,"OUT IPC_getIdleStubQueResource CREATE NEW ENTRY PID:0x%x; entry:0x%x;",RPC_GetPid(),new);
	(void)RPC_MutexUnlock(&(IpcStubDataManage.mutexId));
	return new;
}

#if	__WORDSIZE == 64
static RpcBool_t IPC_compareCBTaskResourceByTaskId(RpcList_t *list,uint64_t taskId) {
	if((uint64_t)(((IpcStubCBTaskResourceDBEntry_t*)list->entry)->taskId) == taskId)
		return RPC_TRUE;
	else
		return RPC_FALSE;
}
#else	/* __WORDSIZE */
static RpcBool_t IPC_compareCBTaskResourceByTaskId(RpcList_t *list,uint32_t taskId) {
	if((uint32_t)(((IpcStubCBTaskResourceDBEntry_t*)list->entry)->taskId) == taskId)
		return RPC_TRUE;
	else
		return RPC_FALSE;
}
#endif	/* __WORDSIZE */

static RpcBool_t IPC_compareCBTaskResourceByState(RpcList_t *list,uint32_t state) {
	if((uint32_t)(((IpcStubCBTaskResourceDBEntry_t*)list->entry)->taskState) == state)
		return RPC_TRUE;
	else
		return RPC_FALSE;
}

static RpcBool_t IPC_compareQueResourceByQueId(RpcList_t *list,uint32_t queId) {
	if(((IpcStubQueResourceDBEntry_t*)list->entry)->queId == queId)
		return RPC_TRUE;
	else
		return RPC_FALSE;
}

static RpcBool_t IPC_compareQueResourceByState(RpcList_t *list,uint32_t state) {
//	(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_DEBUG3,"IN IPC_compareQueResourceByState STATE:%d; ORG:%d;",
//		(uint32_t)(((IpcStubQueResourceDBEntry_t*)list->entry)->queState),state);
	if((uint32_t)(((IpcStubQueResourceDBEntry_t*)list->entry)->queState) == state)
		return RPC_TRUE;
	else
		return RPC_FALSE;
}

static RpcResult_t IPC_allocStubCBTaskResource(IpcStubCBTaskResourceDBEntry_t *entry) {
	RpcResult_t ret;RpcTaskSchedParam_t schedParam;

	if((ret = RPC_CreateTaskControl(RPC_FALSE,&(entry->tskCntl))) != RPC_SUCCESS) {
		return ret;
	}
	if((ret = RPC_TaskAttrInit(&(entry->taskAttr))) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_FATAL, " CAN NOT INIT TASK ATTRIBUTE ret:%s",RPC_LogConvertResultCode(ret));
		goto errOut;
	}
	if((ret = RPC_TaskAttrSetDetachState(&(entry->taskAttr), IPC_STUB_CB_TASK_DETACH_STATE)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_FATAL, " CAN NOT SET SETACH STATE ret:%s",RPC_LogConvertResultCode(ret));
		goto errOut;
	}
	if((ret = RPC_TaskAttrSetSchedPolicy(&(entry->taskAttr), IPC_STUB_CB_TASK_SCHED_POLICY)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_FATAL, " CAN NOT SET SCHED POLICY ret:%s",RPC_LogConvertResultCode(ret));
		goto errOut;
	}
	schedParam.sched_priority = (int)IPC_STUB_CB_TASK_PRIORITY;
	if((ret = RPC_TaskAttrSetSchedParam(&(entry->taskAttr),&schedParam)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_FATAL, " CAN NOT SET SCHED POLICY ret:%s",RPC_LogConvertResultCode(ret));
		goto errOut;
	}	
	if((ret = RPC_TaskAttrSetStackSize(&(entry->taskAttr), IPC_STUB_CB_TASK_STACK_SIZE)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_FATAL, " CAN NOT SET STACK SIZE ret:%s",RPC_LogConvertResultCode(ret));
		goto errOut;
	}
	if((ret = RPC_CreateTask(&(entry->taskId), &(entry->taskAttr), IPC_CBTaskMain, (void*)&(entry->tskCntl))) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_FATAL, " CAN NOT CREATE TASK ret:%s",RPC_LogConvertResultCode(ret));
		goto errOut;
	}
	entry->taskState = RPC_RESOURCE_IDLE_STATE;
	return RPC_SUCCESS;

errOut:
	RPC_DestroyTaskControl(&(entry->tskCntl));
	return ret;
}

static RpcResult_t IPC_allocStubQueResource(IpcStubQueResourceDBEntry_t *entry) {
	RpcResult_t ret;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_DEBUG2,"IN IPC_allocStubQueResource PID:0x%x; ENTRY:0x%x;",RPC_GetPid(),entry);
	if((ret = IPC_CreateQue(RPC_TRUE,IPC_STUB_QUE_SIZE, &(entry->queId))) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_FATAL, " CAN NOT CREATE QUE ret:%s",RPC_LogConvertResultCode(ret));
		return ret;
	}
	if((ret = IPC_EnableQue(entry->queId)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_STUB,RPC_LOG_LEVEL_FATAL, " CAN NOT ENABLE QUE ret:%s",RPC_LogConvertResultCode(ret));
		(void)IPC_DestroyQue(entry->queId);
		return ret;
	}
	entry->queState = RPC_RESOURCE_IDLE_STATE;
//	(void)RPC_LogPrint(RPC_LOG_MODULE_STUB, RPC_LOG_LEVEL_DEBUG2,"OUT IPC_allocStubQueResource PID:0x%x; QUEID:0x%x;",RPC_GetPid(),entry->queId);
	return RPC_SUCCESS;
}

static uint32_t IPC_assignNewSequenceNubmer(void) {
	static uint32_t stubSequenceNumber = IPC_STUB_INVALID_SEQ_NUM;
	IpcStubFuncInfo_t *funcInfo; uint32_t ret;

	if(RPC_MutexLock(&(IpcStubDataManage.mutexId)) != RPC_SUCCESS) {
		return IPC_STUB_INVALID_SEQ_NUM;
	}
	for(;;) {
		ret = ++stubSequenceNumber;
		if(ret == IPC_STUB_INVALID_SEQ_NUM)
			ret = ++stubSequenceNumber;
		if((funcInfo = RPC_SearchListEntryById(IpcStubDataManage.stubFuncDBList,ret,IPC_compareStubFuncDBBySeqNum)) == (IpcStubFuncInfo_t*)NULL) {
			break;
		}
	}
	(void)RPC_MutexUnlock(&(IpcStubDataManage.mutexId));
	return ret;
}

static void IPC_cleanStubQueue(uint32_t queId) {
	uint32_t msgId; RpcMsgParam_t msgParam;

	while(IPC_SweepMsgFromExtQue(queId,&msgId,&msgParam) == RPC_SUCCESS) {
		if(msgParam.u.msgParam.extParam == (void*)NULL) {
			IPC_FreeMarshaledSharedData(msgParam.u.msgParam.extParam);
		}
	}
}

#ifdef	USE_MULTICAST_RPC
static RpcResult_t IPC_initStubMltcstCntl(void) {
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_DEBUG1,"IN IPC_initStubMltcstCntl PID:0x%x;",RPC_GetPid());
	memset(&IpcStubMltcstCntl,0,sizeof(IpcStubMltcstCntl_t));
	if(RPC_MutexAttrInit(&(IpcStubMltcstCntl.mutexAttr)) != RPC_SUCCESS) {
		return RPC_FATAL_ERROR;
	}
#ifdef	_LINUX_
	if(RPC_MutexAttrSetType(&(IpcStubMltcstCntl.mutexAttr), PTHREAD_MUTEX_ADAPTIVE_NP) != RPC_SUCCESS) {
		return RPC_FATAL_ERROR;
	}
#else	/* _LINUX_ */
	if(RPC_MutexAttrSetType(&(IpcStubMltcstCntl.mutexAttr), PTHREAD_MUTEX_RECURSIVE) != RPC_SUCCESS) {
		return RPC_FATAL_ERROR;
	}
#endif	/* _LINUX_ */
	if(RPC_MutexAttrSetPshared(&(IpcStubMltcstCntl.mutexAttr), PTHREAD_PROCESS_PRIVATE) != RPC_SUCCESS) {
		return RPC_FATAL_ERROR;
	}
	if(RPC_InitMutex(&(IpcStubMltcstCntl.mutexId),&(IpcStubMltcstCntl.mutexAttr)) != RPC_SUCCESS) {
		return RPC_FATAL_ERROR;
	}
	IpcStubMltcstCntl.stubMltcstList = (RpcList_t*)NULL;
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_DEBUG1,"OUT IPC_initStubMltcstCntl PID:0x%x;", RPC_GetPid());
	return RPC_SUCCESS;
}

static RpcResult_t IPC_callSyncMulticastFunction(RpcTaskID_t callTaskId,uint32_t mltcstFuncId,void *inParams,uint32_t inParamsSize,uint32_t *numOfCalls,uint32_t *numOfRet,IpcMulticastRetData_t **retData,uint32_t timeOut,uint32_t *errCode) {
	RpcResult_t ret;RpcList_t *funcList = (RpcList_t*)NULL;IpcStubMltcstResourceDBEntry_t *mltcstRcs;
	IpcFuncRetVal_t *retValArea;IpcMltcstRetCntl_t *mltcstRetCntl;RpcList_t *list;
	IpcMltcstFuncEntry_t *funcEntry;uint32_t seqNum;IpcMulticastRetData_t *retVal,*p;
	struct timeval absTime;struct timespec specTime;void *dupData;int32_t calls = 0;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_DEBUG1,"IN IPC_callSyncMulticastFunction callTaskId:0x%x; mltcstFuncId:0x%x;",
//		callTaskId, mltcstFuncId);
	*retData = (IpcMulticastRetData_t*)NULL;
	*numOfCalls = 0;
	*numOfRet = 0;
	if(!RPC_SetTimeout(timeOut,&absTime)) {
		if(inParams != (void*)NULL) {
			IPC_FreeMarshaledSharedData(inParams);
			inParams = (void*)NULL;
		}
		*errCode = RPC_ERR_OTHER;
		return RPC_PARAM_ERROR;
	}
	if((ret = RPC_MutexLock(&(IpcStubMltcstCntl.mutexId))) != RPC_SUCCESS) {
		if(inParams != (void*)NULL) {
			IPC_FreeMarshaledSharedData(inParams);
			inParams = (void*)NULL;
		}
		*errCode = RPC_ERR_OTHER;
		return ret;
	}
	if((ret = IPC_GetFuncListByMltcstFuncId(mltcstFuncId, &funcList)) != RPC_SUCCESS) {
		if(inParams != (void*)NULL) {
			IPC_FreeMarshaledSharedData(inParams);
			inParams = (void*)NULL;
		}
		(void)RPC_MutexUnlock(&(IpcStubMltcstCntl.mutexId));
		(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_ERROR,"NOT FIND MULTICAST FUNCTION MULTICAST-FUNC:0x%x;",
			mltcstFuncId);
		*errCode = RPC_ERR_OTHER;
		return RPC_PARAM_ERROR;
	}
	if((*numOfCalls = RPC_CountNumOfListEntry(funcList)) == 0) {
		if(inParams != (void*)NULL) {
			IPC_FreeMarshaledSharedData(inParams);
			inParams = (void*)NULL;
		}
		IPC_FreeFuncList(funcList);
		(void)RPC_MutexUnlock(&(IpcStubMltcstCntl.mutexId));
		(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_ERROR,"NOT FOUND TARGET FUNC MULTICAST-FUNC:0x%x;",
			mltcstFuncId);
		*errCode = RPC_ERR_OTHER;
		return RPC_CAN_NOT_EXEC;
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_DEBUG3,"  END OF STEP1 numOfCall:%d;",*numOfCalls);
	if((ret = IPC_allocMltcstFromStubResourceDB(callTaskId,&mltcstRcs)) != RPC_SUCCESS) {
		if(inParams != (void*)NULL) {
			IPC_FreeMarshaledSharedData(inParams);
			inParams = (void*)NULL;
		}
		IPC_FreeFuncList(funcList);
		(void)RPC_MutexUnlock(&(IpcStubMltcstCntl.mutexId));
		(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_ERROR,"CAN NOT GET MULTICAST RESOURCE MULTICAST-FUNC:0x%x;",
			mltcstFuncId);
		*errCode = RPC_ERR_OTHER;
		return ret;
	}
	if((mltcstRetCntl = IPC_addStubMltcstCntlEntry(IPC_BLOCKING_FUNCTION, mltcstFuncId,callTaskId,mltcstRcs,(IPC_MultticastCallbackFunc_t) NULL)) == (IpcMltcstRetCntl_t*)NULL) {
		if(inParams != (void*)NULL) {
			IPC_FreeMarshaledSharedData(inParams);
			inParams = (void*)NULL;
		}
		(void)IPC_freeMltcstFromStubResourceDB(callTaskId);
		IPC_FreeFuncList(funcList);
		(void)RPC_MutexUnlock(&(IpcStubMltcstCntl.mutexId));
		*errCode = RPC_ERR_OTHER;
		return RPC_NO_MORE_RESOURCE;
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_DEBUG3,"  END OF REGISTER MULTICAST ENTRY RSC:0x%x; RetCntl:0x%x;",
//		mltcstRcs,mltcstRetCntl);
	if(!RPC_GetRestTimeout(&absTime,&timeOut)) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_ERROR, " TIMEOUT OCCUR");
		ret = RPC_TIMEOUT_ERROR;
		goto OccrError1;
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_DEBUG3,"  NOW CALL FUNCTION");
	for( list = funcList;list != (RpcList_t*)NULL;list = list->next) {
		funcEntry = (IpcMltcstFuncEntry_t*)list->entry;
		if((retValArea = (IpcFuncRetVal_t*)RPC_AllocListData(&(mltcstRetCntl->funcRetVals),sizeof(IpcFuncRetVal_t),0,RPC_LclAllocMemWrapper,RPC_LclFreeMemWrapper)) == (IpcFuncRetVal_t*)NULL) {
			ret = RPC_NO_MORE_RESOURCE;
			*errCode = RPC_ERR_OTHER;
			goto OccrError1;
		}
		(void)memset(retValArea,0,sizeof(IpcFuncRetVal_t));
		if(inParams == (void*)NULL) {
			dupData = (void*)NULL;
		}
		else if(calls < (*numOfCalls - 1)) {
			if((dupData = IPC_DuplicateMarshaledData(inParams,inParamsSize)) == (void*)NULL) {
				ret = RPC_NO_MORE_RESOURCE;
				*errCode = RPC_ERR_OTHER;
				goto OccrError1;
			}
		}
		else {
			dupData = inParams;
			inParams = (void*)NULL;
		}
//		(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_DEBUG3,"     CALL FUNCID:0x%x; inData:0x%x; inDataSize:%d; timeOut:%d;",
//			funcEntry->funcId, dupData,dupData,inParamsSize, timeOut);
		if((ret = IPC_CallStubAsync(funcEntry->funcId, dupData, inParamsSize, timeOut, IPC_mltcstCallback, &seqNum,errCode)) != RPC_SUCCESS) {
			(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_ERROR,"FAIL IN IPC_CallStubAsync FUNCID:0x%x;",funcEntry->funcId);
			(*numOfCalls)--;
			RPC_FreeListData(&(mltcstRetCntl->funcRetVals),(void*)(retValArea),0,RPC_LclFreeMemWrapper);
			continue;
		}
		retValArea->seqNum = seqNum;
		retValArea->dstPid = funcEntry->processId;
		calls++;
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_DEBUG3,"  END CALL FUNCTION");
	if(inParams != (void*)NULL) {
		IPC_FreeMarshaledSharedData(inParams);
		inParams = (void*)NULL;
	}
	IPC_FreeFuncList(funcList);
	funcList = (RpcList_t*)NULL;
	mltcstRetCntl->numOfCall = *numOfCalls;
	if(!RPC_CheckTimeout(&absTime)) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_ERROR, " TIMEOUT OCCUR");
		*errCode = RPC_ERR_OTHER;
		ret = RPC_TIMEOUT_ERROR;
		goto OccrError1;
	}	
	(void)RPC_MutexUnlock(&(IpcStubMltcstCntl.mutexId));
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_DEBUG3,"  END OF STEP2 AND WAIT numOfCall:%d;",*numOfCalls);
	RPC_ConvertTime(&absTime,&specTime);
	if((ret = RPC_TaskControlTimedWait(&(mltcstRcs->tskCntl),&specTime)) != RPC_SUCCESS) {
		if(ret != RPC_TIMEOUT_ERROR) {
			(void)RPC_MutexLock(&(IpcStubMltcstCntl.mutexId));
			goto OccrError1;
		}
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_DEBUG2,"  END OF STEP3");
	if((ret = RPC_MutexLock(&(IpcStubMltcstCntl.mutexId))) != RPC_SUCCESS) {
		*errCode = RPC_ERR_OTHER;
		goto OccrError1;
	}
	(void)IPC_freeMltcstFromStubResourceDB(callTaskId);
	if((retVal = (void*)RPC_AllocMem( *numOfCalls * sizeof(IpcMulticastRetData_t))) == (void*)NULL) {
		*errCode = RPC_ERR_OTHER;
		ret = RPC_NO_MORE_RESOURCE;
		goto OccrError2;
	}
	(void)memset((void*)retVal,0, *numOfCalls * sizeof(IpcMulticastRetData_t));
	p = retVal;
	while((list = mltcstRetCntl->funcRetVals) != (RpcList_t*)NULL) {
		p->resPid = ((IpcFuncRetVal_t*)(list->entry))->dstPid;
		p->errCode = ((IpcFuncRetVal_t*)(list->entry))->errCode;
		p->retParam = ((IpcFuncRetVal_t*)(list->entry))->outParams;
		p->retParamSize = ((IpcFuncRetVal_t*)(list->entry))->outParamsSize;
		(*numOfRet)++;
		p++;
		RPC_FreeListData(&(mltcstRetCntl->funcRetVals),(void*)(list->entry),0,RPC_LclFreeMemWrapper);
	}
	IPC_deleteStubMltcstCntlEntry(mltcstRetCntl);
	(void)RPC_MutexUnlock(&(IpcStubMltcstCntl.mutexId));
	*retData = (IpcMulticastRetData_t*)retVal;
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_DEBUG1,"OUT IPC_callSyncMulticastFunction numOfRet:%d; retData:0x%x;",
//		*numOfRet,*retData);
	return RPC_SUCCESS;

OccrError1:
	if(inParams != (void*)NULL) {
		IPC_FreeMarshaledSharedData(inParams);
		inParams = (void*)NULL;
	}
	(void)IPC_freeMltcstFromStubResourceDB(callTaskId);
	*errCode = RPC_ERR_OTHER;
OccrError2:
	while((list = mltcstRetCntl->funcRetVals) != (RpcList_t*)NULL) {
		if(((IpcFuncRetVal_t*)(list->entry))->outParams != (void*)NULL) {
			IPC_FreeMarshaledSharedData((void*)((IpcFuncRetVal_t*)(list->entry))->outParams);
		}
		RPC_FreeListData(&(mltcstRetCntl->funcRetVals),(void*)(list->entry),0,RPC_LclFreeMemWrapper);
	}
	IPC_deleteStubMltcstCntlEntry(mltcstRetCntl);
	IPC_FreeFuncList(funcList);
	(void)RPC_MutexUnlock(&(IpcStubMltcstCntl.mutexId));
	return ret;
}

static RpcResult_t IPC_callAsyncMulticastFunction(RpcTaskID_t callTaskId,uint32_t mltcstFuncId,void *inParams,uint32_t inParamsSize,uint32_t *numOfCalls,uint32_t timeOut,IPC_MultticastCallbackFunc_t mltcstCallback,uint32_t *seqNum,uint32_t *errCode) {
	RpcResult_t ret;RpcList_t *funcList = (RpcList_t*)NULL;
	IpcFuncRetVal_t *retValArea;IpcMltcstRetCntl_t *mltcstRetCntl;RpcList_t *list;
	IpcMltcstFuncEntry_t *funcEntry;uint32_t lclSeqNum;void *dupData;int32_t calls = 0;
	struct timeval absTime;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_DEBUG1,"IN IPC_callAsyncMulticastFunction callTaskId:0x%x; mltcstFuncId:0x%x;",
//		callTaskId, mltcstFuncId);
	*numOfCalls = 0;
	*seqNum = IPC_STUB_INVALID_SEQ_NUM;
	if(!RPC_SetTimeout(timeOut,&absTime)) {
		if(inParams != (void*)NULL) {
			IPC_FreeMarshaledSharedData(inParams);
			inParams = (void*)NULL;
		}
		*errCode = RPC_ERR_OTHER;
		return RPC_PARAM_ERROR;
	}
	if((ret = RPC_MutexLock(&(IpcStubMltcstCntl.mutexId))) != RPC_SUCCESS) {
		if(inParams != (void*)NULL) {
			IPC_FreeMarshaledSharedData(inParams);
			inParams = (void*)NULL;
		}
		*errCode = RPC_ERR_OTHER;
		return ret;
	}
	if((ret = IPC_GetFuncListByMltcstFuncId(mltcstFuncId, &funcList)) != RPC_SUCCESS) {
		if(inParams != (void*)NULL) {
			IPC_FreeMarshaledSharedData(inParams);
			inParams = (void*)NULL;
		}
		(void)RPC_MutexUnlock(&(IpcStubMltcstCntl.mutexId));
		(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_ERROR,"NOT FIND MULTICAST FUNCTION MULTICAST-FUNC:0x%x;",
			mltcstFuncId);
		*errCode = RPC_ERR_OTHER;
		return RPC_PARAM_ERROR;
	}
	if((*numOfCalls = RPC_CountNumOfListEntry(funcList)) == 0) {
		if(inParams != (void*)NULL) {
			IPC_FreeMarshaledSharedData(inParams);
			inParams = (void*)NULL;
		}
		IPC_FreeFuncList(funcList);
		(void)RPC_MutexUnlock(&(IpcStubMltcstCntl.mutexId));
		(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_ERROR,"NOT FOUND TARGET FUNC MULTICAST-FUNC:0x%x;",
			mltcstFuncId);
		*errCode = RPC_ERR_OTHER;
		return RPC_CAN_NOT_EXEC;
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_DEBUG3,"  END OF STEP1 numOfCall:%d;",*numOfCalls);
	if((mltcstRetCntl = IPC_addStubMltcstCntlEntry(IPC_NONBLOCKING_FUNCTION, mltcstFuncId,callTaskId,(IpcStubMltcstResourceDBEntry_t*)NULL,mltcstCallback)) == (IpcMltcstRetCntl_t*)NULL) {
		if(inParams != (void*)NULL) {
			IPC_FreeMarshaledSharedData(inParams);
			inParams = (void*)NULL;
		}
		(void)IPC_freeMltcstFromStubResourceDB(callTaskId);
		IPC_FreeFuncList(funcList);
		(void)RPC_MutexUnlock(&(IpcStubMltcstCntl.mutexId));
		*errCode = RPC_ERR_OTHER;
		return RPC_NO_MORE_RESOURCE;
	}
	if(!RPC_GetRestTimeout(&absTime,&timeOut)) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_ERROR, " TIMEOUT OCCUR");
		ret = RPC_TIMEOUT_ERROR;
		goto OccrError;
	}
	for( list = funcList;list != (RpcList_t*)NULL;list = list->next) {
		funcEntry = (IpcMltcstFuncEntry_t*)list->entry;
		if((retValArea = (IpcFuncRetVal_t*)RPC_AllocListData(&(mltcstRetCntl->funcRetVals),sizeof(IpcFuncRetVal_t),0,RPC_LclAllocMemWrapper,RPC_LclFreeMemWrapper)) == (IpcFuncRetVal_t*)NULL) {
			ret = RPC_NO_MORE_RESOURCE;
			*errCode = RPC_ERR_OTHER;
			goto OccrError;
		}
		(void)memset(retValArea,0,sizeof(IpcFuncRetVal_t));
		if(inParams == (void*)NULL) {
			dupData = (void*)NULL;
		}
		else if(calls < (*numOfCalls - 1)) {
			if((dupData = IPC_DuplicateMarshaledData(inParams,inParamsSize)) == (void*)NULL) {
				ret = RPC_NO_MORE_RESOURCE;
				*errCode = RPC_ERR_OTHER;
				goto OccrError;
			}
		}
		else {
			dupData = inParams;
			inParams = (void*)NULL;
		}
		if((ret = IPC_CallStubAsync(funcEntry->funcId, dupData, inParamsSize, timeOut, IPC_mltcstCallback, &lclSeqNum,errCode)) != RPC_SUCCESS) {
			(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_ERROR,"FAIL IN IPC_CallStubAsync FUNCID:0x%x;",funcEntry->funcId);
			(*numOfCalls)--;
			RPC_FreeListData(&(mltcstRetCntl->funcRetVals),(void*)(retValArea),0,RPC_LclFreeMemWrapper);
			continue;
		}
		calls++;
		retValArea->seqNum = lclSeqNum;
		retValArea->dstPid = funcEntry->processId;
	}
	if(inParams != (void*)NULL) {
		IPC_FreeMarshaledSharedData(inParams);
		inParams = (void*)NULL;
	}
	IPC_FreeFuncList(funcList);
	funcList = (RpcList_t*)NULL;
	mltcstRetCntl->numOfCall = *numOfCalls;
	if(!RPC_CheckTimeout(&absTime)) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_ERROR, " TIMEOUT OCCUR");
		*errCode = RPC_ERR_OTHER;
		ret = RPC_TIMEOUT_ERROR;
		goto OccrError;
	}
	*seqNum = IPC_assignNewSequenceNubmer();
	mltcstRetCntl->seqNum = *seqNum;
	(void)RPC_MutexUnlock(&(IpcStubMltcstCntl.mutexId));
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_DEBUG1,"OUT IPC_callAsyncMulticastFunction seqNum:0x%d; numOfCalls:%d;",*seqNum,*numOfCalls);
	return RPC_SUCCESS;

OccrError:
	if(inParams != (void*)NULL) {
		IPC_FreeMarshaledSharedData(inParams);
		inParams = (void*)NULL;
	}
	(void)IPC_freeMltcstFromStubResourceDB(callTaskId);
	*errCode = RPC_ERR_OTHER;
	while((list = mltcstRetCntl->funcRetVals) != (RpcList_t*)NULL) {
		if(((IpcFuncRetVal_t*)(list->entry))->outParams != (void*)NULL) {
			IPC_FreeMarshaledSharedData((void*)((IpcFuncRetVal_t*)(list->entry))->outParams);
		}
		RPC_FreeListData(&(mltcstRetCntl->funcRetVals),(void*)(list->entry),0,RPC_LclFreeMemWrapper);
	}
	IPC_deleteStubMltcstCntlEntry(mltcstRetCntl);
	IPC_FreeFuncList(funcList);
	(void)RPC_MutexUnlock(&(IpcStubMltcstCntl.mutexId));
	return ret;
}

static void IPC_mltcstCallback(uint32_t seqNum,void *outData,uint32_t outSize,uint32_t errCode) {
	RpcResult_t ret;IpcMltcstRetCntl_t *mltcstRetCntl;IpcFuncRetVal_t *retValData;
	IpcMulticastRetData_t *retVals,*p;
	IPC_MultticastCallbackFunc_t callbackFunc;uint32_t numOfRet = 0;
	RpcList_t *list;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_DEBUG1,"IN IPC_mltcstCallback seqNum:0x%x;",seqNum);
	if((ret = RPC_MutexLock(&(IpcStubMltcstCntl.mutexId))) != RPC_SUCCESS) {
		IPC_FreeMarshaledSharedData((void*)outData);
		(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_FATAL,"FAIL IN RPC_MutexLock ret:%s;",RPC_LogConvertResultCode(ret));
		return;
	}
	if((retValData = IPC_searchStubMltcstCntlEntryBySeqNum(seqNum,&mltcstRetCntl)) == (IpcFuncRetVal_t*)NULL) {
		IPC_FreeMarshaledSharedData((void*)outData);
		(void)RPC_MutexUnlock(&(IpcStubMltcstCntl.mutexId));
		(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_WARNING," NOT FOUND RET VALUE AREA PERPAHS TIMEOUT OCCUR IN THIS TRANSACTION SEQNUM:0x%x;",seqNum);
		return;
	}
	retValData->outParams = outData;
	retValData->outParamsSize = outSize;
	retValData->errCode = errCode;
	(mltcstRetCntl->numOfCallback)++;
	if(mltcstRetCntl->numOfCallback >= mltcstRetCntl->numOfCall) {
		if(mltcstRetCntl->funcType == IPC_BLOCKING_FUNCTION) {
			if((ret = RPC_TaskControlSignal(&(mltcstRetCntl->mltcstMutex->tskCntl))) != RPC_SUCCESS) {
				(void)RPC_MutexUnlock(&(IpcStubMltcstCntl.mutexId));
				return;			
			}
			(void)RPC_MutexUnlock(&(IpcStubMltcstCntl.mutexId));
		}
		else if(mltcstRetCntl->funcType == IPC_NONBLOCKING_FUNCTION) {
			errCode = RPC_NO_ERROR;
			callbackFunc = mltcstRetCntl->callbackFunc;
			if(callbackFunc != (IPC_MultticastCallbackFunc_t)NULL) {
				if((retVals = (void*)RPC_AllocMem( mltcstRetCntl->numOfCall * sizeof(IpcMulticastRetData_t))) == (void*)NULL) {
					errCode = RPC_ERR_OTHER;
					ret = RPC_NO_MORE_RESOURCE;
					goto OccrError;
				}
				(void)memset((void*)retVals,0, mltcstRetCntl->numOfCall * sizeof(IpcMulticastRetData_t));
				p = retVals;
				while((list = mltcstRetCntl->funcRetVals) != (RpcList_t*)NULL) {
					p->resPid = ((IpcFuncRetVal_t*)(list->entry))->dstPid;
					p->errCode = ((IpcFuncRetVal_t*)(list->entry))->errCode;
					p->retParam = ((IpcFuncRetVal_t*)(list->entry))->outParams;
					p->retParamSize = ((IpcFuncRetVal_t*)(list->entry))->outParamsSize;
					numOfRet++;
					p++;
					RPC_FreeListData(&(mltcstRetCntl->funcRetVals),(void*)(list->entry),0,RPC_LclFreeMemWrapper);
				}
				seqNum = mltcstRetCntl->seqNum;
			}
			else {
				while((list = mltcstRetCntl->funcRetVals) != (RpcList_t*)NULL) {
					if(((IpcFuncRetVal_t*)(list->entry))->outParams != (void*)NULL) {
						IPC_FreeMarshaledSharedData((void*)((IpcFuncRetVal_t*)(list->entry))->outParams);
					}
					RPC_FreeListData(&(mltcstRetCntl->funcRetVals),(void*)(list->entry),0,RPC_LclFreeMemWrapper);
				}
			}
			IPC_deleteStubMltcstCntlEntry(mltcstRetCntl);
			(void)RPC_MutexUnlock(&(IpcStubMltcstCntl.mutexId));
			if(callbackFunc != (IPC_MultticastCallbackFunc_t)NULL) {
				callbackFunc(seqNum,numOfRet,retVals,errCode);
			}
		}
	}
	else {
		(void)RPC_MutexUnlock(&(IpcStubMltcstCntl.mutexId));
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_DEBUG1,"OUT IPC_mltcstCallback");
	return;

OccrError:
	seqNum = mltcstRetCntl->seqNum;
	while((list = mltcstRetCntl->funcRetVals) != (RpcList_t*)NULL) {
		if(((IpcFuncRetVal_t*)(list->entry))->outParams != (void*)NULL) {
			IPC_FreeMarshaledSharedData((void*)((IpcFuncRetVal_t*)(list->entry))->outParams);
		}
		RPC_FreeListData(&(mltcstRetCntl->funcRetVals),(void*)(list->entry),0,RPC_LclFreeMemWrapper);
	}
	callbackFunc = mltcstRetCntl->callbackFunc;
	IPC_deleteStubMltcstCntlEntry(mltcstRetCntl);
	(void)RPC_MutexUnlock(&(IpcStubMltcstCntl.mutexId));
	if(callbackFunc != (IPC_MultticastCallbackFunc_t)NULL) {
		callbackFunc(seqNum,0,(IpcMulticastRetData_t*)NULL,errCode);
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_DEBUG1,"OUT IPC_mltcstCallback ERROR OCCUR RET:%s; ERR-CODE:%s;",
//		RPC_LogConvertResultCode(ret),RPC_LogConvertErrCode(errCode));
	return;
}

static IpcMltcstRetCntl_t *IPC_addStubMltcstCntlEntry(IpcFunctionType_t funcType, uint32_t mltcstFuncId ,RpcTaskID_t callTaskId, IpcStubMltcstResourceDBEntry_t *mltcstMutex,IPC_MultticastCallbackFunc_t callbackFunc) {
	IpcMltcstRetCntl_t *mltcstInfo;

	if((mltcstInfo = (IpcMltcstRetCntl_t*)RPC_AllocListData(&(IpcStubMltcstCntl.stubMltcstList),sizeof(IpcMltcstRetCntl_t),0,RPC_LclAllocMemWrapper,RPC_LclFreeMemWrapper)) == (IpcMltcstRetCntl_t*)NULL) {
		return (IpcMltcstRetCntl_t*)NULL;
	}
	mltcstInfo->funcType = funcType;
	mltcstInfo->mltcstFuncId = mltcstFuncId;
	mltcstInfo->callTaskId = callTaskId;
	mltcstInfo->mltcstMutex = mltcstMutex;
	mltcstInfo->funcRetVals = (RpcList_t*)NULL;
	mltcstInfo->numOfCall = 0;
	mltcstInfo->numOfCallback = 0;
	mltcstInfo->callbackFunc = callbackFunc;
	mltcstInfo->seqNum = IPC_STUB_INVALID_SEQ_NUM;
	return mltcstInfo;
}

static void IPC_deleteStubMltcstCntlEntry(IpcMltcstRetCntl_t *entry) {
	RPC_FreeListData(&(IpcStubMltcstCntl.stubMltcstList),(void*)entry,0,RPC_LclFreeMemWrapper);
}

static IpcFuncRetVal_t *IPC_searchStubMltcstCntlEntryBySeqNum(uint32_t seqNum,IpcMltcstRetCntl_t **mltcstRetCntl) {
	IpcMltcstRetCntl_t *mltcstInfo;IpcFuncRetVal_t *retValData;RpcList_t *list;

	mltcstInfo = (IpcMltcstRetCntl_t*)NULL;
	retValData = (IpcFuncRetVal_t*)NULL;
	for(list = IpcStubMltcstCntl.stubMltcstList;list != (RpcList_t*)NULL;list = list->next) {
		mltcstInfo = (IpcMltcstRetCntl_t*)(list->entry);
		if((retValData = (IpcFuncRetVal_t*)RPC_SearchListEntryById(mltcstInfo->funcRetVals,seqNum,IPC_compareStubMltcstRetValBySeqNum)) != (IpcFuncRetVal_t*)NULL) {
			break;
		}
	}
	*mltcstRetCntl = mltcstInfo;
	return retValData;
}

static RpcResult_t IPC_allocMltcstFromStubResourceDB(RpcTaskID_t taskId,IpcStubMltcstResourceDBEntry_t **entry) {
	IpcStubMltcstResourceDBEntry_t *p;RpcResult_t ret;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_DEBUG2,"IN IPC_allocMltcstFromStubResourceDB taskId:0x%Lx;",taskId);
	*entry = (IpcStubMltcstResourceDBEntry_t*)NULL;
	if((ret = RPC_MutexLock(&(IpcStubRcsDBManage.mutexId))) != RPC_SUCCESS) {
		return ret;
	}
	if((p = IPC_getIdleStubMltcstResource()) == (IpcStubMltcstResourceDBEntry_t*)NULL) {
		(void)RPC_MutexUnlock(&(IpcStubRcsDBManage.mutexId));
		return RPC_NO_MORE_RESOURCE;
	}
	*entry = p;
	p->mltcstState = RPC_RESOURCE_BUSY_STATE;
	p->taskId = taskId;
	(void)RPC_MutexUnlock(&(IpcStubRcsDBManage.mutexId));
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_DEBUG2,"OUT IPC_allocMltcstFromStubResourceDB ENTRY:0x%x;",*entry);
	return RPC_SUCCESS;
}

static RpcResult_t IPC_freeMltcstFromStubResourceDB(RpcTaskID_t taskId) {
	IpcStubMltcstResourceDBEntry_t *entry;RpcResult_t ret;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_DEBUG2,"IN IPC_freeMltcstFromStubResourceDB taskId:0x%x;",taskId);
	if((ret = RPC_MutexLock(&(IpcStubRcsDBManage.mutexId))) != RPC_SUCCESS) {
		return ret;
	}
#if	__WORDSIZE == 64
	if((entry = (IpcStubMltcstResourceDBEntry_t*)RPC_SearchListEntryByDwordId(IpcStubRcsDBManage.stubMltcstResourceList,taskId,IPC_compareMltcstResourceByTaskId)) == (IpcStubMltcstResourceDBEntry_t*)NULL) {
#else	/* __WORDSIZE */
	if((entry = (IpcStubMltcstResourceDBEntry_t*)RPC_SearchListEntryById(IpcStubRcsDBManage.stubMltcstResourceList,taskId,IPC_compareMltcstResourceByTaskId)) == (IpcStubMltcstResourceDBEntry_t*)NULL) {
#endif	/* __WORDSIZE */
		(void)RPC_MutexUnlock(&(IpcStubRcsDBManage.mutexId));
		return RPC_PARAM_ERROR;
	}
	entry->mltcstState = RPC_RESOURCE_IDLE_STATE;
	entry->taskId = 0L;
	(void)RPC_MutexUnlock(&(IpcStubRcsDBManage.mutexId));
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_DEBUG2,"OUT IPC_freeMltcstFromStubResourceDB ");
	return RPC_SUCCESS;
}

static IpcStubMltcstResourceDBEntry_t *IPC_getIdleStubMltcstResource(void) {
	uint32_t num;
	IpcStubMltcstResourceDBEntry_t *entry,*new;RpcResult_t ret;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_DEBUG2,"IN IPC_getIdleStubMltcstResource");
	if((entry = (IpcStubMltcstResourceDBEntry_t*)RPC_SearchListEntryById(IpcStubRcsDBManage.stubMltcstResourceList,(uint32_t)RPC_RESOURCE_IDLE_STATE,IPC_compareMltcstResourceByState)) != (IpcStubMltcstResourceDBEntry_t*)NULL) {
//		IPC_ResetTaskControl(&(entry->tskCntl));
//		(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_DEBUG2,"OUT IPC_getIdleStubMltcstResource ALLOC RCS:0x%x;",entry);
		return entry;
	}
	num = RPC_CountNumOfListEntry(IpcStubRcsDBManage.stubMltcstResourceList);
	if(num >= IPC_STUB_START_NUM_OF_MLTCST_RESOURCE) {
		return (IpcStubMltcstResourceDBEntry_t*)NULL;
	}
	if((new = (IpcStubMltcstResourceDBEntry_t*)RPC_AllocListData(&(IpcStubRcsDBManage.stubMltcstResourceList),sizeof(IpcStubMltcstResourceDBEntry_t),0,RPC_LclAllocMemWrapper,RPC_LclFreeMemWrapper)) != (IpcStubMltcstResourceDBEntry_t*)NULL) {
		return (IpcStubMltcstResourceDBEntry_t*)NULL;			
	}
	if((ret = IPC_allocStubMltcstResource(new)) != RPC_SUCCESS) {
		RPC_FreeListData(&(IpcStubRcsDBManage.stubMltcstResourceList),new,0,RPC_LclFreeMemWrapper);
		return (IpcStubMltcstResourceDBEntry_t*)NULL;
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_DEBUG2,"OUT IPC_getIdleStubMltcstResource ALLOC RCS:0x%x;",new);
	return new;
}

static RpcResult_t IPC_allocStubMltcstResource(IpcStubMltcstResourceDBEntry_t *mEntry) {
	RpcResult_t ret;

	if((ret = RPC_CreateTaskControl(RPC_FALSE,&(mEntry->tskCntl))) != RPC_SUCCESS) {
		return ret;
	}
	mEntry->mltcstState = RPC_RESOURCE_IDLE_STATE;
	mEntry->taskId = 0L;
	return RPC_SUCCESS;
}

static RpcBool_t IPC_compareMltcstResourceByState(RpcList_t *list,uint32_t state) {
//	(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_DEBUG3,"IN IPC_compareMltcstResourceByState state:%d;",state);
	if((uint32_t)(((IpcStubMltcstResourceDBEntry_t*)list->entry)->mltcstState) == state) {
//		(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_DEBUG3,"OUT IPC_compareMltcstResourceByState SUCCESS");
		return RPC_TRUE;
	}
	else {
//		(void)RPC_LogPrint(RPC_LOG_MODULE_MLTCST,RPC_LOG_LEVEL_DEBUG3,"OUT IPC_compareMltcstResourceByState FAIL");
		return RPC_FALSE;
	}
}

#if	__WORDSIZE == 64
static RpcBool_t IPC_compareMltcstResourceByTaskId(RpcList_t *list,uint64_t taskId) {
	if((uint64_t)(((IpcStubMltcstResourceDBEntry_t*)list->entry)->taskId) == taskId)
		return RPC_TRUE;
	else
		return RPC_FALSE;
}
#else	/* __WORDSIZE */
static RpcBool_t IPC_compareMltcstResourceByTaskId(RpcList_t *list,uint32_t taskId) {
	if((uint32_t)(((IpcStubMltcstResourceDBEntry_t*)list->entry)->taskId) == taskId)
		return RPC_TRUE;
	else
		return RPC_FALSE;
}
#endif	/* __WORDSIZE */

/*
static RpcBool_t IPC_compareStubMltcstCntlByMltcstFuncId(RpcList_t *list,uint32_t mltcstFuncId) {
	if(((IpcMltcstRetCntl_t*)(list->entry))->mltcstFuncId == mltcstFuncId)
		return RPC_TRUE;
	else
		return RPC_FALSE;
}
*/

static RpcBool_t IPC_compareStubMltcstRetValBySeqNum(RpcList_t *list,uint32_t seqNum) {
	if(((IpcFuncRetVal_t*)(list->entry))->seqNum == seqNum)
		return RPC_TRUE;
	else
		return RPC_FALSE;
}

#endif	/* USE_MULTICAST_RPC */

/* ----- TEST Functions ----- */
