diff --git a/compat/posix/include/mqueue.h b/compat/posix/include/mqueue.h index eb58bd06..123d5540 100644 --- a/compat/posix/include/mqueue.h +++ b/compat/posix/include/mqueue.h @@ -81,6 +81,11 @@ typedef union send_receive_t { short data; } mode_s; +struct mqnotify { + pid_t pid; + struct sigevent notify; +}; + /* TYPE DEFINITIONS */ struct mqarray { UINT32 mq_id : 31; @@ -91,6 +96,7 @@ struct mqarray { uid_t euid; /* euid of mqueue */ gid_t egid; /* egid of mqueue */ fd_set mq_fdset; /* mqueue sysFd bit map */ + struct mqnotify mq_notify; LosQueueCB *mqcb; struct mqpersonal *mq_personal; }; @@ -418,6 +424,7 @@ extern ssize_t mq_timedreceive(mqd_t personal, char *msg, size_t msgLen, unsigned int *msgPrio, const struct timespec *absTimeout); extern void mqueue_refer(int sysFd); +extern int OsMqNotify(mqd_t personal, const struct sigevent *sigev); #ifdef __cplusplus #if __cplusplus diff --git a/compat/posix/src/mqueue.c b/compat/posix/src/mqueue.c index 9916b641..cfc9de38 100644 --- a/compat/posix/src/mqueue.c +++ b/compat/posix/src/mqueue.c @@ -120,6 +120,7 @@ STATIC INT32 DoMqueueDelete(struct mqarray *mqueueCB) mqueueCB->mode_data.data = 0; mqueueCB->euid = -1; mqueueCB->egid = -1; + mqueueCB->mq_notify.pid = 0; ret = LOS_QueueDelete(mqueueCB->mq_id); switch (ret) { @@ -204,6 +205,7 @@ STATIC struct mqpersonal *DoMqueueCreate(const struct mq_attr *attr, const CHAR mqueueCB->mq_personal->mq_flags = (INT32)((UINT32)openFlag | ((UINT32)attr->mq_flags & (UINT32)FNONBLOCK)); mqueueCB->mq_personal->mq_mode = mode; mqueueCB->mq_personal->mq_refcount = 0; + mqueueCB->mq_notify.pid = 0; return mqueueCB->mq_personal; ERROUT: @@ -717,6 +719,35 @@ STATIC INLINE BOOL MqParamCheck(mqd_t personal, const char *msg, size_t msgLen) return TRUE; } +/* + * Send realtime a signal to process which registered itself + * successfully by mq_notify. + */ +static void MqSendNotify(struct mqarray *mqueueCB) +{ + struct mqnotify *mqnotify = &mqueueCB->mq_notify; + + if ((mqnotify->pid) && (mqueueCB->mqcb->readWriteableCnt[OS_QUEUE_READ] == 0)) { + siginfo_t info; + + switch (mqnotify->notify.sigev_notify) { + case SIGEV_SIGNAL: + /* sends signal */ + /* Create the siginfo structure */ + info.si_signo = mqnotify->notify.sigev_signo; + info.si_code = SI_MESGQ; + info.si_value = mqnotify->notify.sigev_value; + OsDispatch(mqnotify->pid, &info, OS_USER_KILL_PERMISSION); + break; + case SIGEV_NONE: + default: + break; + } + /* after notification unregisters process */ + mqnotify->pid = 0; + } +} + #define OS_MQ_GOTO_ERROUT_UNLOCK_IF(expr, errcode) \ if (expr) { \ errno = errcode; \ @@ -754,6 +785,10 @@ int mq_timedsend(mqd_t personal, const char *msg, size_t msgLen, unsigned int ms mqueueID = mqueueCB->mq_id; (VOID)pthread_mutex_unlock(&g_mqueueMutex); + if (LOS_ListEmpty(&mqueueCB->mqcb->readWriteList[OS_QUEUE_READ])) { + MqSendNotify(mqueueCB); + } + err = LOS_QueueWriteCopy(mqueueID, (VOID *)msg, (UINT32)msgLen, (UINT32)absTicks); if (map_errno(err) != ENOERR) { goto ERROUT; @@ -832,4 +867,82 @@ ssize_t mq_receive(mqd_t personal, char *msg_ptr, size_t msg_len, unsigned int * return mq_timedreceive(personal, msg_ptr, msg_len, msg_prio, NULL); } +STATIC INLINE BOOL MqNotifyParamCheck(mqd_t personal, const struct sigevent *sigev) +{ + if (personal < 0) { + errno = EBADF; + goto ERROUT; + } + + if (sigev != NULL) { + if (sigev->sigev_notify != SIGEV_NONE && sigev->sigev_notify != SIGEV_SIGNAL) { + errno = EINVAL; + goto ERROUT; + } + if (sigev->sigev_notify == SIGEV_SIGNAL && !GOOD_SIGNO(sigev->sigev_signo)) { + errno = EINVAL; + goto ERROUT; + } + } + + return TRUE; +ERROUT: + return FALSE; +} + +int OsMqNotify(mqd_t personal, const struct sigevent *sigev) +{ + struct mqarray *mqueueCB = NULL; + struct mqnotify *mqnotify = NULL; + struct mqpersonal *privateMqPersonal = NULL; + + if (!MqNotifyParamCheck(personal, sigev)) { + goto ERROUT; + } + + (VOID)pthread_mutex_lock(&g_mqueueMutex); + privateMqPersonal = MqGetPrivDataBuff(personal); + if (privateMqPersonal == NULL) { + goto OUT_UNLOCK; + } + + if (privateMqPersonal->mq_status != MQ_USE_MAGIC) { + errno = EBADF; + goto OUT_UNLOCK; + } + + mqueueCB = privateMqPersonal->mq_posixdes; + mqnotify = &mqueueCB->mq_notify; + + if (sigev == NULL) { + if (mqnotify->pid == LOS_GetCurrProcessID()) { + mqnotify->pid = 0; + } + } else if (mqnotify->pid != 0) { + errno = EBUSY; + goto OUT_UNLOCK; + } else { + switch (sigev->sigev_notify) { + case SIGEV_NONE: + mqnotify->notify.sigev_notify = SIGEV_NONE; + break; + case SIGEV_SIGNAL: + mqnotify->notify.sigev_signo = sigev->sigev_signo; + mqnotify->notify.sigev_value = sigev->sigev_value; + mqnotify->notify.sigev_notify = SIGEV_SIGNAL; + break; + default: + break; + } + + mqnotify->pid = LOS_GetCurrProcessID(); + } + + (VOID)pthread_mutex_unlock(&g_mqueueMutex); + return 0; +OUT_UNLOCK: + (VOID)pthread_mutex_unlock(&g_mqueueMutex); +ERROUT: + return -1; +} #endif diff --git a/syscall/ipc_syscall.c b/syscall/ipc_syscall.c index 2ebf7457..f0b3cfbd 100644 --- a/syscall/ipc_syscall.c +++ b/syscall/ipc_syscall.c @@ -87,6 +87,18 @@ int SysMqClose(mqd_t personal) return ret; } +int SysMqNotify(mqd_t personal, const struct sigevent *sigev) +{ + int ret; + + MQUEUE_FD_U2K(personal); + ret = OsMqNotify(personal, sigev); + if (ret < 0) { + return -get_errno(); + } + return ret; +} + int SysMqGetSetAttr(mqd_t mqd, const struct mq_attr *new, struct mq_attr *old) { int ret; diff --git a/syscall/los_syscall.h b/syscall/los_syscall.h index f7334670..67df685e 100644 --- a/syscall/los_syscall.h +++ b/syscall/los_syscall.h @@ -125,6 +125,7 @@ extern int SysMqTimedSend(mqd_t personal, const char *msg, size_t msgLen, unsign const struct timespec *absTimeout); extern ssize_t SysMqTimedReceive(mqd_t personal, char *msg, size_t msgLen, unsigned int *msgPrio, const struct timespec *absTimeout); +extern int SysMqNotify(mqd_t personal, const struct sigevent *sigev); #endif extern int SysSigAction(int sig, const sigaction_t *restrict sa, sigaction_t *restrict old, size_t sigsetsize); diff --git a/syscall/syscall_lookup.h b/syscall/syscall_lookup.h index 44190732..4b714a32 100644 --- a/syscall/syscall_lookup.h +++ b/syscall/syscall_lookup.h @@ -216,6 +216,7 @@ SYSCALL_HAND_DEF(__NR_mq_open, SysMqOpen, mqd_t, ARG_NUM_4) SYSCALL_HAND_DEF(__NR_mq_unlink, SysMqUnlink, int, ARG_NUM_1) SYSCALL_HAND_DEF(__NR_mq_timedsend, SysMqTimedSend, int, ARG_NUM_5) SYSCALL_HAND_DEF(__NR_mq_timedreceive, SysMqTimedReceive, ssize_t, ARG_NUM_5) +SYSCALL_HAND_DEF(__NR_mq_notify, SysMqNotify, int, ARG_NUM_2) SYSCALL_HAND_DEF(__NR_mq_getsetattr, SysMqGetSetAttr, int, ARG_NUM_3) #ifdef LOSCFG_NET_LWIP_SACK diff --git a/testsuites/unittest/posix/mqueue/BUILD.gn b/testsuites/unittest/posix/mqueue/BUILD.gn index 2c570c94..7bc49771 100644 --- a/testsuites/unittest/posix/mqueue/BUILD.gn +++ b/testsuites/unittest/posix/mqueue/BUILD.gn @@ -52,11 +52,6 @@ sources_smoke = [ "smoke/It_posix_queue_028.cpp", "smoke/It_posix_queue_053.cpp", "smoke/It_posix_queue_062.cpp", - "smoke/It_posix_queue_205.cpp", - "smoke/It_posix_queue_206.cpp", - "smoke/It_posix_queue_207.cpp", - "smoke/It_posix_queue_208.cpp", - "smoke/It_posix_queue_209.cpp", ] sources_full = [ @@ -200,6 +195,11 @@ sources_full = [ "full/It_posix_queue_202.cpp", "full/It_posix_queue_203.cpp", "full/It_posix_queue_204.cpp", + "full/It_posix_queue_205.cpp", + "full/It_posix_queue_206.cpp", + "full/It_posix_queue_207.cpp", + "full/It_posix_queue_208.cpp", + "full/It_posix_queue_209.cpp", ] if (LOSCFG_USER_TEST_LEVEL >= TEST_LEVEL_LOW) { diff --git a/testsuites/unittest/posix/mqueue/It_posix_queue.h b/testsuites/unittest/posix/mqueue/It_posix_queue.h index 85d9d308..06471361 100644 --- a/testsuites/unittest/posix/mqueue/It_posix_queue.h +++ b/testsuites/unittest/posix/mqueue/It_posix_queue.h @@ -120,11 +120,6 @@ VOID ItPosixQueue001(VOID); VOID ItPosixQueue003(VOID); VOID ItPosixQueue028(VOID); VOID ItPosixQueue062(VOID); -VOID ItPosixQueue205(VOID); -VOID ItPosixQueue206(VOID); -VOID ItPosixQueue207(VOID); -VOID ItPosixQueue208(VOID); -VOID ItPosixQueue209(VOID); VOID ItPosixQueue053(VOID); VOID ItPosixQueue144(VOID); #endif @@ -274,5 +269,10 @@ VOID ItPosixQueue202(VOID); VOID ItPosixQueue203(VOID); VOID ItPosixQueue204(VOID); +VOID ItPosixQueue205(VOID); +VOID ItPosixQueue206(VOID); +VOID ItPosixQueue207(VOID); +VOID ItPosixQueue208(VOID); +VOID ItPosixQueue209(VOID); #endif #endif diff --git a/testsuites/unittest/posix/mqueue/smoke/It_posix_queue_205.cpp b/testsuites/unittest/posix/mqueue/full/It_posix_queue_205.cpp similarity index 100% rename from testsuites/unittest/posix/mqueue/smoke/It_posix_queue_205.cpp rename to testsuites/unittest/posix/mqueue/full/It_posix_queue_205.cpp diff --git a/testsuites/unittest/posix/mqueue/smoke/It_posix_queue_206.cpp b/testsuites/unittest/posix/mqueue/full/It_posix_queue_206.cpp similarity index 100% rename from testsuites/unittest/posix/mqueue/smoke/It_posix_queue_206.cpp rename to testsuites/unittest/posix/mqueue/full/It_posix_queue_206.cpp diff --git a/testsuites/unittest/posix/mqueue/smoke/It_posix_queue_207.cpp b/testsuites/unittest/posix/mqueue/full/It_posix_queue_207.cpp similarity index 100% rename from testsuites/unittest/posix/mqueue/smoke/It_posix_queue_207.cpp rename to testsuites/unittest/posix/mqueue/full/It_posix_queue_207.cpp diff --git a/testsuites/unittest/posix/mqueue/smoke/It_posix_queue_208.cpp b/testsuites/unittest/posix/mqueue/full/It_posix_queue_208.cpp similarity index 100% rename from testsuites/unittest/posix/mqueue/smoke/It_posix_queue_208.cpp rename to testsuites/unittest/posix/mqueue/full/It_posix_queue_208.cpp diff --git a/testsuites/unittest/posix/mqueue/smoke/It_posix_queue_209.cpp b/testsuites/unittest/posix/mqueue/full/It_posix_queue_209.cpp similarity index 100% rename from testsuites/unittest/posix/mqueue/smoke/It_posix_queue_209.cpp rename to testsuites/unittest/posix/mqueue/full/It_posix_queue_209.cpp diff --git a/testsuites/unittest/posix/mqueue/posix_mqueue_test.cpp b/testsuites/unittest/posix/mqueue/posix_mqueue_test.cpp index b49ce837..81df7893 100644 --- a/testsuites/unittest/posix/mqueue/posix_mqueue_test.cpp +++ b/testsuites/unittest/posix/mqueue/posix_mqueue_test.cpp @@ -1354,6 +1354,63 @@ HWTEST_F(PosixMqueueTest, ItPosixQueue204, TestSize.Level0) { ItPosixQueue204(); } + #endif + +/** + * @tc.name: IT_POSIX_QUEUE_205 + * @tc.desc: function for mq_notify:Set sigev_notify to SIGEV_NONE + * @tc.type: FUNC + * @tc.require: AR000EEMQ9 + */ +HWTEST_F(PosixMqueueTest, ItPosixQueue205, TestSize.Level0) +{ + ItPosixQueue205(); +} + +/** + * @tc.name: IT_POSIX_QUEUE_206 + * @tc.desc: function for mq_notify:The function returns a failure and the error code is verified. + * @tc.type: FUNC + * @tc.require: AR000EEMQ9 + */ +HWTEST_F(PosixMqueueTest, ItPosixQueue206, TestSize.Level0) +{ + ItPosixQueue206(); +} + +/** + * @tc.name: IT_POSIX_QUEUE_207 + * @tc.desc: function for mq_notify:Set sigev_notify to SIGEV_NONE + * @tc.type: FUNC + * @tc.require: AR000EEMQ9 + */ +HWTEST_F(PosixMqueueTest, ItPosixQueue207, TestSize.Level0) +{ + ItPosixQueue207(); +} + +/** + * @tc.name: IT_POSIX_QUEUE_208 + * @tc.desc: function for mq_notify:The message queue is not empty. + * @tc.type: FUNC + * @tc.require: AR000EEMQ9 + */ +HWTEST_F(PosixMqueueTest, ItPosixQueue208, TestSize.Level0) +{ + ItPosixQueue208(); +} + +/** + * @tc.name: IT_POSIX_QUEUE_209 + * @tc.desc: function for mq_notify:The message queue has waiters. + * @tc.type: FUNC + * @tc.require: AR000EEMQ9 + **/ +HWTEST_F(PosixMqueueTest, ItPosixQueue209, TestSize.Level0) +{ + ItPosixQueue209(); +} + #endif } // namespace OHOS