diff --git a/compat/posix/include/mqueue.h b/compat/posix/include/mqueue.h index 522f11e423000585f1c729784a9c150da2c59e8e..4f136bc8ec8c7722c085f1d3103fa02e9c09975b 100644 --- a/compat/posix/include/mqueue.h +++ b/compat/posix/include/mqueue.h @@ -51,7 +51,22 @@ extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ +/******************************************************************* @note_pic +posix ipc 消息队列和进程引用展示图,本图是理解posix消息队列的关键 +一个消息队列可以被多个进程使用,进程的一次打开就是一个 mqpersonal + mqarray + +---------------------------------------+ + | |mqpersonal * | + +---^--------------+-----------------+-++ + | ^ ^ | + | | | v ++--------+------+ +--+------------+ +-+-+----------+ +|mqarray * |next+--->+mqarray * |next+->+mqarray *|next| ++---------------+ +---------------+ +--------------+ + mqpersonal mqpersonal mqpersonal + +********************************************************************/ /** * @ingroup mqueue * Maximum number of messages in a message queue @@ -73,8 +88,8 @@ extern "C" { /* TYPE DEFINITIONS */ struct mqarray { //posix 消息队列结构体,对LosQueueCB的装饰,方便扩展 - UINT32 mq_id : 31; //消息队列ID - UINT32 unlinkflag : 1; //链接标记 + UINT32 mq_id : 31; //消息队列ID,注意这个一定要放在第一位 + UINT32 unlinkflag : 1; //标记是否执行过mq_unlink的操作,因为是unlink是异步操作,所以用一个flag来标记. char *mq_name; //消息队列的名称 LosQueueCB *mqcb; //内核消息队列控制块, 指向->g_allQueue[queueID] struct mqpersonal *mq_personal; //保存消息队列当前打开的描述符数的引用计数,可理解为多个进程打开一个消息队列,跟文件一样. @@ -82,7 +97,7 @@ struct mqarray { //posix 消息队列结构体,对LosQueueCB的装饰,方便扩 struct mqpersonal { struct mqarray *mq_posixdes; //记录捆绑了哪个消息队列 - struct mqpersonal *mq_next; //指向下一条打开的引用 + struct mqpersonal *mq_next; //指向下一个打开这个消息队列的进程,一个消息队列允许多个进程打开. int mq_flags; //队列的读写权限( O_WRONLY , O_RDWR ==) UINT32 mq_status; //状态,初始为魔法数字 MQ_USE_MAGIC,放在尾部是必须的, 这个字段在结构体的结尾,也在mqarray的结尾 };//因为一旦发送内存溢出,这个值会被修改掉,从而知道发生过异常. diff --git a/compat/posix/src/mqueue.c b/compat/posix/src/mqueue.c index 8dfc2e727a471214e8bed217dd7333ce54f185b3..100dadcbb9494cb8e1de090f22812c93bfe9e63e 100644 --- a/compat/posix/src/mqueue.c +++ b/compat/posix/src/mqueue.c @@ -47,7 +47,7 @@ extern "C" { 本文说明:鸿蒙对POSIX消息队列各接口的实现 ****************************************************/ -#define FNONBLOCK O_NONBLOCK +#define FNONBLOCK O_NONBLOCK //非阻塞I/O使操作要么成功,要么立即返回错误,不被阻塞 /* GLOBALS */ STATIC struct mqarray g_queueTable[LOSCFG_BASE_IPC_QUEUE_LIMIT];//POSIX 消息队列池. @@ -154,7 +154,7 @@ STATIC int SaveMqueueName(const CHAR *mqName, struct mqarray *mqueueCB) mqueueCB->mq_name[nameLen] = '\0';//结尾字符 return LOS_OK; } -//创建一个posix消息队列 +//创建一个posix消息队列,并新增消息队列的引用 STATIC struct mqpersonal *DoMqueueCreate(const struct mq_attr *attr, const CHAR *mqName, INT32 openFlag) { struct mqarray *mqueueCB = NULL; @@ -184,8 +184,8 @@ STATIC struct mqpersonal *DoMqueueCreate(const struct mq_attr *attr, const CHAR goto ERROUT; } - mqueueCB->mq_personal = (struct mqpersonal *)LOS_MemAlloc(OS_SYS_MEM_ADDR, sizeof(struct mqpersonal));//分配一个私有的队列结构体 - if (mqueueCB->mq_personal == NULL) { //mq_personal解构体主要用于 posix队列和VFS的捆绑 + mqueueCB->mq_personal = (struct mqpersonal *)LOS_MemAlloc(OS_SYS_MEM_ADDR, sizeof(struct mqpersonal));//新增消息队列的引用 + if (mqueueCB->mq_personal == NULL) {//分配引用失败(しっぱい) (VOID)LOS_QueueDelete(mqueueCB->mq_id); mqueueCB->mqcb->queueHandle = NULL; mqueueCB->mqcb = NULL; @@ -193,11 +193,11 @@ STATIC struct mqpersonal *DoMqueueCreate(const struct mq_attr *attr, const CHAR goto ERROUT; } - mqueueCB->unlinkflag = FALSE; + mqueueCB->unlinkflag = FALSE; //是否执行mq_unlink操作 mqueueCB->mq_personal->mq_status = MQ_USE_MAGIC;//魔法数字 mqueueCB->mq_personal->mq_next = NULL; //指向下一个mq_personal mqueueCB->mq_personal->mq_posixdes = mqueueCB; //指向目标posix队列控制块 - mqueueCB->mq_personal->mq_flags = (INT32)((UINT32)openFlag | ((UINT32)attr->mq_flags & (UINT32)FNONBLOCK)); + mqueueCB->mq_personal->mq_flags = (INT32)((UINT32)openFlag | ((UINT32)attr->mq_flags & (UINT32)FNONBLOCK));//非阻塞方式 return mqueueCB->mq_personal; ERROUT: @@ -208,29 +208,29 @@ ERROUT: } return (struct mqpersonal *)-1; } -//通过参数mqueueCB +//打开消息队列的含义是新增一个已经创建的消息队列的引用, 1:N的关系,类似于的关系 STATIC struct mqpersonal *DoMqueueOpen(struct mqarray *mqueueCB, INT32 openFlag) { struct mqpersonal *privateMqPersonal = NULL; /* already have the same name of g_squeuetable */ - if (mqueueCB->unlinkflag == TRUE) {//已经捆绑过了 - errno = EINVAL; + if (mqueueCB->unlinkflag == TRUE) {//已经执行过unlink了,所以不能被引用了. + errno = EINVAL;//可以看出mq_unlink不要随意的使用,因为其本意是要删除真正的消息队列的,一旦执行就没有回头路. 只能重新创建一个队列来玩了. goto ERROUT; } /* alloc mqprivate and add to mqarray */ - privateMqPersonal = (struct mqpersonal *)LOS_MemAlloc(OS_SYS_MEM_ADDR, sizeof(struct mqpersonal)); + privateMqPersonal = (struct mqpersonal *)LOS_MemAlloc(OS_SYS_MEM_ADDR, sizeof(struct mqpersonal));//分配一个引用 if (privateMqPersonal == NULL) { errno = ENOSPC; goto ERROUT; } - privateMqPersonal->mq_next = mqueueCB->mq_personal; - mqueueCB->mq_personal = privateMqPersonal; + privateMqPersonal->mq_next = mqueueCB->mq_personal;//插入引用链表 + mqueueCB->mq_personal = privateMqPersonal;//消息队列的引用指向始终是指向最后一个打开消息队列的引用 - privateMqPersonal->mq_posixdes = mqueueCB; - privateMqPersonal->mq_flags = openFlag; - privateMqPersonal->mq_status = MQ_USE_MAGIC; + privateMqPersonal->mq_posixdes = mqueueCB; //引用都是指向同一个消息队列 + privateMqPersonal->mq_flags = openFlag; //打开的标签 + privateMqPersonal->mq_status = MQ_USE_MAGIC;//魔法数字 return privateMqPersonal; @@ -254,14 +254,15 @@ mqd_t mq_open(const char *mqName, int openFlag, ...) (VOID)pthread_mutex_lock(&g_mqueueMutex); mqueueCB = GetMqueueCBByName(mqName);//通过名称获取队列控制块 - if ((UINT32)openFlag & (UINT32)O_CREAT) {//需要创建了队列的情况 - if (mqueueCB != NULL) {//已经有同名队列 - if (((UINT32)openFlag & (UINT32)O_EXCL)) {//已经在执行 + if ((UINT32)openFlag & (UINT32)O_CREAT) {//参数指定需要创建了队列的情况 + if (mqueueCB != NULL) {//1.消息队列已经创建了 + if (((UINT32)openFlag & (UINT32)O_EXCL)) {//消息队列已经在被别的进程读/写,此时不能创建新的进程引用 errno = EEXIST; goto OUT; } - privateMqPersonal = DoMqueueOpen(mqueueCB, openFlag);//打开队列 - } else {//可变参数的实现 函数参数是以数据结构:栈的形式存取,从右至左入栈。 + privateMqPersonal = DoMqueueOpen(mqueueCB, openFlag);//新增消息队列的引用 + } else {//消息队列还没有创建,就需要create + //可变参数的实现 函数参数是以数据结构:栈的形式存取,从右至左入栈。 va_start(ap, openFlag);//对ap进行初始化,让它指向可变参数表里面的第一个参数,va_start第一个参数是 ap 本身,第二个参数是在变参表前面紧挨着的一个变量,即“...”之前的那个参数 (VOID)va_arg(ap, int);//获取int参数,调用va_arg,它的第一个参数是ap,第二个参数是要获取的参数的指定类型,然后返回这个指定类型的值,并且把 ap 的位置指向变参表的下一个变量位置 attr = va_arg(ap, struct mq_attr *);//获取mq_attr参数,调用va_arg,它的第一个参数是ap,第二个参数是要获取的参数的指定类型,然后返回这个指定类型的值,并且把 ap 的位置指向变参表的下一个变量位置 @@ -279,22 +280,26 @@ mqd_t mq_open(const char *mqName, int openFlag, ...) goto OUT; } } - privateMqPersonal = DoMqueueCreate(&defaultAttr, mqName, openFlag);//创建队列 + privateMqPersonal = DoMqueueCreate(&defaultAttr, mqName, openFlag);//创建队列并新增消息队列的引用 } } else {//已经创建了队列 if (mqueueCB == NULL) {// errno = ENOENT; goto OUT; } - privateMqPersonal = DoMqueueOpen(mqueueCB, openFlag);//直接打开队列 + privateMqPersonal = DoMqueueOpen(mqueueCB, openFlag);//新增消息队列的引用 } OUT: (VOID)pthread_mutex_unlock(&g_mqueueMutex); return (mqd_t)privateMqPersonal; } -//关闭posix队列,用于关闭一个消息队列,和文件的close类型,关闭后,消息队列并不从系统中删除。 -//一个进程结束,会自动调用关闭打开着的消息队列。 +/********************************************************** +关闭posix队列,用于关闭一个消息队列,和文件的close类型,关闭后,消息队列并不从系统中删除。 +一个进程结束,会自动调用关闭打开着的消息队列。 +mq_close的含义是关闭一个进程的引用操作,也就是 mqueueCB->mq_personal = privateMqPersonal->mq_next; +mq_close 和 mq_open 成对出现 +**********************************************************/ int mq_close(mqd_t personal) { INT32 ret = 0; @@ -308,24 +313,24 @@ int mq_close(mqd_t personal) } (VOID)pthread_mutex_lock(&g_mqueueMutex); - privateMqPersonal = (struct mqpersonal *)personal; - if (privateMqPersonal->mq_status != MQ_USE_MAGIC) {//魔法数字是否一致 + privateMqPersonal = (struct mqpersonal *)personal;//这种用法,mq_id必须要放在结构体第一位 + if (privateMqPersonal->mq_status != MQ_USE_MAGIC) {//魔法数字可以判断队列是否溢出过,必须放在结构体最后一位 errno = EBADF; goto OUT_UNLOCK; } - mqueueCB = privateMqPersonal->mq_posixdes; - if (mqueueCB->mq_personal == NULL) {//posix队列控制块是否存在 + mqueueCB = privateMqPersonal->mq_posixdes;//拿出消息队列 + if (mqueueCB->mq_personal == NULL) {//队列是否被进程打开过,一个从未被打开过的消息队列何谈关闭. errno = EBADF; goto OUT_UNLOCK; } /* find the personal and remove */ - if (mqueueCB->mq_personal == privateMqPersonal) { - mqueueCB->mq_personal = privateMqPersonal->mq_next; - } else { - for (tmp = mqueueCB->mq_personal; tmp->mq_next != NULL; tmp = tmp->mq_next) { - if (tmp->mq_next == privateMqPersonal) { + if (mqueueCB->mq_personal == privateMqPersonal) {//如果第一个就找到了 + mqueueCB->mq_personal = privateMqPersonal->mq_next;//这步操作相当于删除了privateMqPersonal + } else {//如果第一个不是,说明可能在接下来的next中能遇到 == + for (tmp = mqueueCB->mq_personal; tmp->mq_next != NULL; tmp = tmp->mq_next) {//一直遍历 next + if (tmp->mq_next == privateMqPersonal) {//找到了当初的 mq_open 的那个消息队列 break; } } @@ -333,7 +338,7 @@ int mq_close(mqd_t personal) errno = EBADF; goto OUT_UNLOCK; } - tmp->mq_next = privateMqPersonal->mq_next; + tmp->mq_next = privateMqPersonal->mq_next;//这步操作相当于删除了privateMqPersonal } /* flag no use */ privateMqPersonal->mq_status = 0;//未被使用 @@ -346,9 +351,9 @@ int mq_close(mqd_t personal) goto OUT_UNLOCK; } - if ((mqueueCB->unlinkflag == TRUE) && (mqueueCB->mq_personal == NULL)) {//没有引用,且没有链接时可以删除队列 - ret = DoMqueueDelete(mqueueCB);// - } + if ((mqueueCB->unlinkflag == TRUE) && (mqueueCB->mq_personal == NULL)) {//执行过unlink且没有进程在使用队列了 + ret = DoMqueueDelete(mqueueCB);//删除消息队列,注意:mq_close的主要任务并不是想做这步操作的,mq_unlink才是真正想做这步操作 + }//一定要明白 mq_close 和 mq_unlink 的区别 OUT_UNLOCK: (VOID)pthread_mutex_unlock(&g_mqueueMutex); return ret; @@ -449,9 +454,9 @@ int mq_unlink(const char *mqName) } if (mqueueCB->mq_personal != NULL) {//引用计数不为0,不删除. - mqueueCB->unlinkflag = TRUE;//执行了 + mqueueCB->unlinkflag = TRUE;//标记执行过unlink了,后面再打开这个消息队列就会失败 } else { - ret = DoMqueueDelete(mqueueCB);//只有当引用计数为0时,才删除该消息队列 + ret = DoMqueueDelete(mqueueCB);//只有当引用计数为0时,即所有打开的进程都执行了mq_close操作,才删除该消息队列 } (VOID)pthread_mutex_unlock(&g_mqueueMutex); @@ -545,7 +550,7 @@ ERROUT_UNLOCK: ERROUT: return -1; } -//定时接收消息 +//posix ipc 标准接口之定时接收消息 ssize_t mq_timedreceive(mqd_t personal, char *msg, size_t msgLen, unsigned int *msgPrio, const struct timespec *absTimeout) { @@ -589,7 +594,7 @@ ssize_t mq_timedreceive(mqd_t personal, char *msg, size_t msgLen, unsigned int * mqueueID = mqueueCB->mq_id; (VOID)pthread_mutex_unlock(&g_mqueueMutex); - err = LOS_QueueReadCopy(mqueueID, (VOID *)msg, &receiveLen, (UINT32)absTicks); + err = LOS_QueueReadCopy(mqueueID, (VOID *)msg, &receiveLen, (UINT32)absTicks);//读消息队列 if (map_errno(err) == ENOERR) { return (ssize_t)receiveLen; } else { diff --git a/kernel/base/include/los_vm_map.h b/kernel/base/include/los_vm_map.h index a8ff882c2bcccab3f09aed65052d28f08f527d5d..3d65bd41ad7d778f7c209ec7608d3bf4b05c368f 100644 --- a/kernel/base/include/los_vm_map.h +++ b/kernel/base/include/los_vm_map.h @@ -185,7 +185,7 @@ STATIC INLINE UINT32 OsCvtProtFlagsToRegionFlags(unsigned long prot, unsigned lo { UINT32 regionFlags = 0; - regionFlags |= VM_MAP_REGION_FLAG_PERM_USER; //必须得是可用区先 + regionFlags |= VM_MAP_REGION_FLAG_PERM_USER; //必须是可用区 regionFlags |= (prot & PROT_READ) ? VM_MAP_REGION_FLAG_PERM_READ : 0; //映射区可被读 regionFlags |= (prot & PROT_WRITE) ? VM_MAP_REGION_FLAG_PERM_WRITE : 0; //映射区可被写 regionFlags |= (prot & PROT_EXEC) ? VM_MAP_REGION_FLAG_PERM_EXECUTE : 0; //映射区可被执行 @@ -262,13 +262,13 @@ STATIC INLINE BOOL LOS_IsUserAddress(VADDR_T vaddr) return ((vaddr >= USER_ASPACE_BASE) && (vaddr <= (USER_ASPACE_BASE + (USER_ASPACE_SIZE - 1)))); } -//从vaddr 到 vaddr + len 这段虚拟地址是否在用户空间 +//虚拟地址[vaddr,vaddr + len]是否在用户空间 STATIC INLINE BOOL LOS_IsUserAddressRange(VADDR_T vaddr, size_t len) { return (vaddr + len > vaddr) && LOS_IsUserAddress(vaddr) && (LOS_IsUserAddress(vaddr + len - 1)); } -//是否是一个动态分配地址 +//是否是一个动态分配的地址 STATIC INLINE BOOL LOS_IsVmallocAddress(VADDR_T vaddr) { return ((vaddr >= VMALLOC_START) && diff --git a/kernel/base/ipc/los_queue.c b/kernel/base/ipc/los_queue.c index af6085c479cbd529112a7f5b50b61d3ac800b7a7..20d1a889cd261739bed9be5b180da89116e1fc44 100644 --- a/kernel/base/ipc/los_queue.c +++ b/kernel/base/ipc/los_queue.c @@ -333,7 +333,7 @@ QUEUE_END: SCHEDULER_UNLOCK(intSave); return ret; } -//接口函数 鸿蒙 LOS_ 开头的都是可供外面调用的接口函数 +//接口函数定时读取消息队列 LITE_OS_SEC_TEXT UINT32 LOS_QueueReadCopy(UINT32 queueID, VOID *bufferAddr, UINT32 *bufferSize, @@ -347,10 +347,10 @@ LITE_OS_SEC_TEXT UINT32 LOS_QueueReadCopy(UINT32 queueID, return ret; } - operateType = OS_QUEUE_OPERATE_TYPE(OS_QUEUE_READ, OS_QUEUE_HEAD);//意思是从头开始读 - return OsQueueOperate(queueID, operateType, bufferAddr, bufferSize, timeout);//执行读操作 + operateType = OS_QUEUE_OPERATE_TYPE(OS_QUEUE_READ, OS_QUEUE_HEAD);//从头开始读 + return OsQueueOperate(queueID, operateType, bufferAddr, bufferSize, timeout);//定时执行读操作 } -//接口函数 从队列头开始写 +//接口函数从队列头开始写 LITE_OS_SEC_TEXT UINT32 LOS_QueueWriteHeadCopy(UINT32 queueID, VOID *bufferAddr, UINT32 bufferSize, diff --git a/kernel/extended/liteipc/hm_liteipc.c b/kernel/extended/liteipc/hm_liteipc.c index 156dd15112e919f90a1a1e8f55d91a45017a6439..0c3e1dbfe78eeaf2f1438a1549f0b605e3f08343 100644 --- a/kernel/extended/liteipc/hm_liteipc.c +++ b/kernel/extended/liteipc/hm_liteipc.c @@ -1,1321 +1,1321 @@ -/* - * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. - * Copyright (c) 2020, Huawei Device Co., Ltd. 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 the copyright holder 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. - */ - -#include "hm_liteipc.h" -#include "linux/kernel.h" -#include -#include "los_mp.h" -#include "los_mux.h" -#include "los_process_pri.h" -#include "los_spinlock.h" -#include "los_task_pri.h" -#if (LOSCFG_KERNEL_TRACE == YES) -#include "los_trace.h" -#endif -#include "los_vm_map.h" -#include "los_vm_phys.h" -#include "los_vm_page.h" -#include "los_vm_lock.h" - -#define USE_TASKID_AS_HANDLE YES -#define USE_MMAP YES -#define IPC_MSG_DATA_SZ_MAX 1024 -#define IPC_MSG_OBJECT_NUM_MAX 256 - -#define LITE_IPC_POOL_NAME "liteipc" -#define LITE_IPC_POOL_PAGE_MAX_NUM 64 /* 256KB */ -#define LITE_IPC_POOL_PAGE_DEFAULT_NUM 16 /* 64KB */ -#define LITE_IPC_POOL_MAX_SIZE (LITE_IPC_POOL_PAGE_MAX_NUM << PAGE_SHIFT) -#define LITE_IPC_POOL_DEFAULT_SIZE (LITE_IPC_POOL_PAGE_DEFAULT_NUM << PAGE_SHIFT) -#define LITE_IPC_POOL_UVADDR 0x10000000 -#define INVAILD_ID (-1) - -#define LITEIPC_TIMEOUT_MS 5000UL -#define LITEIPC_TIMEOUT_NS 5000000000ULL - -typedef struct { - LOS_DL_LIST list; - VOID *ptr; -} IpcUsedNode; - -LosMux g_serviceHandleMapMux; -#if (USE_TASKID_AS_HANDLE == YES) -HandleInfo g_cmsTask; -#else -HandleInfo g_serviceHandleMap[MAX_SERVICE_NUM]; -#endif -STATIC LOS_DL_LIST g_ipcPendlist; -STATIC LOS_DL_LIST g_ipcUsedNodelist[LOSCFG_BASE_CORE_PROCESS_LIMIT];//==进程数量 64个 - -/* ipc lock */ -SPIN_LOCK_INIT(g_ipcSpin); -#define IPC_LOCK(state) LOS_SpinLockSave(&g_ipcSpin, &(state)) -#define IPC_UNLOCK(state) LOS_SpinUnlockRestore(&g_ipcSpin, state) - -STATIC int LiteIpcOpen(FAR struct file *filep); -STATIC int LiteIpcClose(FAR struct file *filep); -STATIC int LiteIpcIoctl(FAR struct file *filep, int cmd, unsigned long arg); -STATIC int LiteIpcMmap(FAR struct file* filep, LosVmMapRegion *region); -STATIC UINT32 LiteIpcWrite(IpcContent *content); -STATIC UINT32 GetTid(UINT32 serviceHandle, UINT32 *taskID); -STATIC UINT32 HandleSpecialObjects(UINT32 dstTid, IpcListNode *node, BOOL isRollback); - -//实现VFS接口函数,对liteIpc进行操作 -STATIC const struct file_operations_vfs g_liteIpcFops = { - LiteIpcOpen, /* open */ - LiteIpcClose, /* close */ - NULL, /* read */ - NULL, /* write */ - NULL, /* seek */ - LiteIpcIoctl, /* ioctl */ - LiteIpcMmap, /* mmap */ -#ifndef CONFIG_DISABLE_POLL - NULL, /* poll */ -#endif - NULL, /* unlink */ -}; - -#if (LOSCFG_KERNEL_TRACE == YES) -const char *g_operStr[OPERATION_NUM] = {"WRITE", "WRITE_DROP", "TRY_READ", "READ", "READ_DROP", "READ_TIMEOUT"}; -const char *g_msgTypeStr[MT_NUM] = {"REQUEST", "REPLY", "DEATH_NOTIFY"}; -const char *g_ipcStatusStr[2] = {"NOT_PEND", "PEND"}; - -LITE_OS_SEC_TEXT STATIC UINT16 IpcTraceHook(UINT8 *inputBuffer, UINT32 id, UINT32 msg) -{ - IpcTraceFrame *ipcInfo = NULL; - if (inputBuffer == NULL) { - return 0; - } - - ipcInfo = (IpcTraceFrame *)inputBuffer; - ipcInfo->idInfo = id; - ipcInfo->msgInfo = msg; - ipcInfo->timestamp = LOS_CurrNanosec(); - - return sizeof(IpcTraceFrame); -} - -LITE_OS_SEC_TEXT STATIC VOID IpcTrace(IpcMsg *msg, UINT32 operation, UINT32 ipcStatus, UINT32 msgType) -{ - UINT32 curTid = LOS_CurTaskIDGet(); - UINT32 curPid = LOS_GetCurrProcessID(); - UINT32 dstTid; - UINT32 ret = (msg == NULL) ? INVAILD_ID : GetTid(msg->target.handle, &dstTid); - IdArg id = {INVAILD_ID, INVAILD_ID, INVAILD_ID, INVAILD_ID}; - MsgArg msgArg; - if (operation <= WRITE_DROP) { - id.srcTid = curTid; - id.srcPid = curPid; - id.dstTid = ret ? INVAILD_ID : dstTid; - id.dstPid = ret ? INVAILD_ID : OS_TCB_FROM_TID(dstTid)->processID; - } else { - id.srcTid = (msg == NULL) ? INVAILD_ID : msg->taskID; - id.srcPid = (msg == NULL) ? INVAILD_ID : msg->processID; - id.dstTid = curTid; - id.dstPid = curPid; - } - msgArg.msgType = msgType; - msgArg.code = (msg == NULL) ? INVAILD_ID : msg->code; - msgArg.operation = operation; - msgArg.ipcStatus = ipcStatus; - - VOID *ptr1 = &id; - VOID *ptr2 = &msgArg; - LOS_Trace(LOS_TRACE_IPC, *((UINT32 *)ptr1), *((UINT32 *)ptr2)); -} - -UINT32 IpcInfoCheck(IpcTraceFrame *ipcInfo) -{ - MsgArg *msgArg = NULL; - - if (ipcInfo == NULL) { - return LOS_NOK; - } - - msgArg = (MsgArg *)&ipcInfo->msgInfo; - if ((msgArg->operation >= OPERATION_NUM) || - (msgArg->msgType >= MT_NUM)) { - return LOS_NOK; - } - - return LOS_OK; -} - -LITE_OS_SEC_TEXT STATIC VOID IpcTracePrint(UINT32 cpuID, IpcTraceFrame *ipcInfo) -{ - IdArg *idArg = (IdArg *)&ipcInfo->idInfo; - MsgArg *msgArg = (MsgArg *)&ipcInfo->msgInfo; - - if (IpcInfoCheck(ipcInfo) != LOS_OK) { - return; - } - - PRINTK("[LiteIPCTrace]timestamp:%016lld", ipcInfo->timestamp); - PRINTK(" cpuID:%02d", cpuID); - PRINTK(" operation:%13s", g_operStr[msgArg->operation]); - PRINTK(" msgType:%12s", g_msgTypeStr[msgArg->msgType]); - UINT32 isPend = (msgArg->ipcStatus & IPC_THREAD_STATUS_PEND) == IPC_THREAD_STATUS_PEND; - PRINTK(" ipcStatus:%9s", g_ipcStatusStr[isPend]); - PRINTK(" code:%03d", msgArg->code); - PRINTK(" srcTid:%03d", idArg->srcTid); - PRINTK(" srcPid:%03d", idArg->srcPid); - PRINTK(" dstTid:%03d", idArg->dstTid); - PRINTK(" dstPid:%03d\n", idArg->dstPid); -} - -VOID IpcBacktrace(VOID) -{ - INT32 pos; - INT32 i; - TraceBuffer buff; - for (i = 0; i < LOSCFG_KERNEL_CORE_NUM; i++) { - LOS_TraceBufGet(&buff, i); - pos = buff.tracePos; - while (pos >= sizeof(IpcTraceFrame) + LOS_TRACE_TAG_LENGTH) { - UINT32 *traceType = (UINT32 *)(buff.dataBuf + pos - LOS_TRACE_TAG_LENGTH); - pos -= sizeof(IpcTraceFrame) + LOS_TRACE_TAG_LENGTH; - switch (*traceType) { - case LOS_TRACE_IPC: { - IpcTraceFrame *ipcInfo = (IpcTraceFrame *)(buff.dataBuf + pos); - IpcTracePrint(i, ipcInfo); - break; - } - default: - PRINTK("other module trace\n"); - break; - } - } - } -} -#endif -//liteIpc 初始化 -LITE_OS_SEC_TEXT_INIT UINT32 LiteIpcInit(VOID) -{ - UINT32 ret, i; -#if (USE_TASKID_AS_HANDLE == YES) - g_cmsTask.status = HANDLE_NOT_USED; -#else - memset_s(g_serviceHandleMap, sizeof(g_serviceHandleMap), 0, sizeof(g_serviceHandleMap)); -#endif - ret = LOS_MuxInit(&g_serviceHandleMapMux, NULL); - if (ret != LOS_OK) { - return ret; - } - ret = (UINT32)register_driver(LITEIPC_DRIVER, &g_liteIpcFops, DRIVER_MODE, NULL); - if (ret != LOS_OK) { - PRINT_ERR("register lite_ipc driver failed:%d\n", ret); - } - LOS_ListInit(&(g_ipcPendlist)); - for (i = 0; i < LOSCFG_BASE_CORE_PROCESS_LIMIT; i++) { - LOS_ListInit(&(g_ipcUsedNodelist[i])); - } -#if (LOSCFG_KERNEL_TRACE == YES) - ret = LOS_TraceUserReg(LOS_TRACE_IPC, IpcTraceHook, sizeof(IpcTraceFrame)); - if (ret != LOS_OK) { - PRINT_ERR("liteipc LOS_TraceUserReg failed:%d\n", ret); - } -#endif - return ret; -} - -LITE_OS_SEC_TEXT STATIC int LiteIpcOpen(FAR struct file *filep) -{ - return 0; -} - -LITE_OS_SEC_TEXT STATIC int LiteIpcClose(FAR struct file *filep) -{ - return 0; -} - -LITE_OS_SEC_TEXT STATIC BOOL IsPoolMapped(VOID) -{ - LosProcessCB *pcb = OsCurrProcessGet(); - return (pcb->ipcInfo.pool.uvaddr != NULL) && (pcb->ipcInfo.pool.kvaddr != NULL) && - (pcb->ipcInfo.pool.poolSize != 0); -} - -LITE_OS_SEC_TEXT STATIC INT32 DoIpcMmap(LosProcessCB *pcb, LosVmMapRegion *region) -{ - UINT32 i; - INT32 ret = 0; - PADDR_T pa; - UINT32 uflags = VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_USER; - LosVmPage *vmPage = NULL; - VADDR_T uva = (VADDR_T)(UINTPTR)pcb->ipcInfo.pool.uvaddr; - VADDR_T kva = (VADDR_T)(UINTPTR)pcb->ipcInfo.pool.kvaddr; - - (VOID)LOS_MuxAcquire(&pcb->vmSpace->regionMux); - - for (i = 0; i < (region->range.size >> PAGE_SHIFT); i++) { - pa = LOS_PaddrQuery((VOID *)(UINTPTR)(kva + (i << PAGE_SHIFT))); - if (pa == 0) { - PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__); - ret = -EINVAL; - break; - } - vmPage = LOS_VmPageGet(pa); - if (vmPage == NULL) { - PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__); - ret = -EINVAL; - break; - } - STATUS_T err = LOS_ArchMmuMap(&pcb->vmSpace->archMmu, uva + (i << PAGE_SHIFT), pa, 1, uflags); - if (err < 0) { - ret = err; - PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__); - break; - } - LOS_AtomicInc(&vmPage->refCounts); - } - /* if any failure happened, rollback */ - if (i != (region->range.size >> PAGE_SHIFT)) { - while (i--) { - pa = LOS_PaddrQuery((VOID *)(UINTPTR)(kva + (i << PAGE_SHIFT))); - vmPage = LOS_VmPageGet(pa); - (VOID)LOS_ArchMmuUnmap(&pcb->vmSpace->archMmu, uva + (i << PAGE_SHIFT), 1); - LOS_PhysPageFree(vmPage); - } - } - - (VOID)LOS_MuxRelease(&pcb->vmSpace->regionMux); - return ret; -} - -LITE_OS_SEC_TEXT STATIC int LiteIpcMmap(FAR struct file* filep, LosVmMapRegion *region) -{ - int ret = 0; - LosVmMapRegion *regionTemp = NULL; - LosProcessCB *pcb = OsCurrProcessGet(); - if ((region == NULL) || (region->range.size > LITE_IPC_POOL_MAX_SIZE) || - (!LOS_IsRegionPermUserReadOnly(region)) || (!LOS_IsRegionFlagPrivateOnly(region))) { - ret = -EINVAL; - goto ERROR_REGION_OUT; - } - if (IsPoolMapped()) { - return -EEXIST; - } - if (pcb->ipcInfo.pool.uvaddr != NULL) { - regionTemp = LOS_RegionFind(pcb->vmSpace, (VADDR_T)(UINTPTR)pcb->ipcInfo.pool.uvaddr); - if (regionTemp != NULL) { - (VOID)LOS_RegionFree(pcb->vmSpace, regionTemp); - } - } - pcb->ipcInfo.pool.uvaddr = (VOID *)(UINTPTR)region->range.base; - if (pcb->ipcInfo.pool.kvaddr != NULL) { - LOS_VFree(pcb->ipcInfo.pool.kvaddr); - pcb->ipcInfo.pool.kvaddr = NULL; - } - /* use vmalloc to alloc phy mem */ - pcb->ipcInfo.pool.kvaddr = LOS_VMalloc(region->range.size); - if (pcb->ipcInfo.pool.kvaddr == NULL) { - ret = -ENOMEM; - goto ERROR_REGION_OUT; - } - /* do mmap */ - ret = DoIpcMmap(pcb, region); - if (ret) { - goto ERROR_MAP_OUT; - } - /* ipc pool init */ - if (LOS_MemInit(pcb->ipcInfo.pool.kvaddr, region->range.size) != LOS_OK) { - ret = -EINVAL; - goto ERROR_MAP_OUT; - } - pcb->ipcInfo.pool.poolSize = region->range.size; - return 0; -ERROR_MAP_OUT: - LOS_VFree(pcb->ipcInfo.pool.kvaddr); -ERROR_REGION_OUT: - pcb->ipcInfo.pool.uvaddr = NULL; - pcb->ipcInfo.pool.kvaddr = NULL; - return ret; -} - -LITE_OS_SEC_TEXT_INIT UINT32 LiteIpcPoolInit(ProcIpcInfo *ipcInfo) -{ - ipcInfo->pool.uvaddr = NULL; - ipcInfo->pool.kvaddr = NULL; - ipcInfo->pool.poolSize = 0; - ipcInfo->ipcTaskID = INVAILD_ID; - return LOS_OK; -} - -LITE_OS_SEC_TEXT UINT32 LiteIpcPoolReInit(ProcIpcInfo *child, const ProcIpcInfo *parent) -{ - child->pool.uvaddr = parent->pool.uvaddr; - child->pool.kvaddr = NULL; - child->pool.poolSize = 0; - child->ipcTaskID = INVAILD_ID; - return LOS_OK; -} - -LITE_OS_SEC_TEXT VOID LiteIpcPoolDelete(ProcIpcInfo *ipcInfo) -{ - UINT32 intSave; - IpcUsedNode *node = NULL; - UINT32 processID = LOS_GetCurrProcessID(); - if (ipcInfo->pool.kvaddr != NULL) { - LOS_VFree(ipcInfo->pool.kvaddr); - ipcInfo->pool.kvaddr = NULL; - IPC_LOCK(intSave); - while (!LOS_ListEmpty(&g_ipcUsedNodelist[processID])) { - node = LOS_DL_LIST_ENTRY(g_ipcUsedNodelist[processID].pstNext, IpcUsedNode, list); - LOS_ListDelete(&node->list); - free(node); - } - IPC_UNLOCK(intSave); - } - /* remove process access to service */ - for (UINT32 i = 0; i < MAX_SERVICE_NUM; i++) { - if (ipcInfo->access[i] == TRUE) { - ipcInfo->access[i] = FALSE; - OS_TCB_FROM_TID(i)->accessMap[processID] = FALSE; - } - } -} - -/* Only when kernenl no longer access ipc node content, can user free the ipc node */ -LITE_OS_SEC_TEXT STATIC VOID EnableIpcNodeFreeByUser(UINT32 processID, VOID *buf) -{ - UINT32 intSave; - IpcUsedNode *node = (IpcUsedNode *)malloc(sizeof(IpcUsedNode)); - if (node != NULL) { - node->ptr = buf; - IPC_LOCK(intSave); - LOS_ListAdd(&g_ipcUsedNodelist[processID], &node->list); - IPC_UNLOCK(intSave); - } -} - -LITE_OS_SEC_TEXT STATIC VOID* LiteIpcNodeAlloc(UINT32 processID, UINT32 size) -{ - VOID *ptr = LOS_MemAlloc(OS_PCB_FROM_PID(processID)->ipcInfo.pool.kvaddr, size); - PRINT_INFO("LiteIpcNodeAlloc pid:%d, pool:%x buf:%x size:%d\n", - processID, OS_PCB_FROM_PID(processID)->ipcInfo.pool.kvaddr, ptr, size); - return ptr; -} - -LITE_OS_SEC_TEXT STATIC UINT32 LiteIpcNodeFree(UINT32 processID, VOID *buf) -{ - PRINT_INFO("LiteIpcNodeFree pid:%d, pool:%x buf:%x\n", - processID, OS_PCB_FROM_PID(processID)->ipcInfo.pool.kvaddr, buf); - return LOS_MemFree(OS_PCB_FROM_PID(processID)->ipcInfo.pool.kvaddr, buf); -} - -LITE_OS_SEC_TEXT STATIC BOOL IsIpcNode(UINT32 processID, const VOID *buf) -{ - IpcUsedNode *node = NULL; - UINT32 intSave; - IPC_LOCK(intSave); - LOS_DL_LIST_FOR_EACH_ENTRY(node, &g_ipcUsedNodelist[processID], IpcUsedNode, list) { - if (node->ptr == buf) { - LOS_ListDelete(&node->list); - IPC_UNLOCK(intSave); - free(node); - return TRUE; - } - } - IPC_UNLOCK(intSave); - return FALSE; -} - -LITE_OS_SEC_TEXT STATIC INTPTR GetIpcUserAddr(UINT32 processID, INTPTR kernelAddr) -{ - IpcPool pool = OS_PCB_FROM_PID(processID)->ipcInfo.pool; - INTPTR offset = (INTPTR)(pool.uvaddr) - (INTPTR)(pool.kvaddr); - return kernelAddr + offset; -} - -LITE_OS_SEC_TEXT STATIC INTPTR GetIpcKernelAddr(UINT32 processID, INTPTR userAddr) -{ - IpcPool pool = OS_PCB_FROM_PID(processID)->ipcInfo.pool; - INTPTR offset = (INTPTR)(pool.uvaddr) - (INTPTR)(pool.kvaddr); - return userAddr - offset; -} - -LITE_OS_SEC_TEXT STATIC UINT32 CheckUsedBuffer(const VOID *node, IpcListNode **outPtr) -{ - VOID *ptr = NULL; - LosProcessCB *pcb = OsCurrProcessGet(); - IpcPool pool = pcb->ipcInfo.pool; - if ((node == NULL) || ((INTPTR)node < (INTPTR)(pool.uvaddr)) || - ((INTPTR)node > (INTPTR)(pool.uvaddr) + pool.poolSize)) { - return -EINVAL; - } - ptr = (VOID *)GetIpcKernelAddr(pcb->processID, (INTPTR)(node)); - if (IsIpcNode(pcb->processID, ptr) != TRUE) { - return -EFAULT; - } - *outPtr = (IpcListNode *)ptr; - return LOS_OK; -} - -LITE_OS_SEC_TEXT STATIC UINT32 GetTid(UINT32 serviceHandle, UINT32 *taskID) -{ - if (serviceHandle >= MAX_SERVICE_NUM) { - return -EINVAL; - } -#if (USE_TASKID_AS_HANDLE == YES) - *taskID = serviceHandle ? serviceHandle : g_cmsTask.taskID; - return LOS_OK; -#else - if (g_serviceHandleMap[serviceHandle].status == HANDLE_REGISTED) { - *taskID = g_serviceHandleMap[serviceHandle].taskID; - return LOS_OK; - } - return -EINVAL; -#endif -} - -LITE_OS_SEC_TEXT STATIC UINT32 GenerateServiceHandle(UINT32 taskID, HandleStatus status, UINT32 *serviceHandle) -{ -#if (USE_TASKID_AS_HANDLE == YES) - *serviceHandle = taskID ? taskID : LOS_CurTaskIDGet(); /* if taskID is 0, return curTaskID */ - if (*serviceHandle == g_cmsTask.taskID) { - return -EINVAL; - } - return LOS_OK; -#else - UINT32 i; - (VOID)LOS_MuxLock(&g_serviceHandleMapMux, LOS_WAIT_FOREVER); - for (i = 1; i < MAX_SERVICE_NUM; i++) { - if (g_serviceHandleMap[i].status == HANDLE_NOT_USED) { - g_serviceHandleMap[i].taskID = taskID; - g_serviceHandleMap[i].status = status; - *serviceHandle = i; - (VOID)LOS_MuxUnLock(&g_serviceHandleMapMux); - return LOS_OK; - } - } - (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux); - return -EINVAL; -#endif -} - -LITE_OS_SEC_TEXT STATIC VOID RefreshServiceHandle(UINT32 serviceHandle, UINT32 result) -{ -#if (USE_TASKID_AS_HANDLE == NO) - (VOID)LOS_MuxLock(&g_serviceHandleMapMux, LOS_WAIT_FOREVER); - if ((result == LOS_OK) && (g_serviceHandleMap[serviceHandle].status == HANDLE_REGISTING)) { - g_serviceHandleMap[serviceHandle].status = HANDLE_REGISTED; - } else { - g_serviceHandleMap[serviceHandle].status = HANDLE_NOT_USED; - } - (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux); -#endif -} - -LITE_OS_SEC_TEXT STATIC UINT32 AddServiceAccess(UINT32 taskID, UINT32 serviceHandle) -{ - UINT32 serviceTid = 0; - UINT32 ret = GetTid(serviceHandle, &serviceTid); - if (ret != LOS_OK) { - PRINT_ERR("AddServiceAccess GetTid failed\n"); - return ret; - } - UINT32 processID = OS_TCB_FROM_TID(taskID)->processID; - OS_TCB_FROM_TID(serviceTid)->accessMap[processID] = TRUE; - OS_PCB_FROM_PID(processID)->ipcInfo.access[serviceTid] = TRUE; - return LOS_OK; -} - -LITE_OS_SEC_TEXT STATIC BOOL HasServiceAccess(UINT32 serviceHandle) -{ - UINT32 serviceTid = 0; - UINT32 curProcessID = LOS_GetCurrProcessID(); - UINT32 ret; - if (serviceHandle >= MAX_SERVICE_NUM) { - return FALSE; - } - if (serviceHandle == 0) { - return TRUE; - } - ret = GetTid(serviceHandle, &serviceTid); - if (ret != LOS_OK) { - PRINT_ERR("HasServiceAccess GetTid failed\n"); - return FALSE; - } - if (OS_TCB_FROM_TID(serviceTid)->processID == curProcessID) { - return TRUE; - } - return OS_TCB_FROM_TID(serviceTid)->accessMap[curProcessID]; -} - -LITE_OS_SEC_TEXT STATIC UINT32 SetIpcTask(VOID) -{ - if (OsCurrProcessGet()->ipcInfo.ipcTaskID == INVAILD_ID) { - OsCurrProcessGet()->ipcInfo.ipcTaskID = LOS_CurTaskIDGet(); - return OsCurrProcessGet()->ipcInfo.ipcTaskID; - } - PRINT_ERR("curprocess %d IpcTask already set!\n", OsCurrProcessGet()->processID); - return -EINVAL; -} - -LITE_OS_SEC_TEXT BOOL IsIpcTaskSet(VOID) -{ - if (OsCurrProcessGet()->ipcInfo.ipcTaskID == INVAILD_ID) { - return FALSE; - } - return TRUE; -} - -LITE_OS_SEC_TEXT STATIC UINT32 GetIpcTaskID(UINT32 processID, UINT32 *ipcTaskID) -{ - if (OS_PCB_FROM_PID(processID)->ipcInfo.ipcTaskID == INVAILD_ID) { - return LOS_NOK; - } - *ipcTaskID = OS_PCB_FROM_PID(processID)->ipcInfo.ipcTaskID; - return LOS_OK; -} - -LITE_OS_SEC_TEXT STATIC UINT32 SendDeathMsg(UINT32 processID, UINT32 serviceHandle) -{ - UINT32 ipcTaskID; - UINT32 ret; - IpcContent content; - IpcMsg msg; - - OS_PCB_FROM_PID(processID)->ipcInfo.access[serviceHandle] = false; - - ret = GetIpcTaskID(processID, &ipcTaskID); - if (ret != LOS_OK) { - return -EINVAL; - } - content.flag = SEND; - content.outMsg = &msg; - memset_s(content.outMsg, sizeof(IpcMsg), 0, sizeof(IpcMsg)); - content.outMsg->type = MT_DEATH_NOTIFY; - content.outMsg->target.handle = ipcTaskID; - content.outMsg->target.token = serviceHandle; - content.outMsg->code = 0; - return LiteIpcWrite(&content); -} - -LITE_OS_SEC_TEXT VOID LiteIpcRemoveServiceHandle(LosTaskCB *taskCB) -{ - UINT32 j; -#if (USE_TASKID_AS_HANDLE == YES) - - UINT32 intSave; - LOS_DL_LIST *listHead = NULL; - LOS_DL_LIST *listNode = NULL; - IpcListNode *node = NULL; - UINT32 processID = taskCB->processID; - - listHead = &(taskCB->msgListHead); - do { - SCHEDULER_LOCK(intSave); - if (LOS_ListEmpty(listHead)) { - SCHEDULER_UNLOCK(intSave); - break; - } else { - listNode = LOS_DL_LIST_FIRST(listHead); - LOS_ListDelete(listNode); - node = LOS_DL_LIST_ENTRY(listNode, IpcListNode, listNode); - SCHEDULER_UNLOCK(intSave); - (VOID)HandleSpecialObjects(taskCB->taskID, node, TRUE); - (VOID)LiteIpcNodeFree(processID, (VOID *)node); - } - } while (1); - - taskCB->accessMap[processID] = FALSE; - for (j = 0; j < MAX_SERVICE_NUM; j++) { - if (taskCB->accessMap[j] == TRUE) { - taskCB->accessMap[j] = FALSE; - (VOID)SendDeathMsg(j, taskCB->taskID); - } - } -#else - (VOID)LOS_MuxLock(&g_serviceHandleMapMux, LOS_WAIT_FOREVER); - for (UINT32 i = 1; i < MAX_SERVICE_NUM; i++) { - if ((g_serviceHandleMap[i].status != HANDLE_NOT_USED) && (g_serviceHandleMap[i].taskID == taskCB->taskID)) { - g_serviceHandleMap[i].status = HANDLE_NOT_USED; - g_serviceHandleMap[i].taskID = INVAILD_ID; - break; - } - } - (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux); - /* run deathHandler */ - if (i < MAX_SERVICE_NUM) { - for (j = 0; j < MAX_SERVICE_NUM; j++) { - if (taskCB->accessMap[j] == TRUE) { - (VOID)SendDeathMsg(j, i); - } - } - } -#endif -} - -LITE_OS_SEC_TEXT STATIC UINT32 SetCms(UINTPTR maxMsgSize) -{ - if (maxMsgSize < sizeof(IpcMsg)) { - return -EINVAL; - } - (VOID)LOS_MuxLock(&g_serviceHandleMapMux, LOS_WAIT_FOREVER); -#if (USE_TASKID_AS_HANDLE == YES) - if (g_cmsTask.status == HANDLE_NOT_USED) { - g_cmsTask.status = HANDLE_REGISTED; - g_cmsTask.taskID = LOS_CurTaskIDGet(); - g_cmsTask.maxMsgSize = maxMsgSize; - (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux); - return LOS_OK; - } -#else - if (g_serviceHandleMap[0].status == HANDLE_NOT_USED) { - g_serviceHandleMap[0].status = HANDLE_REGISTED; - g_serviceHandleMap[0].taskID = LOS_CurTaskIDGet(); - (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux); - return LOS_OK; - } -#endif - (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux); - return -EEXIST; -} - -LITE_OS_SEC_TEXT STATIC BOOL IsCmsSet(VOID) -{ -#if (USE_TASKID_AS_HANDLE == YES) - return g_cmsTask.status == HANDLE_REGISTED; -#else - return g_serviceHandleMap[0].status == HANDLE_REGISTED; -#endif -} - -LITE_OS_SEC_TEXT STATIC BOOL IsCmsTask(UINT32 taskID) -{ -#if (USE_TASKID_AS_HANDLE == YES) - return IsCmsSet() ? (OS_TCB_FROM_TID(taskID)->processID == OS_TCB_FROM_TID(g_cmsTask.taskID)->processID) : FALSE; -#else - return IsCmsSet() ? (OS_TCB_FROM_TID(taskID)->processID == - OS_TCB_FROM_TID(g_serviceHandleMap[0].taskID)->processID) : FALSE; -#endif -} - -LITE_OS_SEC_TEXT STATIC BOOL IsTaskAlive(UINT32 taskID) -{ - LosTaskCB *tcb = NULL; - if (OS_TID_CHECK_INVALID(taskID)) { - return FALSE; - } - tcb = OS_TCB_FROM_TID(taskID); - if (!OsProcessIsUserMode(OS_PCB_FROM_PID(tcb->processID))) { - return FALSE; - } - if (OsTaskIsInactive(tcb)) { - return FALSE; - } - return TRUE; -} - -LITE_OS_SEC_TEXT STATIC UINT32 HandleFd(SpecialObj *obj, BOOL isRollback) -{ - /* now fd is not Isolated between processes, do nothing */ - return LOS_OK; -} - -LITE_OS_SEC_TEXT STATIC UINT32 HandlePtr(UINT32 processID, SpecialObj *obj, BOOL isRollback) -{ - VOID *buf = NULL; - UINT32 ret; - if ((obj->content.ptr.buff == NULL) || (obj->content.ptr.buffSz == 0)) { - return -EINVAL; - } - if (isRollback == FALSE) { - if (LOS_IsUserAddress((vaddr_t)(UINTPTR)(obj->content.ptr.buff)) == FALSE) { - PRINT_ERR("Bad ptr address\n"); - return -EINVAL; - } - buf = LiteIpcNodeAlloc(processID, obj->content.ptr.buffSz); - if (buf == NULL) { - PRINT_ERR("DealPtr alloc mem failed\n"); - return -EINVAL; - } - ret = copy_from_user(buf, obj->content.ptr.buff, obj->content.ptr.buffSz); - if (ret != LOS_OK) { - LiteIpcNodeFree(processID, buf); - return ret; - } - obj->content.ptr.buff = (VOID *)GetIpcUserAddr(processID, (INTPTR)buf); - EnableIpcNodeFreeByUser(processID, (VOID *)buf); - } else { - (VOID)LiteIpcNodeFree(processID, (VOID *)GetIpcKernelAddr(processID, (INTPTR)obj->content.ptr.buff)); - } - return LOS_OK; -} - -LITE_OS_SEC_TEXT STATIC UINT32 HandleSvc(UINT32 dstTid, const SpecialObj *obj, BOOL isRollback) -{ - UINT32 taskID = 0; - if (isRollback == FALSE) { - if (IsTaskAlive(obj->content.svc.handle) == FALSE) { - PRINT_ERR("HandleSvc wrong svctid\n"); - return -EINVAL; - } - if (HasServiceAccess(obj->content.svc.handle) == FALSE) { - PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__); - return -EACCES; - } - if (GetTid(obj->content.svc.handle, &taskID) == 0) { - if (taskID == OS_PCB_FROM_PID(OS_TCB_FROM_TID(taskID)->processID)->ipcInfo.ipcTaskID) { - AddServiceAccess(dstTid, obj->content.svc.handle); - } - } - } - return LOS_OK; -} - -LITE_OS_SEC_TEXT STATIC UINT32 HandleObj(UINT32 dstTid, SpecialObj *obj, BOOL isRollback) -{ - UINT32 ret; - UINT32 processID = OS_TCB_FROM_TID(dstTid)->processID; - switch (obj->type) { - case OBJ_FD: - ret = HandleFd(obj, isRollback); - break; - case OBJ_PTR: - ret = HandlePtr(processID, obj, isRollback); - break; - case OBJ_SVC: - ret = HandleSvc(dstTid, (const SpecialObj *)obj, isRollback); - break; - default: - ret = -EINVAL; - break; - } - return ret; -} - -LITE_OS_SEC_TEXT STATIC UINT32 HandleSpecialObjects(UINT32 dstTid, IpcListNode *node, BOOL isRollback) -{ - UINT32 ret = LOS_OK; - IpcMsg *msg = &(node->msg); - INT32 i; - SpecialObj *obj = NULL; - UINT32 *offset = (UINT32 *)(UINTPTR)(msg->offsets); - if (isRollback) { - i = msg->spObjNum; - goto EXIT; - } - for (i = 0; i < msg->spObjNum; i++) { - if (offset[i] > msg->dataSz - sizeof(SpecialObj)) { - ret = -EINVAL; - goto EXIT; - } - if ((i > 0) && (offset[i] < offset[i - 1] + sizeof(SpecialObj))) { - ret = -EINVAL; - goto EXIT; - } - obj = (SpecialObj *)((UINTPTR)msg->data + offset[i]); - if (obj == NULL) { - ret = -EINVAL; - goto EXIT; - } - ret = HandleObj(dstTid, obj, FALSE); - if (ret != LOS_OK) { - goto EXIT; - } - } - return LOS_OK; -EXIT: - for (i--; i >= 0; i--) { - obj = (SpecialObj *)((UINTPTR)msg->data + offset[i]); - (VOID)HandleObj(dstTid, obj, TRUE); - } - return ret; -} - -LITE_OS_SEC_TEXT STATIC UINT32 CheckMsgSize(IpcMsg *msg) -{ - UINT64 totalSize; - UINT32 i; - UINT32 *offset = (UINT32 *)(UINTPTR)(msg->offsets); - SpecialObj *obj = NULL; - if (msg->target.handle != 0) { - return LOS_OK; - } - /* msg send to cms, check the msg size */ - totalSize = (UINT64)sizeof(IpcMsg) + msg->dataSz + msg->spObjNum * sizeof(UINT32); - for (i = 0; i < msg->spObjNum; i++) { - if (offset[i] > msg->dataSz - sizeof(SpecialObj)) { - return -EINVAL; - } - if ((i > 0) && (offset[i] < offset[i - 1] + sizeof(SpecialObj))) { - return -EINVAL; - } - obj = (SpecialObj *)((UINTPTR)msg->data + offset[i]); - if (obj == NULL) { - return -EINVAL; - } - if (obj->type == OBJ_PTR) { - totalSize += obj->content.ptr.buffSz; - } - } - if (totalSize > g_cmsTask.maxMsgSize) { - return -EINVAL; - } - return LOS_OK; -} - -LITE_OS_SEC_TEXT STATIC UINT32 CopyDataFromUser(IpcListNode *node, UINT32 bufSz, const IpcMsg *msg) -{ - UINT32 ret; - ret = (UINT32)memcpy_s((VOID *)(&node->msg), bufSz - sizeof(LOS_DL_LIST), (const VOID *)msg, sizeof(IpcMsg)); - if (ret != LOS_OK) { - PRINT_DEBUG("%s, %d, %u\n", __FUNCTION__, __LINE__, ret); - return ret; - } - - if (msg->dataSz) { - node->msg.data = (VOID *)((UINTPTR)node + sizeof(IpcListNode)); - ret = copy_from_user((VOID *)(node->msg.data), msg->data, msg->dataSz); - if (ret != LOS_OK) { - PRINT_DEBUG("%s, %d\n", __FUNCTION__, __LINE__); - return ret; - } - } else { - node->msg.data = NULL; - } - - if (msg->spObjNum) { - node->msg.offsets = (VOID *)((UINTPTR)node + sizeof(IpcListNode) + msg->dataSz); - ret = copy_from_user((VOID *)(node->msg.offsets), msg->offsets, msg->spObjNum * sizeof(UINT32)); - if (ret != LOS_OK) { - PRINT_DEBUG("%s, %d, %x, %x, %d\n", __FUNCTION__, __LINE__, node->msg.offsets, msg->offsets, msg->spObjNum); - return ret; - } - } else { - node->msg.offsets = NULL; - } - ret = CheckMsgSize(&node->msg); - if (ret != LOS_OK) { - PRINT_DEBUG("%s, %d\n", __FUNCTION__, __LINE__); - return ret; - } - node->msg.taskID = LOS_CurTaskIDGet(); - node->msg.processID = OsCurrProcessGet()->processID; -#ifdef LOSCFG_SECURITY_CAPABILITY - node->msg.userID = OsCurrProcessGet()->user->userID; - node->msg.gid = OsCurrProcessGet()->user->gid; -#endif - return LOS_OK; -} - -LITE_OS_SEC_TEXT STATIC BOOL IsLeagalReply(const IpcContent *content) -{ - UINT32 curProcessID = LOS_GetCurrProcessID(); - IpcListNode *node = (IpcListNode *)GetIpcKernelAddr(curProcessID, (INTPTR)(content->buffToFree)); - IpcMsg *requestMsg = &node->msg; - IpcMsg *replyMsg = content->outMsg; - UINT32 reqDstTid = 0; - /* Check whether the reply matches the request */ - if ((requestMsg->type != MT_REQUEST) || - (requestMsg->flag == LITEIPC_FLAG_ONEWAY) || - (replyMsg->timestamp != requestMsg->timestamp) || - (replyMsg->target.handle != requestMsg->taskID) || - (GetTid(requestMsg->target.handle, &reqDstTid) != 0) || - (OS_TCB_FROM_TID(reqDstTid)->processID != curProcessID)) { - return FALSE; - } - return TRUE; -} - -LITE_OS_SEC_TEXT STATIC UINT32 CheckPara(IpcContent *content, UINT32 *dstTid) -{ - UINT32 ret; - IpcMsg *msg = content->outMsg; - UINT32 flag = content->flag; -#if (USE_TIMESTAMP == YES) - UINT64 now = LOS_CurrNanosec(); -#endif - if (((msg->dataSz > 0) && (msg->data == NULL)) || - ((msg->spObjNum > 0) && (msg->offsets == NULL)) || - (msg->dataSz > IPC_MSG_DATA_SZ_MAX) || - (msg->spObjNum > IPC_MSG_OBJECT_NUM_MAX) || - (msg->dataSz < msg->spObjNum * sizeof(SpecialObj))) { - return -EINVAL; - } - switch (msg->type) { - case MT_REQUEST: - if (HasServiceAccess(msg->target.handle)) { - ret = GetTid(msg->target.handle, dstTid); - if (ret != LOS_OK) { - return -EINVAL; - } - } else { - PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__); - return -EACCES; - } -#if (USE_TIMESTAMP == YES) - msg->timestamp = now; -#endif - break; - case MT_REPLY: - case MT_FAILED_REPLY: - if ((flag & BUFF_FREE) != BUFF_FREE) { - return -EINVAL; - } - if (!IsLeagalReply(content)) { - return -EINVAL; - } -#if (USE_TIMESTAMP == YES) - if (now > msg->timestamp + LITEIPC_TIMEOUT_NS) { -#if (LOSCFG_KERNEL_TRACE == YES) - IpcTrace(msg, WRITE_DROP, 0, msg->type); - IpcBacktrace(); -#endif - PRINT_ERR("A timeout reply, request timestamp:%lld, now:%lld\n", msg->timestamp, now); - return -ETIME; - } -#endif - *dstTid = msg->target.handle; - break; - case MT_DEATH_NOTIFY: - *dstTid = msg->target.handle; -#if (USE_TIMESTAMP == YES) - msg->timestamp = now; -#endif - break; - default: - PRINT_DEBUG("Unknow msg type:%d\n", msg->type); - return -EINVAL; - } - - if (IsTaskAlive(*dstTid) == FALSE) { - return -EINVAL; - } - return LOS_OK; -} - -LITE_OS_SEC_TEXT STATIC UINT32 LiteIpcWrite(IpcContent *content) -{ - UINT32 ret, intSave; - UINT32 dstTid; - - IpcMsg *msg = content->outMsg; - - ret = CheckPara(content, &dstTid); - if (ret != LOS_OK) { - return ret; - } - - UINT32 bufSz = sizeof(IpcListNode) + msg->dataSz + msg->spObjNum * sizeof(UINT32); - IpcListNode *buf = (IpcListNode *)LiteIpcNodeAlloc(OS_TCB_FROM_TID(dstTid)->processID, bufSz); - if (buf == NULL) { - PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__); - return -ENOMEM; - } - ret = CopyDataFromUser(buf, bufSz, (const IpcMsg *)msg); - if (ret != LOS_OK) { - PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__); - goto ERROR_COPY; - } - ret = HandleSpecialObjects(dstTid, buf, FALSE); - if (ret != LOS_OK) { - PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__); - goto ERROR_COPY; - } - /* add data to list and wake up dest task */ - SCHEDULER_LOCK(intSave); - LosTaskCB *tcb = OS_TCB_FROM_TID(dstTid); - LOS_ListTailInsert(&(tcb->msgListHead), &(buf->listNode)); -#if (LOSCFG_KERNEL_TRACE == YES) - IpcTrace(&buf->msg, WRITE, tcb->ipcStatus, buf->msg.type); -#endif - if (tcb->ipcStatus & IPC_THREAD_STATUS_PEND) { - tcb->ipcStatus &= ~IPC_THREAD_STATUS_PEND; - OsTaskWake(tcb); - SCHEDULER_UNLOCK(intSave); - LOS_MpSchedule(OS_MP_CPU_ALL); - LOS_Schedule(); - } else { - SCHEDULER_UNLOCK(intSave); - } - return LOS_OK; -ERROR_COPY: - LiteIpcNodeFree(OS_TCB_FROM_TID(dstTid)->processID, buf); - return ret; -} - -LITE_OS_SEC_TEXT STATIC UINT32 CheckRecievedMsg(IpcListNode *node, IpcContent *content, LosTaskCB *tcb) -{ - UINT32 ret = LOS_OK; - if (node == NULL) { - return -EINVAL; - } - switch (node->msg.type) { - case MT_REQUEST: - if ((content->flag & SEND) == SEND) { - PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__); - ret = -EINVAL; - } - break; - case MT_FAILED_REPLY: - ret = -ENOENT; - /* fall-through */ - case MT_REPLY: - if ((content->flag & SEND) != SEND) { - PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__); - ret = -EINVAL; - } -#if (USE_TIMESTAMP == YES) - if (node->msg.timestamp != content->outMsg->timestamp) { - PRINT_ERR("Recieve a unmatch reply, drop it\n"); - ret = -EINVAL; - } -#else - if ((node->msg.code != content->outMsg->code) || - (node->msg.target.token != content->outMsg->target.token)) { - PRINT_ERR("Recieve a unmatch reply, drop it\n"); - ret = -EINVAL; - } -#endif - break; - case MT_DEATH_NOTIFY: - break; - default: - PRINT_ERR("Unknow msg type:%d\n", node->msg.type); - ret = -EINVAL; - } - if (ret != LOS_OK) { -#if (LOSCFG_KERNEL_TRACE == YES) - IpcTrace(&node->msg, READ_DROP, tcb->ipcStatus, node->msg.type); -#endif - (VOID)HandleSpecialObjects(LOS_CurTaskIDGet(), node, TRUE); - (VOID)LiteIpcNodeFree(LOS_GetCurrProcessID(), (VOID *)node); - } else { -#if (LOSCFG_KERNEL_TRACE == YES) - IpcTrace(&node->msg, READ, tcb->ipcStatus, node->msg.type); -#endif - } - return ret; -} - -LITE_OS_SEC_TEXT STATIC UINT32 LiteIpcRead(IpcContent *content) -{ - UINT32 intSave, ret; - UINT32 selfTid = LOS_CurTaskIDGet(); - LOS_DL_LIST *listHead = NULL; - LOS_DL_LIST *listNode = NULL; - IpcListNode *node = NULL; - UINT32 syncFlag = (content->flag & SEND) && (content->flag & RECV); - UINT32 timeout = syncFlag ? LOS_MS2Tick(LITEIPC_TIMEOUT_MS) : LOS_WAIT_FOREVER; - - LosTaskCB *tcb = OS_TCB_FROM_TID(selfTid); - listHead = &(tcb->msgListHead); - do { - SCHEDULER_LOCK(intSave); - if (LOS_ListEmpty(listHead)) { -#if (LOSCFG_KERNEL_TRACE == YES) - IpcTrace(NULL, TRY_READ, tcb->ipcStatus, syncFlag ? MT_REPLY : MT_REQUEST); -#endif - tcb->ipcStatus |= IPC_THREAD_STATUS_PEND; - ret = OsTaskWait(&g_ipcPendlist, timeout, TRUE); - if (ret == LOS_ERRNO_TSK_TIMEOUT) { -#if (LOSCFG_KERNEL_TRACE == YES) - IpcTrace(NULL, READ_TIMEOUT, tcb->ipcStatus, syncFlag ? MT_REPLY : MT_REQUEST); -#endif - SCHEDULER_UNLOCK(intSave); - return -ETIME; - } - - SCHEDULER_UNLOCK(intSave); - } else { - listNode = LOS_DL_LIST_FIRST(listHead); - LOS_ListDelete(listNode); - node = LOS_DL_LIST_ENTRY(listNode, IpcListNode, listNode); - SCHEDULER_UNLOCK(intSave); - ret = CheckRecievedMsg(node, content, tcb); - if (ret == LOS_OK) { - break; - } - if (ret == -ENOENT) { /* It means that we've recieved a failed reply */ - return ret; - } - } - } while (1); - node->msg.data = (VOID *)GetIpcUserAddr(LOS_GetCurrProcessID(), (INTPTR)(node->msg.data)); - node->msg.offsets = (VOID *)GetIpcUserAddr(LOS_GetCurrProcessID(), (INTPTR)(node->msg.offsets)); - content->inMsg = (VOID *)GetIpcUserAddr(LOS_GetCurrProcessID(), (INTPTR)(&(node->msg))); - EnableIpcNodeFreeByUser(LOS_GetCurrProcessID(), (VOID *)node); - return LOS_OK; -} - -LITE_OS_SEC_TEXT STATIC UINT32 LiteIpcMsgHandle(IpcContent *con) -{ - UINT32 ret = LOS_OK; - IpcContent localContent; - IpcContent *content = &localContent; - IpcMsg localMsg; - IpcMsg *msg = &localMsg; - IpcListNode *nodeNeedFree = NULL; - - if (copy_from_user((void *)content, (const void *)con, sizeof(IpcContent)) != LOS_OK) { - PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__); - return -EINVAL; - } - - if ((content->flag & BUFF_FREE) == BUFF_FREE) { - ret = CheckUsedBuffer(content->buffToFree, &nodeNeedFree); - if (ret != LOS_OK) { - PRINT_ERR("CheckUsedBuffer failed:%d\n", ret); - return ret; - } - } - - if ((content->flag & SEND) == SEND) { - if (content->outMsg == NULL) { - PRINT_ERR("content->outmsg is null\n"); - ret = -EINVAL; - goto BUFFER_FREE; - } - if (copy_from_user((void *)msg, (const void *)content->outMsg, sizeof(IpcMsg)) != LOS_OK) { - PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__); - ret = -EINVAL; - goto BUFFER_FREE; - } - content->outMsg = msg; - if ((content->outMsg->type < 0) || (content->outMsg->type >= MT_DEATH_NOTIFY)) { - PRINT_ERR("LiteIpc unknow msg type:%d\n", content->outMsg->type); - ret = -EINVAL; - goto BUFFER_FREE; - } - ret = LiteIpcWrite(content); - if (ret != LOS_OK) { - PRINT_ERR("LiteIpcWrite failed\n"); - goto BUFFER_FREE; - } - } -BUFFER_FREE: - if (nodeNeedFree != NULL) { - UINT32 freeRet = LiteIpcNodeFree(LOS_GetCurrProcessID(), nodeNeedFree); - ret = (freeRet == LOS_OK) ? ret : freeRet; - } - if (ret != LOS_OK) { - return ret; - } - - if ((content->flag & RECV) == RECV) { - ret = LiteIpcRead(content); - if (ret != LOS_OK) { - PRINT_ERR("LiteIpcRead failed\n"); - return ret; - } - UINT32 offset = LOS_OFF_SET_OF(IpcContent, inMsg); - ret = copy_to_user((char*)con + offset, (char*)content + offset, sizeof(IpcMsg *)); - if (ret != LOS_OK) { - PRINT_ERR("%s, %d, %d\n", __FUNCTION__, __LINE__, ret); - return -EINVAL; - } - } - return ret; -} - -LITE_OS_SEC_TEXT STATIC UINT32 HandleCmsCmd(CmsCmdContent *content) -{ - UINT32 ret = LOS_OK; - CmsCmdContent localContent; - if (content == NULL) { - return -EINVAL; - } - if (IsCmsTask(LOS_CurTaskIDGet()) == FALSE) { - return -EACCES; - } - if (copy_from_user((void *)(&localContent), (const void *)content, sizeof(CmsCmdContent)) != LOS_OK) { - PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__); - return -EINVAL; - } - switch (localContent.cmd) { - case CMS_GEN_HANDLE: - if ((localContent.taskID != 0) && (IsTaskAlive(localContent.taskID) == FALSE)) { - return -EINVAL; - } - ret = GenerateServiceHandle(localContent.taskID, HANDLE_REGISTED, &(localContent.serviceHandle)); - if (ret == LOS_OK) { - ret = copy_to_user((void *)content, (const void *)(&localContent), sizeof(CmsCmdContent)); - } - AddServiceAccess(g_cmsTask.taskID, localContent.serviceHandle); - break; - case CMS_REMOVE_HANDLE: - if (localContent.serviceHandle >= MAX_SERVICE_NUM) { - return -EINVAL; - } - RefreshServiceHandle(localContent.serviceHandle, -1); - break; - case CMS_ADD_ACCESS: - if (IsTaskAlive(localContent.taskID) == FALSE) { - return -EINVAL; - } - return AddServiceAccess(localContent.taskID, localContent.serviceHandle); - default: - PRINT_DEBUG("Unknow cmd cmd:%d\n", localContent.cmd); - return -EINVAL; - } - return ret; -} - -LITE_OS_SEC_TEXT int LiteIpcIoctl(FAR struct file *filep, int cmd, unsigned long arg) -{ - UINT32 ret = LOS_OK; - if (IsPoolMapped() == FALSE) { - PRINT_ERR("Ipc pool not init, need to mmap first!\n"); - return -ENOMEM; - } - switch (cmd) { - case IPC_SET_CMS: - return SetCms(arg); - case IPC_CMS_CMD: - return HandleCmsCmd((CmsCmdContent *)(UINTPTR)arg); - case IPC_SET_IPC_THREAD: - if (IsCmsSet() == FALSE) { - PRINT_ERR("ServiceManager not set!\n"); - return -EINVAL; - } - return SetIpcTask(); - case IPC_SEND_RECV_MSG: - if (arg == 0) { - return -EINVAL; - } - if (IsCmsSet() == FALSE) { - PRINT_ERR("ServiceManager not set!\n"); - return -EINVAL; - } - ret = LiteIpcMsgHandle((IpcContent *)(UINTPTR)arg); - if (ret != LOS_OK) { - return ret; - } - break; - default: - PRINT_ERR("Unknow liteipc ioctl cmd:%d\n", cmd); - return -EINVAL; - } - return ret; -} +/* + * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020, Huawei Device Co., Ltd. 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 the copyright holder 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. + */ + +#include "hm_liteipc.h" +#include "linux/kernel.h" +#include +#include "los_mp.h" +#include "los_mux.h" +#include "los_process_pri.h" +#include "los_spinlock.h" +#include "los_task_pri.h" +#if (LOSCFG_KERNEL_TRACE == YES) +#include "los_trace.h" +#endif +#include "los_vm_map.h" +#include "los_vm_phys.h" +#include "los_vm_page.h" +#include "los_vm_lock.h" + +#define USE_TASKID_AS_HANDLE YES //使用任务ID作为句柄 +#define USE_MMAP YES // +#define IPC_MSG_DATA_SZ_MAX 1024 //最大的消息内容 1K ,posix最大消息内容 64个字节 +#define IPC_MSG_OBJECT_NUM_MAX 256 //最大的消息数量256 ,posix最大消息数量 16个 + +#define LITE_IPC_POOL_NAME "liteipc" //ipc池名称 +#define LITE_IPC_POOL_PAGE_MAX_NUM 64 /* 256KB */ +#define LITE_IPC_POOL_PAGE_DEFAULT_NUM 16 /* 64KB */ +#define LITE_IPC_POOL_MAX_SIZE (LITE_IPC_POOL_PAGE_MAX_NUM << PAGE_SHIFT) +#define LITE_IPC_POOL_DEFAULT_SIZE (LITE_IPC_POOL_PAGE_DEFAULT_NUM << PAGE_SHIFT) +#define LITE_IPC_POOL_UVADDR 0x10000000 +#define INVAILD_ID (-1) + +#define LITEIPC_TIMEOUT_MS 5000UL //超时时间单位毫秒 +#define LITEIPC_TIMEOUT_NS 5000000000ULL //超时时间单位纳秒 + +typedef struct { + LOS_DL_LIST list; + VOID *ptr; +} IpcUsedNode; + +LosMux g_serviceHandleMapMux; +#if (USE_TASKID_AS_HANDLE == YES) +HandleInfo g_cmsTask; +#else +HandleInfo g_serviceHandleMap[MAX_SERVICE_NUM]; +#endif +STATIC LOS_DL_LIST g_ipcPendlist;//阻塞链表,上面挂等待读/写消息的任务 +STATIC LOS_DL_LIST g_ipcUsedNodelist[LOSCFG_BASE_CORE_PROCESS_LIMIT];//IPC节点池,默认等于进程数 + +/* ipc lock */ +SPIN_LOCK_INIT(g_ipcSpin);//初始化IPC自旋锁 +#define IPC_LOCK(state) LOS_SpinLockSave(&g_ipcSpin, &(state)) +#define IPC_UNLOCK(state) LOS_SpinUnlockRestore(&g_ipcSpin, state) + +STATIC int LiteIpcOpen(FAR struct file *filep); +STATIC int LiteIpcClose(FAR struct file *filep); +STATIC int LiteIpcIoctl(FAR struct file *filep, int cmd, unsigned long arg); +STATIC int LiteIpcMmap(FAR struct file* filep, LosVmMapRegion *region); +STATIC UINT32 LiteIpcWrite(IpcContent *content); +STATIC UINT32 GetTid(UINT32 serviceHandle, UINT32 *taskID); +STATIC UINT32 HandleSpecialObjects(UINT32 dstTid, IpcListNode *node, BOOL isRollback); + +//实现VFS接口函数,对liteIpc进行操作 +STATIC const struct file_operations_vfs g_liteIpcFops = { + LiteIpcOpen, /* open */ + LiteIpcClose, /* close */ + NULL, /* read */ + NULL, /* write */ + NULL, /* seek */ + LiteIpcIoctl, /* ioctl */ + LiteIpcMmap, /* mmap */ +#ifndef CONFIG_DISABLE_POLL + NULL, /* poll */ +#endif + NULL, /* unlink */ +}; + +#if (LOSCFG_KERNEL_TRACE == YES) +const char *g_operStr[OPERATION_NUM] = {"WRITE", "WRITE_DROP", "TRY_READ", "READ", "READ_DROP", "READ_TIMEOUT"}; +const char *g_msgTypeStr[MT_NUM] = {"REQUEST", "REPLY", "DEATH_NOTIFY"}; +const char *g_ipcStatusStr[2] = {"NOT_PEND", "PEND"}; + +LITE_OS_SEC_TEXT STATIC UINT16 IpcTraceHook(UINT8 *inputBuffer, UINT32 id, UINT32 msg) +{ + IpcTraceFrame *ipcInfo = NULL; + if (inputBuffer == NULL) { + return 0; + } + + ipcInfo = (IpcTraceFrame *)inputBuffer; + ipcInfo->idInfo = id; + ipcInfo->msgInfo = msg; + ipcInfo->timestamp = LOS_CurrNanosec(); + + return sizeof(IpcTraceFrame); +} + +LITE_OS_SEC_TEXT STATIC VOID IpcTrace(IpcMsg *msg, UINT32 operation, UINT32 ipcStatus, UINT32 msgType) +{ + UINT32 curTid = LOS_CurTaskIDGet(); + UINT32 curPid = LOS_GetCurrProcessID(); + UINT32 dstTid; + UINT32 ret = (msg == NULL) ? INVAILD_ID : GetTid(msg->target.handle, &dstTid); + IdArg id = {INVAILD_ID, INVAILD_ID, INVAILD_ID, INVAILD_ID}; + MsgArg msgArg; + if (operation <= WRITE_DROP) { + id.srcTid = curTid; + id.srcPid = curPid; + id.dstTid = ret ? INVAILD_ID : dstTid; + id.dstPid = ret ? INVAILD_ID : OS_TCB_FROM_TID(dstTid)->processID; + } else { + id.srcTid = (msg == NULL) ? INVAILD_ID : msg->taskID; + id.srcPid = (msg == NULL) ? INVAILD_ID : msg->processID; + id.dstTid = curTid; + id.dstPid = curPid; + } + msgArg.msgType = msgType; + msgArg.code = (msg == NULL) ? INVAILD_ID : msg->code; + msgArg.operation = operation; + msgArg.ipcStatus = ipcStatus; + + VOID *ptr1 = &id; + VOID *ptr2 = &msgArg; + LOS_Trace(LOS_TRACE_IPC, *((UINT32 *)ptr1), *((UINT32 *)ptr2)); +} + +UINT32 IpcInfoCheck(IpcTraceFrame *ipcInfo) +{ + MsgArg *msgArg = NULL; + + if (ipcInfo == NULL) { + return LOS_NOK; + } + + msgArg = (MsgArg *)&ipcInfo->msgInfo; + if ((msgArg->operation >= OPERATION_NUM) || + (msgArg->msgType >= MT_NUM)) { + return LOS_NOK; + } + + return LOS_OK; +} + +LITE_OS_SEC_TEXT STATIC VOID IpcTracePrint(UINT32 cpuID, IpcTraceFrame *ipcInfo) +{ + IdArg *idArg = (IdArg *)&ipcInfo->idInfo; + MsgArg *msgArg = (MsgArg *)&ipcInfo->msgInfo; + + if (IpcInfoCheck(ipcInfo) != LOS_OK) { + return; + } + + PRINTK("[LiteIPCTrace]timestamp:%016lld", ipcInfo->timestamp); + PRINTK(" cpuID:%02d", cpuID); + PRINTK(" operation:%13s", g_operStr[msgArg->operation]); + PRINTK(" msgType:%12s", g_msgTypeStr[msgArg->msgType]); + UINT32 isPend = (msgArg->ipcStatus & IPC_THREAD_STATUS_PEND) == IPC_THREAD_STATUS_PEND; + PRINTK(" ipcStatus:%9s", g_ipcStatusStr[isPend]); + PRINTK(" code:%03d", msgArg->code); + PRINTK(" srcTid:%03d", idArg->srcTid); + PRINTK(" srcPid:%03d", idArg->srcPid); + PRINTK(" dstTid:%03d", idArg->dstTid); + PRINTK(" dstPid:%03d\n", idArg->dstPid); +} + +VOID IpcBacktrace(VOID) +{ + INT32 pos; + INT32 i; + TraceBuffer buff; + for (i = 0; i < LOSCFG_KERNEL_CORE_NUM; i++) { + LOS_TraceBufGet(&buff, i); + pos = buff.tracePos; + while (pos >= sizeof(IpcTraceFrame) + LOS_TRACE_TAG_LENGTH) { + UINT32 *traceType = (UINT32 *)(buff.dataBuf + pos - LOS_TRACE_TAG_LENGTH); + pos -= sizeof(IpcTraceFrame) + LOS_TRACE_TAG_LENGTH; + switch (*traceType) { + case LOS_TRACE_IPC: { + IpcTraceFrame *ipcInfo = (IpcTraceFrame *)(buff.dataBuf + pos); + IpcTracePrint(i, ipcInfo); + break; + } + default: + PRINTK("other module trace\n"); + break; + } + } + } +} +#endif +//liteIpc 初始化 +LITE_OS_SEC_TEXT_INIT UINT32 LiteIpcInit(VOID) +{ + UINT32 ret, i; +#if (USE_TASKID_AS_HANDLE == YES) + g_cmsTask.status = HANDLE_NOT_USED; +#else + memset_s(g_serviceHandleMap, sizeof(g_serviceHandleMap), 0, sizeof(g_serviceHandleMap)); +#endif + ret = LOS_MuxInit(&g_serviceHandleMapMux, NULL); + if (ret != LOS_OK) { + return ret; + } + ret = (UINT32)register_driver(LITEIPC_DRIVER, &g_liteIpcFops, DRIVER_MODE, NULL); + if (ret != LOS_OK) { + PRINT_ERR("register lite_ipc driver failed:%d\n", ret); + } + LOS_ListInit(&(g_ipcPendlist)); + for (i = 0; i < LOSCFG_BASE_CORE_PROCESS_LIMIT; i++) { + LOS_ListInit(&(g_ipcUsedNodelist[i])); + } +#if (LOSCFG_KERNEL_TRACE == YES) + ret = LOS_TraceUserReg(LOS_TRACE_IPC, IpcTraceHook, sizeof(IpcTraceFrame)); + if (ret != LOS_OK) { + PRINT_ERR("liteipc LOS_TraceUserReg failed:%d\n", ret); + } +#endif + return ret; +} + +LITE_OS_SEC_TEXT STATIC int LiteIpcOpen(FAR struct file *filep) +{ + return 0; +} + +LITE_OS_SEC_TEXT STATIC int LiteIpcClose(FAR struct file *filep) +{ + return 0; +} + +LITE_OS_SEC_TEXT STATIC BOOL IsPoolMapped(VOID) +{ + LosProcessCB *pcb = OsCurrProcessGet(); + return (pcb->ipcInfo.pool.uvaddr != NULL) && (pcb->ipcInfo.pool.kvaddr != NULL) && + (pcb->ipcInfo.pool.poolSize != 0); +} + +LITE_OS_SEC_TEXT STATIC INT32 DoIpcMmap(LosProcessCB *pcb, LosVmMapRegion *region) +{ + UINT32 i; + INT32 ret = 0; + PADDR_T pa; + UINT32 uflags = VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_USER; + LosVmPage *vmPage = NULL; + VADDR_T uva = (VADDR_T)(UINTPTR)pcb->ipcInfo.pool.uvaddr; + VADDR_T kva = (VADDR_T)(UINTPTR)pcb->ipcInfo.pool.kvaddr; + + (VOID)LOS_MuxAcquire(&pcb->vmSpace->regionMux); + + for (i = 0; i < (region->range.size >> PAGE_SHIFT); i++) { + pa = LOS_PaddrQuery((VOID *)(UINTPTR)(kva + (i << PAGE_SHIFT))); + if (pa == 0) { + PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__); + ret = -EINVAL; + break; + } + vmPage = LOS_VmPageGet(pa); + if (vmPage == NULL) { + PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__); + ret = -EINVAL; + break; + } + STATUS_T err = LOS_ArchMmuMap(&pcb->vmSpace->archMmu, uva + (i << PAGE_SHIFT), pa, 1, uflags); + if (err < 0) { + ret = err; + PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__); + break; + } + LOS_AtomicInc(&vmPage->refCounts); + } + /* if any failure happened, rollback */ + if (i != (region->range.size >> PAGE_SHIFT)) { + while (i--) { + pa = LOS_PaddrQuery((VOID *)(UINTPTR)(kva + (i << PAGE_SHIFT))); + vmPage = LOS_VmPageGet(pa); + (VOID)LOS_ArchMmuUnmap(&pcb->vmSpace->archMmu, uva + (i << PAGE_SHIFT), 1); + LOS_PhysPageFree(vmPage); + } + } + + (VOID)LOS_MuxRelease(&pcb->vmSpace->regionMux); + return ret; +} + +LITE_OS_SEC_TEXT STATIC int LiteIpcMmap(FAR struct file* filep, LosVmMapRegion *region) +{ + int ret = 0; + LosVmMapRegion *regionTemp = NULL; + LosProcessCB *pcb = OsCurrProcessGet(); + if ((region == NULL) || (region->range.size > LITE_IPC_POOL_MAX_SIZE) || + (!LOS_IsRegionPermUserReadOnly(region)) || (!LOS_IsRegionFlagPrivateOnly(region))) { + ret = -EINVAL; + goto ERROR_REGION_OUT; + } + if (IsPoolMapped()) { + return -EEXIST; + } + if (pcb->ipcInfo.pool.uvaddr != NULL) { + regionTemp = LOS_RegionFind(pcb->vmSpace, (VADDR_T)(UINTPTR)pcb->ipcInfo.pool.uvaddr); + if (regionTemp != NULL) { + (VOID)LOS_RegionFree(pcb->vmSpace, regionTemp); + } + } + pcb->ipcInfo.pool.uvaddr = (VOID *)(UINTPTR)region->range.base; + if (pcb->ipcInfo.pool.kvaddr != NULL) { + LOS_VFree(pcb->ipcInfo.pool.kvaddr); + pcb->ipcInfo.pool.kvaddr = NULL; + } + /* use vmalloc to alloc phy mem */ + pcb->ipcInfo.pool.kvaddr = LOS_VMalloc(region->range.size); + if (pcb->ipcInfo.pool.kvaddr == NULL) { + ret = -ENOMEM; + goto ERROR_REGION_OUT; + } + /* do mmap */ + ret = DoIpcMmap(pcb, region); + if (ret) { + goto ERROR_MAP_OUT; + } + /* ipc pool init */ + if (LOS_MemInit(pcb->ipcInfo.pool.kvaddr, region->range.size) != LOS_OK) { + ret = -EINVAL; + goto ERROR_MAP_OUT; + } + pcb->ipcInfo.pool.poolSize = region->range.size; + return 0; +ERROR_MAP_OUT: + LOS_VFree(pcb->ipcInfo.pool.kvaddr); +ERROR_REGION_OUT: + pcb->ipcInfo.pool.uvaddr = NULL; + pcb->ipcInfo.pool.kvaddr = NULL; + return ret; +} + +LITE_OS_SEC_TEXT_INIT UINT32 LiteIpcPoolInit(ProcIpcInfo *ipcInfo) +{ + ipcInfo->pool.uvaddr = NULL; + ipcInfo->pool.kvaddr = NULL; + ipcInfo->pool.poolSize = 0; + ipcInfo->ipcTaskID = INVAILD_ID; + return LOS_OK; +} + +LITE_OS_SEC_TEXT UINT32 LiteIpcPoolReInit(ProcIpcInfo *child, const ProcIpcInfo *parent) +{ + child->pool.uvaddr = parent->pool.uvaddr; + child->pool.kvaddr = NULL; + child->pool.poolSize = 0; + child->ipcTaskID = INVAILD_ID; + return LOS_OK; +} + +LITE_OS_SEC_TEXT VOID LiteIpcPoolDelete(ProcIpcInfo *ipcInfo) +{ + UINT32 intSave; + IpcUsedNode *node = NULL; + UINT32 processID = LOS_GetCurrProcessID(); + if (ipcInfo->pool.kvaddr != NULL) { + LOS_VFree(ipcInfo->pool.kvaddr); + ipcInfo->pool.kvaddr = NULL; + IPC_LOCK(intSave); + while (!LOS_ListEmpty(&g_ipcUsedNodelist[processID])) { + node = LOS_DL_LIST_ENTRY(g_ipcUsedNodelist[processID].pstNext, IpcUsedNode, list); + LOS_ListDelete(&node->list); + free(node); + } + IPC_UNLOCK(intSave); + } + /* remove process access to service */ + for (UINT32 i = 0; i < MAX_SERVICE_NUM; i++) { + if (ipcInfo->access[i] == TRUE) { + ipcInfo->access[i] = FALSE; + OS_TCB_FROM_TID(i)->accessMap[processID] = FALSE; + } + } +} + +/* Only when kernenl no longer access ipc node content, can user free the ipc node */ +LITE_OS_SEC_TEXT STATIC VOID EnableIpcNodeFreeByUser(UINT32 processID, VOID *buf) +{ + UINT32 intSave; + IpcUsedNode *node = (IpcUsedNode *)malloc(sizeof(IpcUsedNode)); + if (node != NULL) { + node->ptr = buf; + IPC_LOCK(intSave); + LOS_ListAdd(&g_ipcUsedNodelist[processID], &node->list); + IPC_UNLOCK(intSave); + } +} + +LITE_OS_SEC_TEXT STATIC VOID* LiteIpcNodeAlloc(UINT32 processID, UINT32 size) +{ + VOID *ptr = LOS_MemAlloc(OS_PCB_FROM_PID(processID)->ipcInfo.pool.kvaddr, size); + PRINT_INFO("LiteIpcNodeAlloc pid:%d, pool:%x buf:%x size:%d\n", + processID, OS_PCB_FROM_PID(processID)->ipcInfo.pool.kvaddr, ptr, size); + return ptr; +} + +LITE_OS_SEC_TEXT STATIC UINT32 LiteIpcNodeFree(UINT32 processID, VOID *buf) +{ + PRINT_INFO("LiteIpcNodeFree pid:%d, pool:%x buf:%x\n", + processID, OS_PCB_FROM_PID(processID)->ipcInfo.pool.kvaddr, buf); + return LOS_MemFree(OS_PCB_FROM_PID(processID)->ipcInfo.pool.kvaddr, buf); +} + +LITE_OS_SEC_TEXT STATIC BOOL IsIpcNode(UINT32 processID, const VOID *buf) +{ + IpcUsedNode *node = NULL; + UINT32 intSave; + IPC_LOCK(intSave); + LOS_DL_LIST_FOR_EACH_ENTRY(node, &g_ipcUsedNodelist[processID], IpcUsedNode, list) { + if (node->ptr == buf) { + LOS_ListDelete(&node->list); + IPC_UNLOCK(intSave); + free(node); + return TRUE; + } + } + IPC_UNLOCK(intSave); + return FALSE; +} + +LITE_OS_SEC_TEXT STATIC INTPTR GetIpcUserAddr(UINT32 processID, INTPTR kernelAddr) +{ + IpcPool pool = OS_PCB_FROM_PID(processID)->ipcInfo.pool; + INTPTR offset = (INTPTR)(pool.uvaddr) - (INTPTR)(pool.kvaddr); + return kernelAddr + offset; +} + +LITE_OS_SEC_TEXT STATIC INTPTR GetIpcKernelAddr(UINT32 processID, INTPTR userAddr) +{ + IpcPool pool = OS_PCB_FROM_PID(processID)->ipcInfo.pool; + INTPTR offset = (INTPTR)(pool.uvaddr) - (INTPTR)(pool.kvaddr); + return userAddr - offset; +} + +LITE_OS_SEC_TEXT STATIC UINT32 CheckUsedBuffer(const VOID *node, IpcListNode **outPtr) +{ + VOID *ptr = NULL; + LosProcessCB *pcb = OsCurrProcessGet(); + IpcPool pool = pcb->ipcInfo.pool; + if ((node == NULL) || ((INTPTR)node < (INTPTR)(pool.uvaddr)) || + ((INTPTR)node > (INTPTR)(pool.uvaddr) + pool.poolSize)) { + return -EINVAL; + } + ptr = (VOID *)GetIpcKernelAddr(pcb->processID, (INTPTR)(node)); + if (IsIpcNode(pcb->processID, ptr) != TRUE) { + return -EFAULT; + } + *outPtr = (IpcListNode *)ptr; + return LOS_OK; +} + +LITE_OS_SEC_TEXT STATIC UINT32 GetTid(UINT32 serviceHandle, UINT32 *taskID) +{ + if (serviceHandle >= MAX_SERVICE_NUM) { + return -EINVAL; + } +#if (USE_TASKID_AS_HANDLE == YES) + *taskID = serviceHandle ? serviceHandle : g_cmsTask.taskID; + return LOS_OK; +#else + if (g_serviceHandleMap[serviceHandle].status == HANDLE_REGISTED) { + *taskID = g_serviceHandleMap[serviceHandle].taskID; + return LOS_OK; + } + return -EINVAL; +#endif +} + +LITE_OS_SEC_TEXT STATIC UINT32 GenerateServiceHandle(UINT32 taskID, HandleStatus status, UINT32 *serviceHandle) +{ +#if (USE_TASKID_AS_HANDLE == YES) + *serviceHandle = taskID ? taskID : LOS_CurTaskIDGet(); /* if taskID is 0, return curTaskID */ + if (*serviceHandle == g_cmsTask.taskID) { + return -EINVAL; + } + return LOS_OK; +#else + UINT32 i; + (VOID)LOS_MuxLock(&g_serviceHandleMapMux, LOS_WAIT_FOREVER); + for (i = 1; i < MAX_SERVICE_NUM; i++) { + if (g_serviceHandleMap[i].status == HANDLE_NOT_USED) { + g_serviceHandleMap[i].taskID = taskID; + g_serviceHandleMap[i].status = status; + *serviceHandle = i; + (VOID)LOS_MuxUnLock(&g_serviceHandleMapMux); + return LOS_OK; + } + } + (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux); + return -EINVAL; +#endif +} + +LITE_OS_SEC_TEXT STATIC VOID RefreshServiceHandle(UINT32 serviceHandle, UINT32 result) +{ +#if (USE_TASKID_AS_HANDLE == NO) + (VOID)LOS_MuxLock(&g_serviceHandleMapMux, LOS_WAIT_FOREVER); + if ((result == LOS_OK) && (g_serviceHandleMap[serviceHandle].status == HANDLE_REGISTING)) { + g_serviceHandleMap[serviceHandle].status = HANDLE_REGISTED; + } else { + g_serviceHandleMap[serviceHandle].status = HANDLE_NOT_USED; + } + (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux); +#endif +} + +LITE_OS_SEC_TEXT STATIC UINT32 AddServiceAccess(UINT32 taskID, UINT32 serviceHandle) +{ + UINT32 serviceTid = 0; + UINT32 ret = GetTid(serviceHandle, &serviceTid); + if (ret != LOS_OK) { + PRINT_ERR("AddServiceAccess GetTid failed\n"); + return ret; + } + UINT32 processID = OS_TCB_FROM_TID(taskID)->processID; + OS_TCB_FROM_TID(serviceTid)->accessMap[processID] = TRUE; + OS_PCB_FROM_PID(processID)->ipcInfo.access[serviceTid] = TRUE; + return LOS_OK; +} + +LITE_OS_SEC_TEXT STATIC BOOL HasServiceAccess(UINT32 serviceHandle) +{ + UINT32 serviceTid = 0; + UINT32 curProcessID = LOS_GetCurrProcessID(); + UINT32 ret; + if (serviceHandle >= MAX_SERVICE_NUM) { + return FALSE; + } + if (serviceHandle == 0) { + return TRUE; + } + ret = GetTid(serviceHandle, &serviceTid); + if (ret != LOS_OK) { + PRINT_ERR("HasServiceAccess GetTid failed\n"); + return FALSE; + } + if (OS_TCB_FROM_TID(serviceTid)->processID == curProcessID) { + return TRUE; + } + return OS_TCB_FROM_TID(serviceTid)->accessMap[curProcessID]; +} + +LITE_OS_SEC_TEXT STATIC UINT32 SetIpcTask(VOID) +{ + if (OsCurrProcessGet()->ipcInfo.ipcTaskID == INVAILD_ID) { + OsCurrProcessGet()->ipcInfo.ipcTaskID = LOS_CurTaskIDGet(); + return OsCurrProcessGet()->ipcInfo.ipcTaskID; + } + PRINT_ERR("curprocess %d IpcTask already set!\n", OsCurrProcessGet()->processID); + return -EINVAL; +} + +LITE_OS_SEC_TEXT BOOL IsIpcTaskSet(VOID) +{ + if (OsCurrProcessGet()->ipcInfo.ipcTaskID == INVAILD_ID) { + return FALSE; + } + return TRUE; +} + +LITE_OS_SEC_TEXT STATIC UINT32 GetIpcTaskID(UINT32 processID, UINT32 *ipcTaskID) +{ + if (OS_PCB_FROM_PID(processID)->ipcInfo.ipcTaskID == INVAILD_ID) { + return LOS_NOK; + } + *ipcTaskID = OS_PCB_FROM_PID(processID)->ipcInfo.ipcTaskID; + return LOS_OK; +} + +LITE_OS_SEC_TEXT STATIC UINT32 SendDeathMsg(UINT32 processID, UINT32 serviceHandle) +{ + UINT32 ipcTaskID; + UINT32 ret; + IpcContent content; + IpcMsg msg; + + OS_PCB_FROM_PID(processID)->ipcInfo.access[serviceHandle] = false; + + ret = GetIpcTaskID(processID, &ipcTaskID); + if (ret != LOS_OK) { + return -EINVAL; + } + content.flag = SEND; + content.outMsg = &msg; + memset_s(content.outMsg, sizeof(IpcMsg), 0, sizeof(IpcMsg)); + content.outMsg->type = MT_DEATH_NOTIFY; + content.outMsg->target.handle = ipcTaskID; + content.outMsg->target.token = serviceHandle; + content.outMsg->code = 0; + return LiteIpcWrite(&content); +} + +LITE_OS_SEC_TEXT VOID LiteIpcRemoveServiceHandle(LosTaskCB *taskCB) +{ + UINT32 j; +#if (USE_TASKID_AS_HANDLE == YES) + + UINT32 intSave; + LOS_DL_LIST *listHead = NULL; + LOS_DL_LIST *listNode = NULL; + IpcListNode *node = NULL; + UINT32 processID = taskCB->processID; + + listHead = &(taskCB->msgListHead); + do { + SCHEDULER_LOCK(intSave); + if (LOS_ListEmpty(listHead)) { + SCHEDULER_UNLOCK(intSave); + break; + } else { + listNode = LOS_DL_LIST_FIRST(listHead); + LOS_ListDelete(listNode); + node = LOS_DL_LIST_ENTRY(listNode, IpcListNode, listNode); + SCHEDULER_UNLOCK(intSave); + (VOID)HandleSpecialObjects(taskCB->taskID, node, TRUE); + (VOID)LiteIpcNodeFree(processID, (VOID *)node); + } + } while (1); + + taskCB->accessMap[processID] = FALSE; + for (j = 0; j < MAX_SERVICE_NUM; j++) { + if (taskCB->accessMap[j] == TRUE) { + taskCB->accessMap[j] = FALSE; + (VOID)SendDeathMsg(j, taskCB->taskID); + } + } +#else + (VOID)LOS_MuxLock(&g_serviceHandleMapMux, LOS_WAIT_FOREVER); + for (UINT32 i = 1; i < MAX_SERVICE_NUM; i++) { + if ((g_serviceHandleMap[i].status != HANDLE_NOT_USED) && (g_serviceHandleMap[i].taskID == taskCB->taskID)) { + g_serviceHandleMap[i].status = HANDLE_NOT_USED; + g_serviceHandleMap[i].taskID = INVAILD_ID; + break; + } + } + (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux); + /* run deathHandler */ + if (i < MAX_SERVICE_NUM) { + for (j = 0; j < MAX_SERVICE_NUM; j++) { + if (taskCB->accessMap[j] == TRUE) { + (VOID)SendDeathMsg(j, i); + } + } + } +#endif +} + +LITE_OS_SEC_TEXT STATIC UINT32 SetCms(UINTPTR maxMsgSize) +{ + if (maxMsgSize < sizeof(IpcMsg)) { + return -EINVAL; + } + (VOID)LOS_MuxLock(&g_serviceHandleMapMux, LOS_WAIT_FOREVER); +#if (USE_TASKID_AS_HANDLE == YES) + if (g_cmsTask.status == HANDLE_NOT_USED) { + g_cmsTask.status = HANDLE_REGISTED; + g_cmsTask.taskID = LOS_CurTaskIDGet(); + g_cmsTask.maxMsgSize = maxMsgSize; + (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux); + return LOS_OK; + } +#else + if (g_serviceHandleMap[0].status == HANDLE_NOT_USED) { + g_serviceHandleMap[0].status = HANDLE_REGISTED; + g_serviceHandleMap[0].taskID = LOS_CurTaskIDGet(); + (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux); + return LOS_OK; + } +#endif + (VOID)LOS_MuxUnlock(&g_serviceHandleMapMux); + return -EEXIST; +} + +LITE_OS_SEC_TEXT STATIC BOOL IsCmsSet(VOID) +{ +#if (USE_TASKID_AS_HANDLE == YES) + return g_cmsTask.status == HANDLE_REGISTED; +#else + return g_serviceHandleMap[0].status == HANDLE_REGISTED; +#endif +} + +LITE_OS_SEC_TEXT STATIC BOOL IsCmsTask(UINT32 taskID) +{ +#if (USE_TASKID_AS_HANDLE == YES) + return IsCmsSet() ? (OS_TCB_FROM_TID(taskID)->processID == OS_TCB_FROM_TID(g_cmsTask.taskID)->processID) : FALSE; +#else + return IsCmsSet() ? (OS_TCB_FROM_TID(taskID)->processID == + OS_TCB_FROM_TID(g_serviceHandleMap[0].taskID)->processID) : FALSE; +#endif +} + +LITE_OS_SEC_TEXT STATIC BOOL IsTaskAlive(UINT32 taskID) +{ + LosTaskCB *tcb = NULL; + if (OS_TID_CHECK_INVALID(taskID)) { + return FALSE; + } + tcb = OS_TCB_FROM_TID(taskID); + if (!OsProcessIsUserMode(OS_PCB_FROM_PID(tcb->processID))) { + return FALSE; + } + if (OsTaskIsInactive(tcb)) { + return FALSE; + } + return TRUE; +} + +LITE_OS_SEC_TEXT STATIC UINT32 HandleFd(SpecialObj *obj, BOOL isRollback) +{ + /* now fd is not Isolated between processes, do nothing */ + return LOS_OK; +} + +LITE_OS_SEC_TEXT STATIC UINT32 HandlePtr(UINT32 processID, SpecialObj *obj, BOOL isRollback) +{ + VOID *buf = NULL; + UINT32 ret; + if ((obj->content.ptr.buff == NULL) || (obj->content.ptr.buffSz == 0)) { + return -EINVAL; + } + if (isRollback == FALSE) { + if (LOS_IsUserAddress((vaddr_t)(UINTPTR)(obj->content.ptr.buff)) == FALSE) { + PRINT_ERR("Bad ptr address\n"); + return -EINVAL; + } + buf = LiteIpcNodeAlloc(processID, obj->content.ptr.buffSz); + if (buf == NULL) { + PRINT_ERR("DealPtr alloc mem failed\n"); + return -EINVAL; + } + ret = copy_from_user(buf, obj->content.ptr.buff, obj->content.ptr.buffSz); + if (ret != LOS_OK) { + LiteIpcNodeFree(processID, buf); + return ret; + } + obj->content.ptr.buff = (VOID *)GetIpcUserAddr(processID, (INTPTR)buf); + EnableIpcNodeFreeByUser(processID, (VOID *)buf); + } else { + (VOID)LiteIpcNodeFree(processID, (VOID *)GetIpcKernelAddr(processID, (INTPTR)obj->content.ptr.buff)); + } + return LOS_OK; +} + +LITE_OS_SEC_TEXT STATIC UINT32 HandleSvc(UINT32 dstTid, const SpecialObj *obj, BOOL isRollback) +{ + UINT32 taskID = 0; + if (isRollback == FALSE) { + if (IsTaskAlive(obj->content.svc.handle) == FALSE) { + PRINT_ERR("HandleSvc wrong svctid\n"); + return -EINVAL; + } + if (HasServiceAccess(obj->content.svc.handle) == FALSE) { + PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__); + return -EACCES; + } + if (GetTid(obj->content.svc.handle, &taskID) == 0) { + if (taskID == OS_PCB_FROM_PID(OS_TCB_FROM_TID(taskID)->processID)->ipcInfo.ipcTaskID) { + AddServiceAccess(dstTid, obj->content.svc.handle); + } + } + } + return LOS_OK; +} + +LITE_OS_SEC_TEXT STATIC UINT32 HandleObj(UINT32 dstTid, SpecialObj *obj, BOOL isRollback) +{ + UINT32 ret; + UINT32 processID = OS_TCB_FROM_TID(dstTid)->processID; + switch (obj->type) { + case OBJ_FD: + ret = HandleFd(obj, isRollback); + break; + case OBJ_PTR: + ret = HandlePtr(processID, obj, isRollback); + break; + case OBJ_SVC: + ret = HandleSvc(dstTid, (const SpecialObj *)obj, isRollback); + break; + default: + ret = -EINVAL; + break; + } + return ret; +} + +LITE_OS_SEC_TEXT STATIC UINT32 HandleSpecialObjects(UINT32 dstTid, IpcListNode *node, BOOL isRollback) +{ + UINT32 ret = LOS_OK; + IpcMsg *msg = &(node->msg); + INT32 i; + SpecialObj *obj = NULL; + UINT32 *offset = (UINT32 *)(UINTPTR)(msg->offsets); + if (isRollback) { + i = msg->spObjNum; + goto EXIT; + } + for (i = 0; i < msg->spObjNum; i++) { + if (offset[i] > msg->dataSz - sizeof(SpecialObj)) { + ret = -EINVAL; + goto EXIT; + } + if ((i > 0) && (offset[i] < offset[i - 1] + sizeof(SpecialObj))) { + ret = -EINVAL; + goto EXIT; + } + obj = (SpecialObj *)((UINTPTR)msg->data + offset[i]); + if (obj == NULL) { + ret = -EINVAL; + goto EXIT; + } + ret = HandleObj(dstTid, obj, FALSE); + if (ret != LOS_OK) { + goto EXIT; + } + } + return LOS_OK; +EXIT: + for (i--; i >= 0; i--) { + obj = (SpecialObj *)((UINTPTR)msg->data + offset[i]); + (VOID)HandleObj(dstTid, obj, TRUE); + } + return ret; +} + +LITE_OS_SEC_TEXT STATIC UINT32 CheckMsgSize(IpcMsg *msg) +{ + UINT64 totalSize; + UINT32 i; + UINT32 *offset = (UINT32 *)(UINTPTR)(msg->offsets); + SpecialObj *obj = NULL; + if (msg->target.handle != 0) { + return LOS_OK; + } + /* msg send to cms, check the msg size */ + totalSize = (UINT64)sizeof(IpcMsg) + msg->dataSz + msg->spObjNum * sizeof(UINT32); + for (i = 0; i < msg->spObjNum; i++) { + if (offset[i] > msg->dataSz - sizeof(SpecialObj)) { + return -EINVAL; + } + if ((i > 0) && (offset[i] < offset[i - 1] + sizeof(SpecialObj))) { + return -EINVAL; + } + obj = (SpecialObj *)((UINTPTR)msg->data + offset[i]); + if (obj == NULL) { + return -EINVAL; + } + if (obj->type == OBJ_PTR) { + totalSize += obj->content.ptr.buffSz; + } + } + if (totalSize > g_cmsTask.maxMsgSize) { + return -EINVAL; + } + return LOS_OK; +} + +LITE_OS_SEC_TEXT STATIC UINT32 CopyDataFromUser(IpcListNode *node, UINT32 bufSz, const IpcMsg *msg) +{ + UINT32 ret; + ret = (UINT32)memcpy_s((VOID *)(&node->msg), bufSz - sizeof(LOS_DL_LIST), (const VOID *)msg, sizeof(IpcMsg)); + if (ret != LOS_OK) { + PRINT_DEBUG("%s, %d, %u\n", __FUNCTION__, __LINE__, ret); + return ret; + } + + if (msg->dataSz) { + node->msg.data = (VOID *)((UINTPTR)node + sizeof(IpcListNode)); + ret = copy_from_user((VOID *)(node->msg.data), msg->data, msg->dataSz); + if (ret != LOS_OK) { + PRINT_DEBUG("%s, %d\n", __FUNCTION__, __LINE__); + return ret; + } + } else { + node->msg.data = NULL; + } + + if (msg->spObjNum) { + node->msg.offsets = (VOID *)((UINTPTR)node + sizeof(IpcListNode) + msg->dataSz); + ret = copy_from_user((VOID *)(node->msg.offsets), msg->offsets, msg->spObjNum * sizeof(UINT32)); + if (ret != LOS_OK) { + PRINT_DEBUG("%s, %d, %x, %x, %d\n", __FUNCTION__, __LINE__, node->msg.offsets, msg->offsets, msg->spObjNum); + return ret; + } + } else { + node->msg.offsets = NULL; + } + ret = CheckMsgSize(&node->msg); + if (ret != LOS_OK) { + PRINT_DEBUG("%s, %d\n", __FUNCTION__, __LINE__); + return ret; + } + node->msg.taskID = LOS_CurTaskIDGet(); + node->msg.processID = OsCurrProcessGet()->processID; +#ifdef LOSCFG_SECURITY_CAPABILITY + node->msg.userID = OsCurrProcessGet()->user->userID; + node->msg.gid = OsCurrProcessGet()->user->gid; +#endif + return LOS_OK; +} + +LITE_OS_SEC_TEXT STATIC BOOL IsLeagalReply(const IpcContent *content) +{ + UINT32 curProcessID = LOS_GetCurrProcessID(); + IpcListNode *node = (IpcListNode *)GetIpcKernelAddr(curProcessID, (INTPTR)(content->buffToFree)); + IpcMsg *requestMsg = &node->msg; + IpcMsg *replyMsg = content->outMsg; + UINT32 reqDstTid = 0; + /* Check whether the reply matches the request */ + if ((requestMsg->type != MT_REQUEST) || + (requestMsg->flag == LITEIPC_FLAG_ONEWAY) || + (replyMsg->timestamp != requestMsg->timestamp) || + (replyMsg->target.handle != requestMsg->taskID) || + (GetTid(requestMsg->target.handle, &reqDstTid) != 0) || + (OS_TCB_FROM_TID(reqDstTid)->processID != curProcessID)) { + return FALSE; + } + return TRUE; +} + +LITE_OS_SEC_TEXT STATIC UINT32 CheckPara(IpcContent *content, UINT32 *dstTid) +{ + UINT32 ret; + IpcMsg *msg = content->outMsg; + UINT32 flag = content->flag; +#if (USE_TIMESTAMP == YES) + UINT64 now = LOS_CurrNanosec(); +#endif + if (((msg->dataSz > 0) && (msg->data == NULL)) || + ((msg->spObjNum > 0) && (msg->offsets == NULL)) || + (msg->dataSz > IPC_MSG_DATA_SZ_MAX) || + (msg->spObjNum > IPC_MSG_OBJECT_NUM_MAX) || + (msg->dataSz < msg->spObjNum * sizeof(SpecialObj))) { + return -EINVAL; + } + switch (msg->type) { + case MT_REQUEST: + if (HasServiceAccess(msg->target.handle)) { + ret = GetTid(msg->target.handle, dstTid); + if (ret != LOS_OK) { + return -EINVAL; + } + } else { + PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__); + return -EACCES; + } +#if (USE_TIMESTAMP == YES) + msg->timestamp = now; +#endif + break; + case MT_REPLY: + case MT_FAILED_REPLY: + if ((flag & BUFF_FREE) != BUFF_FREE) { + return -EINVAL; + } + if (!IsLeagalReply(content)) { + return -EINVAL; + } +#if (USE_TIMESTAMP == YES) + if (now > msg->timestamp + LITEIPC_TIMEOUT_NS) { +#if (LOSCFG_KERNEL_TRACE == YES) + IpcTrace(msg, WRITE_DROP, 0, msg->type); + IpcBacktrace(); +#endif + PRINT_ERR("A timeout reply, request timestamp:%lld, now:%lld\n", msg->timestamp, now); + return -ETIME; + } +#endif + *dstTid = msg->target.handle; + break; + case MT_DEATH_NOTIFY: + *dstTid = msg->target.handle; +#if (USE_TIMESTAMP == YES) + msg->timestamp = now; +#endif + break; + default: + PRINT_DEBUG("Unknow msg type:%d\n", msg->type); + return -EINVAL; + } + + if (IsTaskAlive(*dstTid) == FALSE) { + return -EINVAL; + } + return LOS_OK; +} + +LITE_OS_SEC_TEXT STATIC UINT32 LiteIpcWrite(IpcContent *content) +{ + UINT32 ret, intSave; + UINT32 dstTid; + + IpcMsg *msg = content->outMsg; + + ret = CheckPara(content, &dstTid); + if (ret != LOS_OK) { + return ret; + } + + UINT32 bufSz = sizeof(IpcListNode) + msg->dataSz + msg->spObjNum * sizeof(UINT32); + IpcListNode *buf = (IpcListNode *)LiteIpcNodeAlloc(OS_TCB_FROM_TID(dstTid)->processID, bufSz); + if (buf == NULL) { + PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__); + return -ENOMEM; + } + ret = CopyDataFromUser(buf, bufSz, (const IpcMsg *)msg); + if (ret != LOS_OK) { + PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__); + goto ERROR_COPY; + } + ret = HandleSpecialObjects(dstTid, buf, FALSE); + if (ret != LOS_OK) { + PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__); + goto ERROR_COPY; + } + /* add data to list and wake up dest task */ + SCHEDULER_LOCK(intSave); + LosTaskCB *tcb = OS_TCB_FROM_TID(dstTid); + LOS_ListTailInsert(&(tcb->msgListHead), &(buf->listNode)); +#if (LOSCFG_KERNEL_TRACE == YES) + IpcTrace(&buf->msg, WRITE, tcb->ipcStatus, buf->msg.type); +#endif + if (tcb->ipcStatus & IPC_THREAD_STATUS_PEND) { + tcb->ipcStatus &= ~IPC_THREAD_STATUS_PEND; + OsTaskWake(tcb); + SCHEDULER_UNLOCK(intSave); + LOS_MpSchedule(OS_MP_CPU_ALL); + LOS_Schedule(); + } else { + SCHEDULER_UNLOCK(intSave); + } + return LOS_OK; +ERROR_COPY: + LiteIpcNodeFree(OS_TCB_FROM_TID(dstTid)->processID, buf); + return ret; +} + +LITE_OS_SEC_TEXT STATIC UINT32 CheckRecievedMsg(IpcListNode *node, IpcContent *content, LosTaskCB *tcb) +{ + UINT32 ret = LOS_OK; + if (node == NULL) { + return -EINVAL; + } + switch (node->msg.type) { + case MT_REQUEST: + if ((content->flag & SEND) == SEND) { + PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__); + ret = -EINVAL; + } + break; + case MT_FAILED_REPLY: + ret = -ENOENT; + /* fall-through */ + case MT_REPLY: + if ((content->flag & SEND) != SEND) { + PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__); + ret = -EINVAL; + } +#if (USE_TIMESTAMP == YES) + if (node->msg.timestamp != content->outMsg->timestamp) { + PRINT_ERR("Recieve a unmatch reply, drop it\n"); + ret = -EINVAL; + } +#else + if ((node->msg.code != content->outMsg->code) || + (node->msg.target.token != content->outMsg->target.token)) { + PRINT_ERR("Recieve a unmatch reply, drop it\n"); + ret = -EINVAL; + } +#endif + break; + case MT_DEATH_NOTIFY: + break; + default: + PRINT_ERR("Unknow msg type:%d\n", node->msg.type); + ret = -EINVAL; + } + if (ret != LOS_OK) { +#if (LOSCFG_KERNEL_TRACE == YES) + IpcTrace(&node->msg, READ_DROP, tcb->ipcStatus, node->msg.type); +#endif + (VOID)HandleSpecialObjects(LOS_CurTaskIDGet(), node, TRUE); + (VOID)LiteIpcNodeFree(LOS_GetCurrProcessID(), (VOID *)node); + } else { +#if (LOSCFG_KERNEL_TRACE == YES) + IpcTrace(&node->msg, READ, tcb->ipcStatus, node->msg.type); +#endif + } + return ret; +} + +LITE_OS_SEC_TEXT STATIC UINT32 LiteIpcRead(IpcContent *content) +{ + UINT32 intSave, ret; + UINT32 selfTid = LOS_CurTaskIDGet(); + LOS_DL_LIST *listHead = NULL; + LOS_DL_LIST *listNode = NULL; + IpcListNode *node = NULL; + UINT32 syncFlag = (content->flag & SEND) && (content->flag & RECV); + UINT32 timeout = syncFlag ? LOS_MS2Tick(LITEIPC_TIMEOUT_MS) : LOS_WAIT_FOREVER; + + LosTaskCB *tcb = OS_TCB_FROM_TID(selfTid); + listHead = &(tcb->msgListHead); + do { + SCHEDULER_LOCK(intSave); + if (LOS_ListEmpty(listHead)) { +#if (LOSCFG_KERNEL_TRACE == YES) + IpcTrace(NULL, TRY_READ, tcb->ipcStatus, syncFlag ? MT_REPLY : MT_REQUEST); +#endif + tcb->ipcStatus |= IPC_THREAD_STATUS_PEND; + ret = OsTaskWait(&g_ipcPendlist, timeout, TRUE); + if (ret == LOS_ERRNO_TSK_TIMEOUT) { +#if (LOSCFG_KERNEL_TRACE == YES) + IpcTrace(NULL, READ_TIMEOUT, tcb->ipcStatus, syncFlag ? MT_REPLY : MT_REQUEST); +#endif + SCHEDULER_UNLOCK(intSave); + return -ETIME; + } + + SCHEDULER_UNLOCK(intSave); + } else { + listNode = LOS_DL_LIST_FIRST(listHead); + LOS_ListDelete(listNode); + node = LOS_DL_LIST_ENTRY(listNode, IpcListNode, listNode); + SCHEDULER_UNLOCK(intSave); + ret = CheckRecievedMsg(node, content, tcb); + if (ret == LOS_OK) { + break; + } + if (ret == -ENOENT) { /* It means that we've recieved a failed reply */ + return ret; + } + } + } while (1); + node->msg.data = (VOID *)GetIpcUserAddr(LOS_GetCurrProcessID(), (INTPTR)(node->msg.data)); + node->msg.offsets = (VOID *)GetIpcUserAddr(LOS_GetCurrProcessID(), (INTPTR)(node->msg.offsets)); + content->inMsg = (VOID *)GetIpcUserAddr(LOS_GetCurrProcessID(), (INTPTR)(&(node->msg))); + EnableIpcNodeFreeByUser(LOS_GetCurrProcessID(), (VOID *)node); + return LOS_OK; +} + +LITE_OS_SEC_TEXT STATIC UINT32 LiteIpcMsgHandle(IpcContent *con) +{ + UINT32 ret = LOS_OK; + IpcContent localContent; + IpcContent *content = &localContent; + IpcMsg localMsg; + IpcMsg *msg = &localMsg; + IpcListNode *nodeNeedFree = NULL; + + if (copy_from_user((void *)content, (const void *)con, sizeof(IpcContent)) != LOS_OK) { + PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__); + return -EINVAL; + } + + if ((content->flag & BUFF_FREE) == BUFF_FREE) { + ret = CheckUsedBuffer(content->buffToFree, &nodeNeedFree); + if (ret != LOS_OK) { + PRINT_ERR("CheckUsedBuffer failed:%d\n", ret); + return ret; + } + } + + if ((content->flag & SEND) == SEND) { + if (content->outMsg == NULL) { + PRINT_ERR("content->outmsg is null\n"); + ret = -EINVAL; + goto BUFFER_FREE; + } + if (copy_from_user((void *)msg, (const void *)content->outMsg, sizeof(IpcMsg)) != LOS_OK) { + PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__); + ret = -EINVAL; + goto BUFFER_FREE; + } + content->outMsg = msg; + if ((content->outMsg->type < 0) || (content->outMsg->type >= MT_DEATH_NOTIFY)) { + PRINT_ERR("LiteIpc unknow msg type:%d\n", content->outMsg->type); + ret = -EINVAL; + goto BUFFER_FREE; + } + ret = LiteIpcWrite(content); + if (ret != LOS_OK) { + PRINT_ERR("LiteIpcWrite failed\n"); + goto BUFFER_FREE; + } + } +BUFFER_FREE: + if (nodeNeedFree != NULL) { + UINT32 freeRet = LiteIpcNodeFree(LOS_GetCurrProcessID(), nodeNeedFree); + ret = (freeRet == LOS_OK) ? ret : freeRet; + } + if (ret != LOS_OK) { + return ret; + } + + if ((content->flag & RECV) == RECV) { + ret = LiteIpcRead(content); + if (ret != LOS_OK) { + PRINT_ERR("LiteIpcRead failed\n"); + return ret; + } + UINT32 offset = LOS_OFF_SET_OF(IpcContent, inMsg); + ret = copy_to_user((char*)con + offset, (char*)content + offset, sizeof(IpcMsg *)); + if (ret != LOS_OK) { + PRINT_ERR("%s, %d, %d\n", __FUNCTION__, __LINE__, ret); + return -EINVAL; + } + } + return ret; +} + +LITE_OS_SEC_TEXT STATIC UINT32 HandleCmsCmd(CmsCmdContent *content) +{ + UINT32 ret = LOS_OK; + CmsCmdContent localContent; + if (content == NULL) { + return -EINVAL; + } + if (IsCmsTask(LOS_CurTaskIDGet()) == FALSE) { + return -EACCES; + } + if (copy_from_user((void *)(&localContent), (const void *)content, sizeof(CmsCmdContent)) != LOS_OK) { + PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__); + return -EINVAL; + } + switch (localContent.cmd) { + case CMS_GEN_HANDLE: + if ((localContent.taskID != 0) && (IsTaskAlive(localContent.taskID) == FALSE)) { + return -EINVAL; + } + ret = GenerateServiceHandle(localContent.taskID, HANDLE_REGISTED, &(localContent.serviceHandle)); + if (ret == LOS_OK) { + ret = copy_to_user((void *)content, (const void *)(&localContent), sizeof(CmsCmdContent)); + } + AddServiceAccess(g_cmsTask.taskID, localContent.serviceHandle); + break; + case CMS_REMOVE_HANDLE: + if (localContent.serviceHandle >= MAX_SERVICE_NUM) { + return -EINVAL; + } + RefreshServiceHandle(localContent.serviceHandle, -1); + break; + case CMS_ADD_ACCESS: + if (IsTaskAlive(localContent.taskID) == FALSE) { + return -EINVAL; + } + return AddServiceAccess(localContent.taskID, localContent.serviceHandle); + default: + PRINT_DEBUG("Unknow cmd cmd:%d\n", localContent.cmd); + return -EINVAL; + } + return ret; +} + +LITE_OS_SEC_TEXT int LiteIpcIoctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + UINT32 ret = LOS_OK; + if (IsPoolMapped() == FALSE) { + PRINT_ERR("Ipc pool not init, need to mmap first!\n"); + return -ENOMEM; + } + switch (cmd) { + case IPC_SET_CMS: + return SetCms(arg); + case IPC_CMS_CMD: + return HandleCmsCmd((CmsCmdContent *)(UINTPTR)arg); + case IPC_SET_IPC_THREAD: + if (IsCmsSet() == FALSE) { + PRINT_ERR("ServiceManager not set!\n"); + return -EINVAL; + } + return SetIpcTask(); + case IPC_SEND_RECV_MSG: + if (arg == 0) { + return -EINVAL; + } + if (IsCmsSet() == FALSE) { + PRINT_ERR("ServiceManager not set!\n"); + return -EINVAL; + } + ret = LiteIpcMsgHandle((IpcContent *)(UINTPTR)arg); + if (ret != LOS_OK) { + return ret; + } + break; + default: + PRINT_ERR("Unknow liteipc ioctl cmd:%d\n", cmd); + return -EINVAL; + } + return ret; +} diff --git a/kernel/extended/liteipc/hm_liteipc.h b/kernel/extended/liteipc/hm_liteipc.h index 0357ab2f2dd0a87e4d83a4168c3cc52d3a0f6fdc..6c35c9ef60ae761363b1fded5999f2264a7a4cca 100644 --- a/kernel/extended/liteipc/hm_liteipc.h +++ b/kernel/extended/liteipc/hm_liteipc.h @@ -1,233 +1,233 @@ -/* - * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. - * Copyright (c) 2020, Huawei Device Co., Ltd. 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 the copyright holder 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. - */ - -#ifndef HM_LITEIPC_H -#define HM_LITEIPC_H - -#include "sys/ioctl.h" -#include "los_config.h" -#include "los_task_pri.h" -#include "los_typedef.h" -#include "los_vm_map.h" - -#ifdef __cplusplus -#if __cplusplus -extern "C" { -#endif /* __cplusplus */ -#endif /* __cplusplus */ - -#define LITEIPC_DRIVER "/dev/lite_ipc" -#define DRIVER_MODE 0666 -#define MAX_SERVICE_NUM LOSCFG_BASE_CORE_TSK_LIMIT -#define USE_TIMESTAMP YES - -typedef enum { - HANDLE_NOT_USED, - HANDLE_REGISTING, - HANDLE_REGISTED -} HandleStatus; - -typedef struct { - HandleStatus status; - UINT32 taskID; - UINTPTR maxMsgSize; -} HandleInfo; - -typedef struct { - VOID *uvaddr; - VOID *kvaddr; - UINT32 poolSize; -} IpcPool; - -typedef struct { - IpcPool pool; - UINT32 ipcTaskID; - UINT32 access[LOSCFG_BASE_CORE_TSK_LIMIT]; -} ProcIpcInfo; - -typedef enum { - OBJ_FD, - OBJ_PTR, - OBJ_SVC -} ObjType; - -typedef struct { - UINT32 buffSz; - VOID *buff; -} BuffPtr; - -typedef struct { - UINT32 handle; - UINT32 token; - UINT32 cookie; -} SvcIdentity; - -typedef union { - UINT32 fd; - BuffPtr ptr; - SvcIdentity svc; -} ObjContent; - -typedef struct { - ObjType type; - ObjContent content; -} SpecialObj; - -typedef enum { - MT_REQUEST, - MT_REPLY, - MT_FAILED_REPLY, - MT_DEATH_NOTIFY, - MT_NUM -} MsgType; - -/* lite ipc ioctl */ -#define IPC_IOC_MAGIC 'i' -#define IPC_SET_CMS _IO(IPC_IOC_MAGIC, 1) -#define IPC_CMS_CMD _IOWR(IPC_IOC_MAGIC, 2, CmsCmdContent) -#define IPC_SET_IPC_THREAD _IO(IPC_IOC_MAGIC, 3) -#define IPC_SEND_RECV_MSG _IOWR(IPC_IOC_MAGIC, 4, IpcContent) - -typedef enum { - CMS_GEN_HANDLE, - CMS_REMOVE_HANDLE, - CMS_ADD_ACCESS -} CmsCmd; - -typedef struct { - CmsCmd cmd; - UINT32 taskID; - UINT32 serviceHandle; -} CmsCmdContent; - -typedef enum { - LITEIPC_FLAG_DEFAULT = 0, // send and reply - LITEIPC_FLAG_ONEWAY, // send message only -} IpcFlag; - -typedef struct { - MsgType type; /**< cmd type, decide the data structure below*/ - SvcIdentity target; /**< serviceHandle or targetTaskId, depending on type */ - UINT32 code; /**< service function code */ - UINT32 flag; -#if (USE_TIMESTAMP == YES) - UINT64 timestamp; -#endif - UINT32 dataSz; /**< size of data */ - VOID *data; - UINT32 spObjNum; - VOID *offsets; - UINT32 processID; /**< filled by kernel, processId of sender/reciever */ - UINT32 taskID; /**< filled by kernel, taskId of sender/reciever */ -#ifdef LOSCFG_SECURITY_CAPABILITY - UINT32 userID; - UINT32 gid; -#endif -} IpcMsg; - -typedef struct { - IpcMsg msg; - LOS_DL_LIST listNode; -} IpcListNode; - -#define SEND (1 << 0) -#define RECV (1 << 1) -#define BUFF_FREE (1 << 2) - -typedef struct { - UINT32 flag; /**< size of writeData */ - IpcMsg *outMsg; /**< data to send to target */ - IpcMsg *inMsg; /**< data reply by target */ - VOID *buffToFree; -} IpcContent; - -#define IPC_THREAD_STATUS_INVAL 0x0001U -#define IPC_THREAD_STATUS_START 0x0002U -#define IPC_THREAD_STATUS_PEND 0x0004U -#define IPC_THREAD_STATUS_STOP 0x0008U - -#if (LOSCFG_KERNEL_TRACE == YES) -#define LOS_TRACE_IPC 3 //IPC 对应..\kernel\include\los_trace.h TraceType 理解 - -typedef enum { - WRITE, - WRITE_DROP, - TRY_READ, - READ, - READ_DROP, - READ_TIMEOUT, - OPERATION_NUM -} IpcOpertion; - -typedef struct { - UINT32 srcTid : 8; - UINT32 srcPid : 8; - UINT32 dstTid : 8; - UINT32 dstPid : 8; -} IdArg; - -typedef struct { - UINT32 msgType : 8; - UINT32 code : 8; - UINT32 operation : 8; - UINT32 ipcStatus : 8; -} MsgArg; - -typedef struct { - UINT32 idInfo; - UINT32 msgInfo; - UINT64 timestamp; -} IpcTraceFrame; -#endif - - -/* init liteipc driver */ -extern UINT32 LiteIpcInit(VOID); - -/* init process liteipc memory pool */ -extern UINT32 LiteIpcPoolInit(ProcIpcInfo *ipcInfo); - -/* reinit process liteipc memory pool, using in fork situation */ -extern UINT32 LiteIpcPoolReInit(ProcIpcInfo *childIpcInfo, const ProcIpcInfo *parentIpcInfo); - -/* delete process liteipc memory pool */ -extern VOID LiteIpcPoolDelete(ProcIpcInfo *ipcInfo); - -/* remove service handle and send death notify */ -extern VOID LiteIpcRemoveServiceHandle(LosTaskCB *taskCB); - -#ifdef __cplusplus -#if __cplusplus -} -#endif /* __cplusplus */ -#endif /* __cplusplus */ - -#endif +/* + * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020, Huawei Device Co., Ltd. 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 the copyright holder 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. + */ + +#ifndef HM_LITEIPC_H +#define HM_LITEIPC_H + +#include "sys/ioctl.h" +#include "los_config.h" +#include "los_task_pri.h" +#include "los_typedef.h" +#include "los_vm_map.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define LITEIPC_DRIVER "/dev/lite_ipc" +#define DRIVER_MODE 0666 +#define MAX_SERVICE_NUM LOSCFG_BASE_CORE_TSK_LIMIT +#define USE_TIMESTAMP YES + +typedef enum { + HANDLE_NOT_USED, + HANDLE_REGISTING, + HANDLE_REGISTED +} HandleStatus; + +typedef struct {//句柄信息 + HandleStatus status; //状态 + UINT32 taskID; //任务ID,以任务当句柄 + UINTPTR maxMsgSize;//最大消息大小 +} HandleInfo; + +typedef struct { + VOID *uvaddr; + VOID *kvaddr; + UINT32 poolSize; +} IpcPool; + +typedef struct { + IpcPool pool; + UINT32 ipcTaskID; + UINT32 access[LOSCFG_BASE_CORE_TSK_LIMIT]; +} ProcIpcInfo; + +typedef enum { + OBJ_FD, + OBJ_PTR, + OBJ_SVC +} ObjType; + +typedef struct { + UINT32 buffSz; + VOID *buff; +} BuffPtr; + +typedef struct { + UINT32 handle; + UINT32 token; + UINT32 cookie; +} SvcIdentity; + +typedef union { + UINT32 fd; + BuffPtr ptr; + SvcIdentity svc; +} ObjContent; + +typedef struct { + ObjType type; + ObjContent content; +} SpecialObj; + +typedef enum { + MT_REQUEST, + MT_REPLY, + MT_FAILED_REPLY, + MT_DEATH_NOTIFY, + MT_NUM +} MsgType; + +/* lite ipc ioctl */ +#define IPC_IOC_MAGIC 'i' +#define IPC_SET_CMS _IO(IPC_IOC_MAGIC, 1) +#define IPC_CMS_CMD _IOWR(IPC_IOC_MAGIC, 2, CmsCmdContent) +#define IPC_SET_IPC_THREAD _IO(IPC_IOC_MAGIC, 3) +#define IPC_SEND_RECV_MSG _IOWR(IPC_IOC_MAGIC, 4, IpcContent) + +typedef enum { + CMS_GEN_HANDLE, + CMS_REMOVE_HANDLE, + CMS_ADD_ACCESS +} CmsCmd; + +typedef struct { + CmsCmd cmd; + UINT32 taskID; + UINT32 serviceHandle; +} CmsCmdContent; + +typedef enum { + LITEIPC_FLAG_DEFAULT = 0, // send and reply + LITEIPC_FLAG_ONEWAY, // send message only +} IpcFlag; + +typedef struct { + MsgType type; /**< cmd type, decide the data structure below*/ + SvcIdentity target; /**< serviceHandle or targetTaskId, depending on type */ + UINT32 code; /**< service function code */ + UINT32 flag; +#if (USE_TIMESTAMP == YES) + UINT64 timestamp; +#endif + UINT32 dataSz; /**< size of data */ + VOID *data; + UINT32 spObjNum; + VOID *offsets; + UINT32 processID; /**< filled by kernel, processId of sender/reciever */ + UINT32 taskID; /**< filled by kernel, taskId of sender/reciever */ +#ifdef LOSCFG_SECURITY_CAPABILITY + UINT32 userID; + UINT32 gid; +#endif +} IpcMsg; + +typedef struct { + IpcMsg msg; + LOS_DL_LIST listNode; +} IpcListNode; + +#define SEND (1 << 0) +#define RECV (1 << 1) +#define BUFF_FREE (1 << 2) + +typedef struct { + UINT32 flag; /**< size of writeData */ + IpcMsg *outMsg; /**< data to send to target */ + IpcMsg *inMsg; /**< data reply by target */ + VOID *buffToFree; +} IpcContent; + +#define IPC_THREAD_STATUS_INVAL 0x0001U +#define IPC_THREAD_STATUS_START 0x0002U +#define IPC_THREAD_STATUS_PEND 0x0004U +#define IPC_THREAD_STATUS_STOP 0x0008U + +#if (LOSCFG_KERNEL_TRACE == YES) +#define LOS_TRACE_IPC 3 //IPC 对应..\kernel\include\los_trace.h TraceType 理解 + +typedef enum { + WRITE, + WRITE_DROP, + TRY_READ, + READ, + READ_DROP, + READ_TIMEOUT, + OPERATION_NUM +} IpcOpertion; + +typedef struct { + UINT32 srcTid : 8; + UINT32 srcPid : 8; + UINT32 dstTid : 8; + UINT32 dstPid : 8; +} IdArg; + +typedef struct { + UINT32 msgType : 8; + UINT32 code : 8; + UINT32 operation : 8; + UINT32 ipcStatus : 8; +} MsgArg; + +typedef struct { + UINT32 idInfo; + UINT32 msgInfo; + UINT64 timestamp; +} IpcTraceFrame; +#endif + + +/* init liteipc driver */ +extern UINT32 LiteIpcInit(VOID); + +/* init process liteipc memory pool */ +extern UINT32 LiteIpcPoolInit(ProcIpcInfo *ipcInfo); + +/* reinit process liteipc memory pool, using in fork situation */ +extern UINT32 LiteIpcPoolReInit(ProcIpcInfo *childIpcInfo, const ProcIpcInfo *parentIpcInfo); + +/* delete process liteipc memory pool */ +extern VOID LiteIpcPoolDelete(ProcIpcInfo *ipcInfo); + +/* remove service handle and send death notify */ +extern VOID LiteIpcRemoveServiceHandle(LosTaskCB *taskCB); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif diff --git a/syscall/fs_syscall.c b/syscall/fs_syscall.c index 408be68eb7567496f9e3cc66a56e2d274d2014c1..7a232f67d951d0db39ae810c5e8d840e172c222c 100644 --- a/syscall/fs_syscall.c +++ b/syscall/fs_syscall.c @@ -176,7 +176,7 @@ static int UserPoll(struct pollfd *fds, nfds_t nfds, int timeout) free(pollFds); return ret; } - +//复杂一个文件描述符 static int FcntlDupFd(int fd, void *arg, int (*fcntl)(int, int, ...)) { int ret; @@ -776,7 +776,25 @@ int SysIoctl(int fd, int req, void *arg) } return ret; } -//文件控制 +/******************************************************** +用来修改已经打开文件的属性的函数包含5个功能: +1.复制一个已有文件描述符,功能和dup和dup2相同,对应的cmd:F_DUPFD、F_DUPFD_CLOEXEC。 + 当使用这两个cmd时,需要传入第三个参数,fcntl返回复制后的文件描述符,此返回值是之前未被占用的描述符, + 并且必须一个大于等于第三个参数值。 + F_DUPFD命令要求返回的文件描述符会清除对应的FD_CLOEXEC + F_DUPFD_CLOEXEC要求设置新描述符的FD_CLOEXEC标志。 + +2.获取、设置文件描述符标志,对应的cmd:F_GETFD、F_SETFD。 + 用于设置FD_CLOEXEC标志,此标志的含义是:当进程执行exec系统调用后此文件描述符会被自动关闭。 + +3.获取、设置文件访问状态标志,对应的cmd:F_GETFL、F_SETFL。 + 获取当前打开文件的访问标志,设置对应的访问标志,一般常用来设置做非阻塞读写操作。 + +4.获取、设置记录锁功能,对应的cmd:F_GETLK、F_SETLK、F_SETLKW。 + +5.获取、设置异步I/O所有权,对应的cmd:F_GETOWN、F_SETOWN。 + 获取和设置用来接收SIGIO/SIGURG信号的进程id或者进程组id。返回对应的进程id或者进程组id取负值。 +********************************************************/ int SysFcntl(int fd, int cmd, void *arg) { /* Process fd convert to system global fd */ @@ -791,23 +809,38 @@ int SysFcntl(int fd, int cmd, void *arg) } return ret; } -//创建管道 +/******************************************************** +管道是一种最基本的IPC机制,作用于有血缘关系的进程之间,完成数据传递。 +调用pipe系统函数即可创建一个管道。有如下特质: + +1. 其本质是一个伪文件(实为内核缓冲区) +2. 由两个文件描述符引用,一个表示读端,一个表示写端。 +3. 规定数据从管道的写端流入管道,从读端流出。 + +管道的原理: 管道实为内核使用环形队列机制,借助内核缓冲区(4k)实现。 +管道的局限性: + ① 数据自己读不能自己写。 + ② 数据一旦被读走,便不在管道中存在,不可反复读取。 + ③ 由于管道采用半双工通信方式。因此,数据只能在一个方向上流动。 + ④ 只能在有公共祖先的进程间使用管道。 +常见的通信方式有,单工通信、半双工通信、全双工通信。 +********************************************************/ int SysPipe(int pipefd[2]) /* 2 : pipe fds for read and write */ { int ret; int pipeFdIntr[2] = {0}; /* 2 : pipe fds for read and write */ - int procFd0 = AllocProcessFd(); + int procFd0 = AllocProcessFd();//读端管道,像 stdin对应标准输入 if (procFd0 < 0) { return -EMFILE; } - int procFd1 = AllocProcessFd(); + int procFd1 = AllocProcessFd();//写端管道,像 stdout对应标准输出 if (procFd1 < 0) { FreeProcessFd(procFd0); return -EMFILE; } - ret = pipe(pipeFdIntr); + ret = pipe(pipeFdIntr);//创建管道 if (ret < 0) { FreeProcessFd(procFd0); FreeProcessFd(procFd1); @@ -816,13 +849,13 @@ int SysPipe(int pipefd[2]) /* 2 : pipe fds for read and write */ int sysPipeFd0 = pipeFdIntr[0]; int sysPipeFd1 = pipeFdIntr[1]; - AssociateSystemFd(procFd0, sysPipeFd0); + AssociateSystemFd(procFd0, sysPipeFd0);//进程FD和系统FD绑定 AssociateSystemFd(procFd1, sysPipeFd1); pipeFdIntr[0] = procFd0; pipeFdIntr[1] = procFd1; - ret = LOS_ArchCopyToUser(pipefd, pipeFdIntr, sizeof(pipeFdIntr)); + ret = LOS_ArchCopyToUser(pipefd, pipeFdIntr, sizeof(pipeFdIntr));//参数都走两个进程FD if (ret != 0) { FreeProcessFd(procFd0); FreeProcessFd(procFd1); @@ -832,15 +865,17 @@ int SysPipe(int pipefd[2]) /* 2 : pipe fds for read and write */ } return ret; } -//按指定条件复制文件描述字 +/******************************************************** +/复制文件描述符 +********************************************************/ int SysDup2(int fd1, int fd2) { int ret; int sysfd1 = GetAssociatedSystemFd(fd1); int sysfd2 = GetAssociatedSystemFd(fd2); - + //检查参数是否有效,注意:socket fd不支持dup2 /* Check if the param is valid, note that: socket fd is not support dup2 */ - if ((sysfd1 < 0) || (sysfd1 >= CONFIG_NFILE_DESCRIPTORS) || (CheckProcessFd(fd2) != OK)) { + if ((sysfd1 < 0) || (sysfd1 >= CONFIG_NFILE_DESCRIPTORS) || (CheckProcessFd(fd2) != OK)) {//socket的fd必大于CONFIG_NFILE_DESCRIPTORS return -EBADF; } diff --git a/syscall/ipc_syscall.c b/syscall/ipc_syscall.c index ee3896fb1b2f1cfa7cf75a0a1bd9a6080cb06908..0537752a26be28421f18896516ec114927a9326e 100644 --- a/syscall/ipc_syscall.c +++ b/syscall/ipc_syscall.c @@ -38,7 +38,7 @@ #include "los_signal.h" #include "los_strncpy_from_user.h" /******************************************************** -本文说明:系统调用|IPC +本文说明:包含消息队列和信号两部分内容,是实现IPC的其中两种方式 IPC(Inter-Process Communication,进程间通信) 每个进程各自有不同的用户地址空间,进程之间地址保护,相互隔离,任何一个进程的信息在另一个进程中都看不到, 所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程A把数据从用户空间拷到内核缓冲区, @@ -84,7 +84,12 @@ int SysMqClose(mqd_t personal) } return ret; } - +/****************************************************** +封装posix的标准接口,获取和设置消息队列的属性 +new:来判断是否是获取还是设置功能 + new==null 获取 + 否则为设置 +******************************************************/ int SysMqGetSetAttr(mqd_t mqd, const struct mq_attr *new, struct mq_attr *old) { int ret; @@ -108,7 +113,14 @@ int SysMqGetSetAttr(mqd_t mqd, const struct mq_attr *new, struct mq_attr *old) } return ret; } - +/****************************************************** +从内核中删除名为mqName的消息队列 +如果该函数被调用了,但是仍然有进程已经打开了这个消息队列,那么这个消息队列 +的销毁会被推迟到所有的引用都被关闭时执行.并且函数 mq_unlink() 不需要阻塞 +到所有的引用都被关闭为止,它会立即返回.函数 mq_unlink()调用成功后, 如果在 +随后调用 mq_open() 时重用这个消息队列名字,效果就像这个名字的消息队列不存在, +如果没有设置O_CREAT标志,函数mq_open() 会返回失败,否则会创建一个新的消息队列. +******************************************************/ int SysMqUnlink(const char *mqName) { int ret; @@ -126,7 +138,9 @@ int SysMqUnlink(const char *mqName) } return ret; } - +/****************************************************** +定时时间发送消息,任务将被阻塞,等待被唤醒写入消息 +******************************************************/ int SysMqTimedSend(mqd_t personal, const char *msg, size_t msgLen, unsigned int msgPrio, const struct timespec *absTimeout) { @@ -152,14 +166,16 @@ int SysMqTimedSend(mqd_t personal, const char *msg, size_t msgLen, unsigned int free(msgIntr); return -EFAULT; } - ret = mq_timedsend(personal, msgIntr, msgLen, msgPrio, absTimeout ? &timeout : NULL); + ret = mq_timedsend(personal, msgIntr, msgLen, msgPrio, absTimeout ? &timeout : NULL);//posix 接口的实现 free(msgIntr); if (ret < 0) { return -get_errno(); } return ret; } - +/****************************************************** +定时接收消息,任务将被阻塞,等待被唤醒读取 +******************************************************/ ssize_t SysMqTimedReceive(mqd_t personal, char *msg, size_t msgLen, unsigned int *msgPrio, const struct timespec *absTimeout) { @@ -181,7 +197,7 @@ ssize_t SysMqTimedReceive(mqd_t personal, char *msg, size_t msgLen, unsigned int if (msgIntr == NULL) { return -ENOMEM; } - receiveLen = mq_timedreceive(personal, msgIntr, msgLen, &kMsgPrio, absTimeout ? &timeout : NULL); + receiveLen = mq_timedreceive(personal, msgIntr, msgLen, &kMsgPrio, absTimeout ? &timeout : NULL);//posix 接口的实现 if (receiveLen < 0) { free(msgIntr); return -get_errno(); diff --git a/zzz/git/push.sh b/zzz/git/push.sh index 143a90abb99c6180d0c5d86aebec64f9cfe62bb6..73bb31ea6f67ffefeb8c4248abc51bf1b748cd30 100644 --- a/zzz/git/push.sh +++ b/zzz/git/push.sh @@ -1,5 +1,5 @@ git add -A -git commit -m '完善虚拟内存模块注解 +git commit -m '字符图说明posix消息队列内在运行逻辑 搜索 @note_pic 可以查看全部字符图 搜索 @note_why 是注者尚未看明白的地方,如果您看明白了,请告诉注者完善 搜索 @note_thinking 是注者的思考和吐槽的地方