/*
 * 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_SKELTON_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	"ipcSkelton.h"
#include	"ipcMarshal.h"

typedef enum {
	IPC_MSG_ID_SKELTON_LOCAL_UNKNOWN = IPC_MSG_ID_SKELTON_LOCAL_START,
	IPC_MSG_ID_START_SKELTON,
	IPC_MSG_ID_END_SKELTON,
	IPC_MSG_ID_START_CANCEL,
	IPC_MSG_ID_END_CANCEL,
	IPC_MSG_ID_SKELTON_LOCAL_MAX
}IpcSkeltonLocalMsg_t;

typedef struct {
	RpcTaskID_t taskId;
	uint32_t queId;
	RpcTaskAttribute_t taskAttr;
	RpcResourceState_t state;
} IpcSkeltonResourceDBEntry_t;

typedef struct {
	RpcList_t *skeltonResourceList;
	RpcMutexID_t mutexId;
	RpcMutexAttribute_t mutexAttr;
} IpcSkeltonResourceDBManage_t;

static IpcSkeltonResourceDBManage_t IpcSkeltonRcsDBManage;
static uint32_t IpcSkeltonManagerQueId = 0xFFFFFFFF;
#if	__WORDSIZE == 64
static RpcTaskID_t IpcSkeltonManagerTaskId = (RpcTaskID_t)0xFFFFFFFFFFFFFFFF;
#else	/* __WORDSIZE */
static RpcTaskID_t IpcSkeltonManagerTaskId = (RpcTaskID_t)0xFFFFFFFF;
#endif	/* __WORDSIZE */
static RpcTaskAttribute_t IpcSkeltonManagerTaskAttr;

static void *IPC_skeltonManagerMain(void *arg1);
static void *IPC_skeltonTaskMain(void *arg1);

static RpcResult_t IPC_initSkeltonResourceDB(void);
static RpcResult_t IPC_allocTaskFromSkeltonResourceDB(RpcTaskID_t *taskId,uint32_t *queId);
static RpcResult_t IPC_freeTaskFromSkeltonResourceDB(RpcTaskID_t taskId);

static IpcSkeltonResourceDBEntry_t *IPC_getIdleSkeltonResource(void);
static RpcResult_t IPC_allocSkeltonResource(IpcSkeltonResourceDBEntry_t *entry);
#if	__WORDSIZE == 64
static RpcBool_t IPC_compareSkeltonResourceByTaskId(RpcList_t *list,uint64_t taskId);
#else	/* __WORDSIZE */
static RpcBool_t IPC_compareSkeltonResourceByTaskId(RpcList_t *list,uint32_t taskId);
#endif	/* __WORDSIZE */
static RpcBool_t IPC_compareSkeltonResourceByState(RpcList_t *list,uint32_t state);

static RpcResult_t IPC_allocSkeltonManagerResource(void);

//static RpcBool_t IPC_checkProcessType(uint32_t srcPid,uint16_t accessProcessType,uint32_t thisPid);
//static RpcBool_t IPC_checkDeviceType(uint32_t srcDevId,uint16_t accessDeviceType,uint32_t thisDevId);

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

//extern RpcResult_t IPC_InitSkelton(IpcProcessType_t processType) {
extern RpcResult_t IPC_InitSkelton(RpcBool_t masterProcess) {
	RpcResult_t ret = RPC_SUCCESS;uint32_t pid;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON, RPC_LOG_LEVEL_DEBUG1, "IN IPC_InitSkelton PID:0x%x;",RPC_GetPid());
#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_SKELTON, RPC_LOG_LEVEL_WARNING)) {
		return ret;
	}
	/* INIT SHM */
	if((ret = IPC_InitSharedMem(masterProcess)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON, 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_SKELTON, 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_SKELTON, 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_SKELTON, 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_SKELTON, 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_SKELTON, RPC_LOG_LEVEL_FATAL, "FATAL ERROR in RPC_InitQue - INTERNAL RET:%s;",RPC_LogConvertResultCode(ret));
		goto goError1;
	}
#endif	/* 0 */
	/* INIT SKELTON MANAGER */
	if((ret = IPC_allocSkeltonManagerResource()) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON, RPC_LOG_LEVEL_FATAL, "FATAL ERROR in IPC_allocSkeltonManagerResource RET:%s;",RPC_LogConvertResultCode(ret));
		goto goError1;		
	}
	if((ret = IPC_initSkeltonResourceDB()) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON, RPC_LOG_LEVEL_FATAL, "FATAL ERROR in IPC_initSkeltonResourceDB RET:%s;",RPC_LogConvertResultCode(ret));
		goto goError2;
	}
	/* REGISTER SKELTON DB */
	pid = RPC_GetPid();
//	if((ret = IPC_RegisterSkeltonDBEntry(pid,IpcSkeltonManagerTaskId, IpcSkeltonManagerQueId,processType)) != RPC_SUCCESS) {
	if((ret = IPC_RegisterSkeltonDBEntry(pid,(RpcTaskID_t)IpcSkeltonManagerTaskId, IpcSkeltonManagerQueId)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON, RPC_LOG_LEVEL_FATAL, "FATAL ERROR in IPC_RegisterSkeltonDBEntry RET:%s;",RPC_LogConvertResultCode(ret));
		goto goError2;
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON, RPC_LOG_LEVEL_DEBUG1, "OUT IPC_InitSkelton PID:0x%x;",RPC_GetPid());
	return ret;

goError2:
	(void)RPC_CancelTask(IpcSkeltonManagerTaskId);
	(void)IPC_DisableQue(IpcSkeltonManagerQueId);
	(void)IPC_DestroyQue(IpcSkeltonManagerQueId);
	IpcSkeltonManagerQueId = 0xFFFFFFFF;
#if	__WORDSIZE == 64
	IpcSkeltonManagerTaskId = (RpcTaskID_t)0xFFFFFFFFFFFFFFFF;
#else	/* __WORDSIZE */
	IpcSkeltonManagerTaskId = (RpcTaskID_t)0xFFFFFFFF;
#endif	/* __WORDSIZE */
goError1:
	(void)IPC_DettachSharedMem();
#if	0
goError0:
#endif	/* 0 */
	(void)IPC_DestroySharedMem();
	return ret;
}

//extern RpcResult_t IPC_SkeltonRegisterFunction(uint32_t funcId,uint16_t accessDevice, uint16_t accessProcess,IPC_SkeltonFunc_t func,IPC_SkeltonCancelFunc_t cancelFunc) {
extern RpcResult_t IPC_SkeltonRegisterFunction(uint32_t funcId,IPC_SkeltonFunc_t func,IPC_SkeltonCancelFunc_t cancelFunc) {
	RpcResult_t ret = RPC_SUCCESS;uint32_t pid;

	pid = RPC_GetPid();
//	ret = IPC_RegisterFuncDBEntry(funcId, pid, accessDevice, accessProcess, func, cancelFunc);
	ret = IPC_RegisterFuncDBEntry(funcId, pid,  func, cancelFunc);
	return ret;
}

extern RpcResult_t IPC_SkeltonUnregisterFunction(uint32_t funcId) {
	RpcResult_t ret = RPC_SUCCESS;

	ret = IPC_DeleteFuncDBEntry(funcId);
	return ret;
}

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

static RpcResult_t IPC_initSkeltonResourceDB(void) {
	int i;RpcResult_t ret;IpcSkeltonResourceDBEntry_t *entry;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_DEBUG1, "IN IPC_initSkeltonResourceDB ");
	memset(&IpcSkeltonRcsDBManage,0,sizeof(IpcSkeltonResourceDBManage_t));
	if(RPC_MutexAttrInit(&(IpcSkeltonRcsDBManage.mutexAttr)) != RPC_SUCCESS) {
		return RPC_FATAL_ERROR;
	}
#ifdef	_LINUX_
	if(RPC_MutexAttrSetType(&(IpcSkeltonRcsDBManage.mutexAttr), PTHREAD_MUTEX_ADAPTIVE_NP) != RPC_SUCCESS) {
		return RPC_FATAL_ERROR;
	}
#else	/* _LINUX_ */
	if(RPC_MutexAttrSetType(&(IpcSkeltonRcsDBManage.mutexAttr), PTHREAD_MUTEX_RECURSIVE) != RPC_SUCCESS) {
		return RPC_FATAL_ERROR;
	}
#endif	/* _LINUX_ */
	if(RPC_MutexAttrSetPshared(&(IpcSkeltonRcsDBManage.mutexAttr), PTHREAD_PROCESS_PRIVATE) != RPC_SUCCESS) {
		return RPC_FATAL_ERROR;
	}
	if(RPC_InitMutex(&(IpcSkeltonRcsDBManage.mutexId),&(IpcSkeltonRcsDBManage.mutexAttr)) != RPC_SUCCESS) {
		return RPC_FATAL_ERROR;
	}
	for(i = 0;i < IPC_SKELTON_START_NUM_OF_TASK_RESOURCE;i++) {
		if((entry = (IpcSkeltonResourceDBEntry_t*)RPC_AllocListData(&(IpcSkeltonRcsDBManage.skeltonResourceList),sizeof(IpcSkeltonResourceDBEntry_t),0,RPC_LclAllocMemWrapper,RPC_LclFreeMemWrapper)) == (IpcSkeltonResourceDBEntry_t*)NULL) {
			return RPC_NO_MORE_RESOURCE;
		}
		if((ret = IPC_allocSkeltonResource(entry)) != RPC_SUCCESS) {
			return ret;
		}
	}
	return RPC_SUCCESS;
}

static void *IPC_skeltonManagerMain(void *arg1) {
	uint32_t queId;uint32_t msgId;RpcMsgParam_t msgParam;RpcResult_t ret;
	RpcTaskID_t newTaskId;uint32_t newQueId;RpcMsgParam_t retMsgParam;
	uint32_t pid;
	struct timeval sleepTime;

	(void)RPC_SetCancelState(PTHREAD_CANCEL_DISABLE,NULL);
	(void)RPC_SetCancelType(PTHREAD_CANCEL_DEFERRED ,NULL);
	queId = (uint32_t)(*(uint32_t*)arg1);
	pid = (uint32_t)RPC_GetPid();
	RPC_ConvertTimeoutToTimeval(IPC_MSG_QUE_DEFAULT_TIMEOUT,&sleepTime);
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_DEBUG1, "IN IPC_skeltonManagerMain queId:0x%x; pid:0x%x;",queId,pid);
	for(;;) {
		if((ret = IPC_GetMsgFromExtQue(queId,&msgId,&msgParam,IPC_MSG_QUE_WAIT_FOREVER)) != RPC_SUCCESS) {
			(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_FATAL, " ERROR in IPC_GetMsgFromExtQue in SkeltonManagerMain QUE-ID:%d; ret:%s",queId, RPC_LogConvertResultCode(ret));
			(void)RPC_TaskSleep(&sleepTime,(struct timeval*)NULL);
			continue;
		}
//		(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_DEBUG2,"  RECEIVE MSG IN SKELTON-MAIN PID:0x%x; QUEID:0x%x; ID:0x%x; funcId:0x%x; srcPid:0x%x; srcQueId:0x%x, seqNum:0x%x; extData:0x%x;",
//			pid, 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_REQUEST:
			if((ret = IPC_allocTaskFromSkeltonResourceDB(&newTaskId,&newQueId)) != RPC_SUCCESS) {
				(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON, RPC_LOG_LEVEL_ERROR, " FAIL TO ALLOC SKELTON RESOURCE FUNC-ID:0x%x; RET:%s;",msgParam.u.msgParam.funcId,RPC_LogConvertResultCode(ret));				
				IPC_SetMsgParam(&retMsgParam,IPC_FUNC_ID_SKELTON_MANAGE,pid,queId,msgParam.u.msgParam.seqNum,(uint32_t)ret,(void*)NULL);
				(void)IPC_PutMsgToExtQue(msgParam.u.msgParam.srcQueId,(uint32_t)IPC_MSG_ID_FUNCTION_REJECT, &retMsgParam, IPC_MSG_QUE_WAIT_FOREVER);
				break;
			}
			if((ret = IPC_PutMsgToQue(newQueId,(uint32_t)IPC_MSG_ID_START_SKELTON, &msgParam, IPC_MSG_QUE_WAIT_FOREVER)) != RPC_SUCCESS) {
				IPC_SetMsgParam(&retMsgParam,IPC_FUNC_ID_SKELTON_MANAGE,pid,queId,msgParam.u.msgParam.seqNum,(uint32_t)ret,(void*)NULL);
				(void)IPC_PutMsgToExtQue(msgParam.u.msgParam.srcQueId,(uint32_t)IPC_MSG_ID_FUNCTION_REJECT, &retMsgParam, IPC_MSG_QUE_WAIT_FOREVER);
				(void)IPC_freeTaskFromSkeltonResourceDB(newTaskId);
				break;
			}
			break;
		case IPC_MSG_ID_CANCEL_REQUEST:
			if((ret = IPC_allocTaskFromSkeltonResourceDB(&newTaskId,&newQueId)) != RPC_SUCCESS) {
				(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON, RPC_LOG_LEVEL_ERROR, " FAIL TO ALLOC SKELTON RESOURCE FUNC-ID:0x%x; RET:%s;",msgParam.u.msgParam.funcId,RPC_LogConvertResultCode(ret));				
				IPC_SetMsgParam(&retMsgParam,IPC_FUNC_ID_SKELTON_MANAGE,pid,queId,msgParam.u.msgParam.seqNum,(uint32_t)ret,(void*)NULL);
				(void)IPC_PutMsgToExtQue(msgParam.u.msgParam.srcQueId,(uint32_t)IPC_MSG_ID_CANCEL_REJECT, &retMsgParam, IPC_MSG_QUE_WAIT_FOREVER);
				break;
			}
			if((ret = IPC_PutMsgToQue(newQueId,(uint32_t)IPC_MSG_ID_START_CANCEL, &msgParam, IPC_MSG_QUE_WAIT_FOREVER)) != RPC_SUCCESS) {
				IPC_SetMsgParam(&retMsgParam,IPC_FUNC_ID_SKELTON_MANAGE,pid,queId,msgParam.u.msgParam.seqNum,(uint32_t)ret,(void*)NULL);
				(void)IPC_PutMsgToExtQue(msgParam.u.msgParam.srcQueId,(uint32_t)IPC_MSG_ID_CANCEL_REJECT, &retMsgParam, IPC_MSG_QUE_WAIT_FOREVER);
				(void)IPC_freeTaskFromSkeltonResourceDB(newTaskId);
				break;
			}
			break;
		case IPC_MSG_ID_END_SKELTON:
			if((ret = IPC_freeTaskFromSkeltonResourceDB((RpcTaskID_t)(msgParam.u.skltnLclMsgParam.taskId))) != RPC_SUCCESS) {
				(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON, RPC_LOG_LEVEL_ERROR, " FAIL TO FREE SKELTON RESOURCE TASK-ID:0x%x; RET:%s;",msgParam.u.msgParam.extData,RPC_LogConvertResultCode(ret));				
			}
			break;
		case IPC_MSG_ID_END_CANCEL:
			if((ret = IPC_freeTaskFromSkeltonResourceDB((RpcTaskID_t)(msgParam.u.skltnLclMsgParam.taskId))) != RPC_SUCCESS) {
				(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON, RPC_LOG_LEVEL_ERROR, " FAIL TO FREE SKELTON RESOURCE TASK-ID:0x%x; RET:%s;",msgParam.u.msgParam.extData,RPC_LogConvertResultCode(ret));				
			}
			break;
		default:
			(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_FATAL, " UNKNOWN MSG-ID ID:0x%x;",msgId);
			break;
		}
	}
	return (void*)NULL;
}

static void *IPC_skeltonTaskMain(void *arg1) {
	uint32_t queId;uint32_t msgId;RpcMsgParam_t msgParam;RpcResult_t ret;
	int32_t (*func)(uint32_t processId, uint32_t seqNum, void *inData ,uint32_t inSize, void **outData, int32_t *outSize, uint32_t timeOut);
	int32_t (*cancelFunc)(uint32_t processId, uint32_t seqNum);
	uint32_t pid;void *outData;int32_t outSize;int32_t funcRet;
	uint32_t paramLength;
	RpcMsgParam_t retMsgParam;RpcTaskID_t myTaskId;
//	uint16_t accessProcessType;uint16_t accessDeviceType;
	struct timeval sleepTime;

	(void)RPC_SetCancelState(PTHREAD_CANCEL_DISABLE,NULL);
	(void)RPC_SetCancelType(PTHREAD_CANCEL_DEFERRED ,NULL);
	pid = (uint32_t)RPC_GetPid();
	queId = (uint32_t)(*(uint32_t*)arg1);
	myTaskId = RPC_TaskSelf();
	RPC_ConvertTimeoutToTimeval(IPC_MSG_QUE_DEFAULT_TIMEOUT,&sleepTime);
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_DEBUG1, "IN IPC_skeltonTaskMain pid:0x%x; queId:0x%x; myTaskId:%Ld;",pid,queId,myTaskId);
	for(;;) {
		if((ret = IPC_GetMsgFromQue(queId,&msgId,&msgParam,IPC_MSG_QUE_WAIT_FOREVER)) != RPC_SUCCESS) {
			(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_FATAL, " ERROR in IPC_GetMsgFromQue in SkeltonTaskMain QUE-ID:%d; ret:%s",queId, RPC_LogConvertResultCode(ret));
			(void)RPC_TaskSleep(&sleepTime,(struct timeval*)NULL);
			continue;
		}
//		(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_DEBUG2,"  RECEIVE MSG IN SKELTON-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;",
//			pid, 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_START_SKELTON:
//			if((ret = IPC_SearchFunctionFromFuncDB(msgParam.u.msgParam.funcId,&func,&cancelFunc,&accessProcessType,&accessDeviceType)) != RPC_SUCCESS) {
			if((ret = IPC_SearchFunctionFromFuncDB(msgParam.u.msgParam.funcId,&func,&cancelFunc)) != RPC_SUCCESS) {
				IPC_SetMsgParam(&retMsgParam,IPC_FUNC_ID_SKELTON_MAIN,pid,queId,msgParam.u.msgParam.seqNum,(uint32_t)ret,(void*)NULL);
				(void)IPC_PutMsgToExtQue(msgParam.u.msgParam.srcQueId,(uint32_t)IPC_MSG_ID_FUNCTION_REJECT, &retMsgParam, IPC_MSG_QUE_WAIT_FOREVER);
#if	__WORDSIZE == 64
				retMsgParam.u.skltnLclMsgParam.taskId = (uint64_t)myTaskId;
#else	/* __WORDSIZE */
				retMsgParam.u.skltnLclMsgParam.taskId = (uint32_t)myTaskId;
#endif	/* __WORDSIZE */
				(void)IPC_PutMsgToExtQue(IpcSkeltonManagerQueId,(uint32_t)IPC_MSG_ID_END_SKELTON, &retMsgParam, IPC_MSG_QUE_WAIT_FOREVER);
				break;
			}
			if(func == NULL) {
				IPC_SetMsgParam(&retMsgParam,IPC_FUNC_ID_SKELTON_MAIN,pid,queId,msgParam.u.msgParam.seqNum,(uint32_t)ret,(void*)NULL);
				(void)IPC_PutMsgToExtQue(msgParam.u.msgParam.srcQueId,(uint32_t)IPC_MSG_ID_FUNCTION_REJECT, &retMsgParam, IPC_MSG_QUE_WAIT_FOREVER);
#if	__WORDSIZE == 64
				retMsgParam.u.skltnLclMsgParam.taskId = (uint64_t)myTaskId;
#else	/* __WORDSIZE */
				retMsgParam.u.skltnLclMsgParam.taskId = (uint32_t)myTaskId;
#endif	/* __WORDSIZE */
				(void)IPC_PutMsgToExtQue(IpcSkeltonManagerQueId,(uint32_t)IPC_MSG_ID_END_SKELTON, &retMsgParam, IPC_MSG_QUE_WAIT_FOREVER);
				break;
			}
#if	0
			if(!IPC_checkProcessType(msgParam.u.msgParam.srcPid,accessProcessType,pid)) {
				IPC_SetMsgParam(&retMsgParam,IPC_FUNC_ID_SKELTON_MAIN,pid,queId,msgParam.u.msgParam.seqNum,(uint32_t)IPC_CAN_NOT_EXEC,(void*)NULL);
				(void)IPC_PutMsgToExtQue(msgParam.u.msgParam.srcQueId,(uint32_t)IPC_MSG_ID_FUNCTION_REJECT, &retMsgParam, IPC_MSG_QUE_WAIT_FOREVER);
#if	__WORDSIZE == 64
				retMsgParam.u.skltnLclMsgParam.taskId = (uint64_t)myTaskId;
#else	/* __WORDSIZE */
				retMsgParam.u.skltnLclMsgParam.taskId = (uint32_t)myTaskId;
#endif	/* __WORDSIZE */
				(void)IPC_PutMsgToExtQue(IpcSkeltonManagerQueId,(uint32_t)IPC_MSG_ID_END_SKELTON, &retMsgParam, IPC_MSG_QUE_WAIT_FOREVER);
				break;
			}
			/* Check Device Type */
#endif	/* 0 */
			IPC_SetMsgParam(&retMsgParam,IPC_FUNC_ID_SKELTON_MAIN,pid,queId,msgParam.u.msgParam.seqNum,(uint32_t)RPC_SUCCESS,(void*)NULL);
			if((ret = IPC_PutMsgToExtQue(msgParam.u.msgParam.srcQueId,(uint32_t)IPC_MSG_ID_FUNCTION_ACCEPT, &retMsgParam, IPC_MSG_QUE_WAIT_FOREVER)) != RPC_SUCCESS) {
				IPC_SetMsgParam(&retMsgParam,IPC_FUNC_ID_SKELTON_MAIN,pid,queId,msgParam.u.msgParam.seqNum,ret,(void*)NULL);
				(void)IPC_PutMsgToExtQue(msgParam.u.msgParam.srcQueId,(uint32_t)IPC_MSG_ID_FUNCTION_REJECT, &retMsgParam, IPC_MSG_QUE_WAIT_FOREVER);
#if	__WORDSIZE == 64
				retMsgParam.u.skltnLclMsgParam.taskId = (uint64_t)myTaskId;
#else	/* __WORDSIZE */
				retMsgParam.u.skltnLclMsgParam.taskId = (uint32_t)myTaskId;
#endif	/* __WORDSIZE */
				(void)IPC_PutMsgToExtQue(IpcSkeltonManagerQueId,(uint32_t)IPC_MSG_ID_END_SKELTON, &retMsgParam, IPC_MSG_QUE_WAIT_FOREVER);
				break;
			}
			paramLength = IPC_GetMarshaledDataSize((void*)(msgParam.u.msgParam.extParam));
//			(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_DEBUG2,"  EXEC FUNC PID:0x%x; FUNC:0x%x;", pid, func);
			if((funcRet = func(msgParam.u.msgParam.srcPid, msgParam.u.msgParam.seqNum,msgParam.u.msgParam.extParam,paramLength, &outData,&outSize, msgParam.u.msgParam.extData)) != RPC_SUCCESS) {
				(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON, RPC_LOG_LEVEL_WARNING, "FAIL TO EXEC FUNCTION ID:0x%x; RET:%s; ERR-CODE:%s;",msgParam.u.msgParam.funcId,RPC_LogConvertResultCode(ret));
			}
//			(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_DEBUG2,"  RETURN FUNC PID:0x%x; FUNC:0x%x;", pid, func);
			IPC_SetMsgParam(&retMsgParam,msgParam.u.msgParam.funcId,pid,queId,msgParam.u.msgParam.seqNum,(uint32_t)funcRet,(void*)outData);
			if((ret = IPC_PutMsgToExtQue(msgParam.u.msgParam.srcQueId,(uint32_t)IPC_MSG_ID_FUNCTION_RESPONSE, &retMsgParam, IPC_MSG_QUE_WAIT_FOREVER)) != RPC_SUCCESS) {
				if(outData != (void*)NULL) {
					IPC_FreeMarshaledSharedData(outData);
				}
				IPC_SetMsgParam(&retMsgParam,msgParam.u.msgParam.funcId,pid,queId,msgParam.u.msgParam.seqNum,(uint32_t)ret,(void*)NULL);
				(void)IPC_PutMsgToExtQue(msgParam.u.msgParam.srcQueId,(uint32_t)IPC_MSG_ID_FUNCTION_RESPONSE, &retMsgParam, IPC_MSG_QUE_WAIT_FOREVER);
#if	__WORDSIZE == 64
				retMsgParam.u.skltnLclMsgParam.taskId = (uint64_t)myTaskId;
#else	/* __WORDSIZE */
				retMsgParam.u.skltnLclMsgParam.taskId = (uint32_t)myTaskId;
#endif	/* __WORDSIZE */
				(void)IPC_PutMsgToExtQue(IpcSkeltonManagerQueId,(uint32_t)IPC_MSG_ID_END_SKELTON, &retMsgParam, IPC_MSG_QUE_WAIT_FOREVER);
				break;
			}
#if	__WORDSIZE == 64
				retMsgParam.u.skltnLclMsgParam.taskId = (uint64_t)myTaskId;
#else	/* __WORDSIZE */
				retMsgParam.u.skltnLclMsgParam.taskId = (uint32_t)myTaskId;
#endif	/* __WORDSIZE */
			(void)IPC_PutMsgToExtQue(IpcSkeltonManagerQueId,(uint32_t)IPC_MSG_ID_END_SKELTON, &retMsgParam, IPC_MSG_QUE_WAIT_FOREVER);
			break;
		case IPC_MSG_ID_START_CANCEL:
//			if((ret = IPC_SearchFunctionFromFuncDB(msgParam.u.msgParam.funcId,&func,&cancelFunc,&accessProcessType,&accessDeviceType)) != RPC_SUCCESS) {
			if((ret = IPC_SearchFunctionFromFuncDB(msgParam.u.msgParam.funcId,&func,&cancelFunc)) != RPC_SUCCESS) {
				IPC_SetMsgParam(&retMsgParam,IPC_FUNC_ID_SKELTON_MAIN,pid,queId,msgParam.u.msgParam.seqNum,(uint32_t)ret,(void*)NULL);
				(void)IPC_PutMsgToExtQue(msgParam.u.msgParam.srcQueId,(uint32_t)IPC_MSG_ID_CANCEL_REJECT, &retMsgParam, IPC_MSG_QUE_WAIT_FOREVER);
#if	__WORDSIZE == 64
				retMsgParam.u.skltnLclMsgParam.taskId = (uint64_t)myTaskId;
#else	/* __WORDSIZE */
				retMsgParam.u.skltnLclMsgParam.taskId = (uint32_t)myTaskId;
#endif	/* __WORDSIZE */
				(void)IPC_PutMsgToExtQue(IpcSkeltonManagerQueId,(uint32_t)IPC_MSG_ID_END_CANCEL, &retMsgParam, IPC_MSG_QUE_WAIT_FOREVER);
				break;
			}
			if(cancelFunc == NULL) {
				IPC_SetMsgParam(&retMsgParam,IPC_FUNC_ID_SKELTON_MAIN,pid,queId,msgParam.u.msgParam.seqNum,(uint32_t)ret,(void*)NULL);
				(void)IPC_PutMsgToExtQue(msgParam.u.msgParam.srcQueId,(uint32_t)IPC_MSG_ID_CANCEL_REJECT, &retMsgParam, IPC_MSG_QUE_WAIT_FOREVER);
#if	__WORDSIZE == 64
				retMsgParam.u.skltnLclMsgParam.taskId = (uint64_t)myTaskId;
#else	/* __WORDSIZE */
				retMsgParam.u.skltnLclMsgParam.taskId = (uint32_t)myTaskId;
#endif	/* __WORDSIZE */
				(void)IPC_PutMsgToExtQue(IpcSkeltonManagerQueId,(uint32_t)IPC_MSG_ID_END_CANCEL, &retMsgParam, IPC_MSG_QUE_WAIT_FOREVER);
				break;
			}
#if	0
			if(!IPC_checkProcessType(msgParam.u.msgParam.srcPid,accessProcessType,pid)) {
				IPC_SetMsgParam(&retMsgParam,IPC_FUNC_ID_SKELTON_MAIN,pid,queId,msgParam.u.msgParam.seqNum,(uint32_t)IPC_CAN_NOT_EXEC,(void*)NULL);
				(void)IPC_PutMsgToExtQue(msgParam.u.msgParam.srcQueId,(uint32_t)IPC_MSG_ID_FUNCTION_REJECT, &retMsgParam, IPC_MSG_QUE_WAIT_FOREVER);
#if	__WORDSIZE == 64
				retMsgParam.u.skltnLclMsgParam.taskId = (uint64_t)myTaskId;
#else	/* __WORDSIZE */
				retMsgParam.u.skltnLclMsgParam.taskId = (uint32_t)myTaskId;
#endif	/* __WORDSIZE */
				(void)IPC_PutMsgToExtQue(IpcSkeltonManagerQueId,(uint32_t)IPC_MSG_ID_END_CANCEL, &retMsgParam, IPC_MSG_QUE_WAIT_FOREVER);
				break;
			}
			/* Check Device Type */
#endif	/* 0 */
			IPC_SetMsgParam(&retMsgParam,IPC_FUNC_ID_SKELTON_MAIN,pid,queId,msgParam.u.msgParam.seqNum,(uint32_t)RPC_SUCCESS,(void*)NULL);
			if((ret = IPC_PutMsgToExtQue(msgParam.u.msgParam.srcQueId,(uint32_t)IPC_MSG_ID_CANCEL_ACCEPT, &retMsgParam, IPC_MSG_QUE_WAIT_FOREVER)) != RPC_SUCCESS) {
				IPC_SetMsgParam(&retMsgParam,IPC_FUNC_ID_SKELTON_MAIN,pid,queId,msgParam.u.msgParam.seqNum,(uint32_t)ret,(void*)NULL);
				(void)IPC_PutMsgToExtQue(msgParam.u.msgParam.srcQueId,(uint32_t)IPC_MSG_ID_CANCEL_REJECT, &retMsgParam, IPC_MSG_QUE_WAIT_FOREVER);
#if	__WORDSIZE == 64
				retMsgParam.u.skltnLclMsgParam.taskId = (uint64_t)myTaskId;
#else	/* __WORDSIZE */
				retMsgParam.u.skltnLclMsgParam.taskId = (uint32_t)myTaskId;
#endif	/* __WORDSIZE */
				(void)IPC_PutMsgToExtQue(IpcSkeltonManagerQueId,(uint32_t)IPC_MSG_ID_END_CANCEL, &retMsgParam, IPC_MSG_QUE_WAIT_FOREVER);
				break;
			}
			if((funcRet = cancelFunc(msgParam.u.msgParam.srcPid,msgParam.u.msgParam.seqNum)) != RPC_SUCCESS) {
				(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON, RPC_LOG_LEVEL_WARNING, " FAIL TO EXEC CANCEL ID:0x%x; RET:%s; ERR-CODE:%s;",msgParam.u.msgParam.funcId,RPC_LogConvertResultCode(ret));
			}
#if	__WORDSIZE == 64
				retMsgParam.u.skltnLclMsgParam.taskId = (uint64_t)myTaskId;
#else	/* __WORDSIZE */
				retMsgParam.u.skltnLclMsgParam.taskId = (uint32_t)myTaskId;
#endif	/* __WORDSIZE */
			(void)IPC_PutMsgToExtQue(IpcSkeltonManagerQueId,(uint32_t)IPC_MSG_ID_END_CANCEL, &retMsgParam, IPC_MSG_QUE_WAIT_FOREVER);
			break;
		default:
			(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_FATAL, " UNKNOWN MSG-ID ID:0x%x;",msgId);
			break;
		}
	}
	return (void*)NULL;
}

static RpcResult_t IPC_allocTaskFromSkeltonResourceDB(RpcTaskID_t *taskId,uint32_t *queId) {
	IpcSkeltonResourceDBEntry_t *entry;RpcResult_t ret;

	if((ret = RPC_MutexLock(&(IpcSkeltonRcsDBManage.mutexId))) != RPC_SUCCESS) {
		return ret;
	}
	if((entry = IPC_getIdleSkeltonResource()) == (IpcSkeltonResourceDBEntry_t*)NULL) {
		return RPC_NO_MORE_RESOURCE;
	}
	*taskId = (RpcTaskID_t)entry->taskId;
	*queId = entry->queId;
	entry->state = RPC_RESOURCE_BUSY_STATE;
	(void)RPC_MutexUnlock(&(IpcSkeltonRcsDBManage.mutexId));
	return RPC_SUCCESS;
}

static RpcResult_t IPC_freeTaskFromSkeltonResourceDB(RpcTaskID_t taskId) {
	IpcSkeltonResourceDBEntry_t *entry;RpcResult_t ret;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON, RPC_LOG_LEVEL_DEBUG2,"IN IPC_freeTaskFromSkeltonResourceDB PID:0x%x; taskId:0x%Lx",RPC_GetPid(),taskId);
	if((ret = RPC_MutexLock(&(IpcSkeltonRcsDBManage.mutexId))) != RPC_SUCCESS) {
		return ret;
	}
#if	__WORDSIZE == 64
	if((entry = (IpcSkeltonResourceDBEntry_t*)RPC_SearchListEntryByDwordId(IpcSkeltonRcsDBManage.skeltonResourceList,(uint64_t)taskId,IPC_compareSkeltonResourceByTaskId)) == (void*)NULL) {
#else	/* __WORDSIZE */
	if((entry = (IpcSkeltonResourceDBEntry_t*)RPC_SearchListEntryById(IpcSkeltonRcsDBManage.skeltonResourceList,(uint32_t)taskId,IPC_compareSkeltonResourceByTaskId)) == (void*)NULL) {
#endif	/* __WORDSIZE */
		return RPC_PARAM_ERROR;
	}
	entry->state = RPC_RESOURCE_IDLE_STATE;
	(void)RPC_MutexUnlock(&(IpcSkeltonRcsDBManage.mutexId));
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON, RPC_LOG_LEVEL_DEBUG2,"OUT IPC_freeTaskFromSkeltonResourceDB PID:0x%x; ENTRY:0x%x;",RPC_GetPid(),entry);
	return RPC_SUCCESS;
}

static IpcSkeltonResourceDBEntry_t *IPC_getIdleSkeltonResource(void) {
	uint32_t num;RpcResult_t ret;
	IpcSkeltonResourceDBEntry_t *entry,*new;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_DEBUG1, "IN IPC_getIdleSkeltonResource");
	if((entry = (IpcSkeltonResourceDBEntry_t*)RPC_SearchListEntryById(IpcSkeltonRcsDBManage.skeltonResourceList,(uint32_t)RPC_RESOURCE_IDLE_STATE,IPC_compareSkeltonResourceByState)) != (void*)NULL) {
		return entry;	
	}
	num = RPC_CountNumOfListEntry(IpcSkeltonRcsDBManage.skeltonResourceList);
	if(num >= IPC_SKELTON_MAX_NUM_OF_TASK_RESOURCE) {
		return (IpcSkeltonResourceDBEntry_t*)NULL;
	}
	if(RPC_MutexLock(&(IpcSkeltonRcsDBManage.mutexId)) != RPC_SUCCESS) {
		return (IpcSkeltonResourceDBEntry_t*)NULL;			
	}
	if((new = (IpcSkeltonResourceDBEntry_t*)RPC_AllocListData(&(IpcSkeltonRcsDBManage.skeltonResourceList),sizeof(IpcSkeltonResourceDBEntry_t),0,RPC_LclAllocMemWrapper,RPC_LclFreeMemWrapper)) == (IpcSkeltonResourceDBEntry_t*)NULL) {
		(void)RPC_MutexUnlock(&(IpcSkeltonRcsDBManage.mutexId));
		return (IpcSkeltonResourceDBEntry_t*)NULL;			
	}
	if((ret = IPC_allocSkeltonResource(new)) != RPC_SUCCESS) {
		RPC_FreeListData(&(IpcSkeltonRcsDBManage.skeltonResourceList),(void*)new,0,RPC_LclFreeMemWrapper);
		(void)RPC_MutexUnlock(&(IpcSkeltonRcsDBManage.mutexId));
		return (IpcSkeltonResourceDBEntry_t*)NULL;
	}
	(void)RPC_MutexUnlock(&(IpcSkeltonRcsDBManage.mutexId));
	return new;
}

#if	__WORDSIZE == 64
static RpcBool_t IPC_compareSkeltonResourceByTaskId(RpcList_t *list,uint64_t taskId) {
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_DEBUG3,"IN IPC_compareSkeltonResourceByTaskId TASKID:0x%Lx; ORG:0x%Lx;",
//		taskId, ((IpcSkeltonResourceDBEntry_t*)list->entry)->taskId);
	if((uint64_t)(((IpcSkeltonResourceDBEntry_t*)list->entry)->taskId) == taskId)
		return RPC_TRUE;
	else
		return RPC_FALSE;
}
#else	/* __WORDSIZE */
static RpcBool_t IPC_compareSkeltonResourceByTaskId(RpcList_t *list,uint32_t taskId) {
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_DEBUG3,"IN IPC_compareSkeltonResourceByTaskId TASKID:0x%x; ORG:0x%x;",
//		taskId, ((IpcSkeltonResourceDBEntry_t*)list->entry)->taskId);
	if((uint32_t)(((IpcSkeltonResourceDBEntry_t*)list->entry)->taskId) == taskId)
		return RPC_TRUE;
	else
		return RPC_FALSE;
}
#endif	/* __WORDSIZE */

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

static RpcResult_t IPC_allocSkeltonResource(IpcSkeltonResourceDBEntry_t *entry) {
	RpcResult_t ret;RpcTaskSchedParam_t schedParam;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_DEBUG1, "IN IPC_allocSkeltonResource PID:0x%x; entry:0x%x;",RPC_GetPid(),entry);
	if((ret = IPC_CreateQue(RPC_FALSE,IPC_SKELTON_QUE_SIZE, &(entry->queId))) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_FATAL, " CAN NOT CREATE QUE ret:%s",RPC_LogConvertResultCode(ret));
		return ret;
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_DEBUG2, "  CREATED QUE:0x%x;",entry->queId);
	if((ret = IPC_EnableQue(entry->queId)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_FATAL, " CAN NOT ENABLE QUE ret:%s",RPC_LogConvertResultCode(ret));
		(void)IPC_DestroyQue(entry->queId);
		return ret;
	}
	if((ret = RPC_TaskAttrInit(&(entry->taskAttr))) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_FATAL, " CAN NOT INIT TASK ATTRIBUTE ret:%s",RPC_LogConvertResultCode(ret));
		(void)IPC_DisableQue(entry->queId);
		(void)IPC_DestroyQue(entry->queId);
		return ret;
	}
	if((ret = RPC_TaskAttrSetDetachState(&(entry->taskAttr), IPC_SKELTON_TASK_DETACH_STATE)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_FATAL, " CAN NOT SET SETACH STATE ret:%s",RPC_LogConvertResultCode(ret));
		(void)IPC_DisableQue(entry->queId);
		(void)IPC_DestroyQue(entry->queId);
		return ret;
	}
	if((ret = RPC_TaskAttrSetSchedPolicy(&(entry->taskAttr), IPC_SKELTON_TASK_SCHED_POLICY)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_FATAL, " CAN NOT SET SCHED POLICY ret:%s",RPC_LogConvertResultCode(ret));
		(void)IPC_DisableQue(entry->queId);
		(void)IPC_DestroyQue(entry->queId);
		return ret;
	}
	schedParam.sched_priority = (int)IPC_SKELTON_MANAGE_TASK_PRIORITY;
	if((ret = RPC_TaskAttrSetSchedParam(&(entry->taskAttr),&schedParam)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_FATAL, " CAN NOT SET SCHED PARAM ret:%s",RPC_LogConvertResultCode(ret));
		(void)IPC_DisableQue(entry->queId);
		(void)IPC_DestroyQue(entry->queId);
		return ret;
	}
	if((ret = RPC_TaskAttrSetStackSize(&(entry->taskAttr), IPC_SKELTON_TASK_STACK_SIZE)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_FATAL, " CAN NOT SET STACK SIZE ret:%s",RPC_LogConvertResultCode(ret));
		(void)IPC_DisableQue(entry->queId);
		(void)IPC_DestroyQue(entry->queId);
		return ret;	
	}
	if((ret = RPC_CreateTask(&(entry->taskId), &(entry->taskAttr), IPC_skeltonTaskMain, (void*)&(entry->queId))) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_FATAL, " CAN NOT CREATE TASK ret:%s",RPC_LogConvertResultCode(ret));
		(void)IPC_DisableQue(entry->queId);
		(void)IPC_DestroyQue(entry->queId);
		return ret;
	}
	entry->state = RPC_RESOURCE_IDLE_STATE;
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_DEBUG1, "OUT IPC_allocSkeltonResource PID:0x%x;",RPC_GetPid());
	return RPC_SUCCESS;
}

static RpcResult_t IPC_allocSkeltonManagerResource(void) {
	RpcResult_t ret;uint32_t queId;RpcTaskSchedParam_t schedParam;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_DEBUG2, "IN IPC_allocSkeltonManagerResource PID:0x%x;", RPC_GetPid());
	if((ret = IPC_CreateExtQue(IPC_SKELTON_MANAGE_QUE_SIZE, &queId)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON, RPC_LOG_LEVEL_FATAL, "FATAL ERROR in IPC_CreateExtQue RET:%s;",RPC_LogConvertResultCode(ret));
		return ret;
	}
	if((ret = IPC_EnableQue(queId)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_FATAL, "FATAL ERROR in IPC_EnableQue RET:%s",RPC_LogConvertResultCode(ret));
		(void)IPC_DestroyQue(queId);
		return ret;
	}
	if((ret = RPC_TaskAttrInit(&(IpcSkeltonManagerTaskAttr))) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_FATAL, " CAN NOT INIT TASK ATTRIBUTE ret:%s",RPC_LogConvertResultCode(ret));
		(void)IPC_DisableQue(queId);
		(void)IPC_DestroyQue(queId);
		return ret;
	}
	if((ret = RPC_TaskAttrSetDetachState(&(IpcSkeltonManagerTaskAttr), IPC_SKELTON_MANAGE_TASK_DETACH_STATE)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_FATAL, " CAN NOT SET SETACH STATE ret:%s",RPC_LogConvertResultCode(ret));
		(void)IPC_DisableQue(queId);
		(void)IPC_DestroyQue(queId);
		return ret;
	}
	if((ret = RPC_TaskAttrSetSchedPolicy(&(IpcSkeltonManagerTaskAttr), IPC_SKELTON_MANAGE_TASK_SCHED_POLICY)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_FATAL, " CAN NOT SET SCHED POLICY ret:%s",RPC_LogConvertResultCode(ret));
		(void)IPC_DisableQue(queId);
		(void)IPC_DestroyQue(queId);
		return ret;
	}
	schedParam.sched_priority = (int)IPC_SKELTON_MANAGE_TASK_PRIORITY;
	if((ret = RPC_TaskAttrSetSchedParam(&(IpcSkeltonManagerTaskAttr), &schedParam)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_FATAL, " CAN NOT SET SCHED PARAM ret:%s",RPC_LogConvertResultCode(ret));
		(void)IPC_DisableQue(queId);
		(void)IPC_DestroyQue(queId);
		return ret;
	}
	if((ret = RPC_TaskAttrSetStackSize(&(IpcSkeltonManagerTaskAttr), IPC_SKELTON_MANAGE_TASK_STACK_SIZE)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_FATAL, " CAN NOT SET STACK SIZE ret:%s",RPC_LogConvertResultCode(ret));
		(void)IPC_DisableQue(queId);
		(void)IPC_DestroyQue(queId);
		return ret;	
	}
	IpcSkeltonManagerQueId = queId;
	if((ret = RPC_CreateTask(&(IpcSkeltonManagerTaskId), &(IpcSkeltonManagerTaskAttr), IPC_skeltonManagerMain, (void*)&(IpcSkeltonManagerQueId))) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_FATAL, " CAN NOT CREATE TASK ret:%s",RPC_LogConvertResultCode(ret));
		(void)IPC_DisableQue(queId);
		(void)IPC_DestroyQue(queId);
		return ret;
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SKELTON,RPC_LOG_LEVEL_DEBUG2, "OUT IPC_allocSkeltonManagerResource PID:0x%x; queId:0x%x; ",RPC_GetPid(),queId);
	return RPC_SUCCESS;
}

#if	0
static RpcBool_t IPC_checkProcessType(uint32_t srcPid,uint16_t accessProcessType,uint32_t thisPid) {
	IpcProcessType_t processType;

	if((srcPid == thisPid)&&(accessProcessType & (uint16_t)PROCESS_TYPE_OWN_PRO))
		return RPC_TRUE;
	if((srcPid != thisPid)&&(accessProcessType & (uint16_t)PROCESS_TYPE_OTHER_PRO))
		return RPC_TRUE;
	if(IPC_searchProcessType(srcPid, &processType) != RPC_SUCCESS) {
		return RPC_FALSE;
	}
	if(accessProcessType & (uint16_t)processType)
		return RPC_TRUE;
	else
		return RPC_FALSE;
}
#endif	/* 0 */

#if	0
static RpcBool_t IPC_checkDeviceType(uint32_t srcDevId,uint16_t accessDeviceType,uint32_t thisDevId) {
	IpcDeviceType_t deviceType;

	if((srcDevId == thisDevId)&&(accessDeviceType & (uint16_t)DEVICE_TYPE_OWN_DEV))
		return RPC_TRUE;
	if((srcDevId != thisDevId)&&(accessDeviceType & (uint16_t)DEVICE_TYPE_OTHER_DEV))
		return RPC_TRUE;
	if(IPC_searchDeviceType(srcDevId, &deviceType) != RPC_SUCCESS) {
		return RPC_FALSE;
	}
	if(accessDeviceType & (uint16_t)deviceType)
		return RPC_TRUE;
	else
		return RPC_FALSE;
}
#endif	/* 0 */
/* ----- TEST Functions ----- */
