• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  *    conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12  *    of conditions and the following disclaimer in the documentation and/or other materials
13  *    provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16  *    to endorse or promote products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "mqueue_impl.h"
33 #include "time_internal.h"
34 
35 /* GLOBALS */
36 STATIC struct mqarray g_queueTable[LOSCFG_BASE_IPC_QUEUE_LIMIT];
37 STATIC pthread_mutex_t g_mqueueMutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
38 
MapMqErrno(UINT32 err)39 int MapMqErrno(UINT32 err)
40 {
41     if (err == LOS_OK) {
42         return ENOERR;
43     }
44     switch (err) {
45         case LOS_ERRNO_QUEUE_INVALID:
46         case LOS_ERRNO_QUEUE_WRITE_PTR_NULL:
47         case LOS_ERRNO_QUEUE_WRITESIZE_ISZERO:
48         case LOS_ERRNO_QUEUE_SIZE_TOO_BIG:
49         case LOS_ERRNO_QUEUE_CREAT_PTR_NULL:
50         case LOS_ERRNO_QUEUE_PARA_ISZERO:
51         case LOS_ERRNO_QUEUE_WRITE_SIZE_TOO_BIG:
52             errno = EINVAL;
53             break;
54         case LOS_ERRNO_QUEUE_ISFULL:
55         case LOS_ERRNO_QUEUE_ISEMPTY:
56             errno = EAGAIN;
57             break;
58         case LOS_ERRNO_QUEUE_CREATE_NO_MEMORY:
59             errno = ENOSPC;
60             break;
61         case LOS_ERRNO_QUEUE_TIMEOUT:
62             errno = ETIMEDOUT;
63             break;
64         case LOS_ERRNO_QUEUE_CB_UNAVAILABLE:
65             errno = ENFILE;
66             break;
67         case LOS_ERRNO_QUEUE_READ_IN_INTERRUPT:
68         case LOS_ERRNO_QUEUE_WRITE_IN_INTERRUPT:
69             errno = EINTR;
70             break;
71         default:
72             errno = EINVAL;
73             break;
74     }
75     return errno;
76 }
77 
MqNameCheck(const CHAR * mqName)78 STATIC INLINE INT32 MqNameCheck(const CHAR *mqName)
79 {
80     if (mqName == NULL) {
81         errno = EINVAL;
82         return -1;
83     }
84 
85     if (strlen(mqName) == 0) {
86         errno = EINVAL;
87         return -1;
88     }
89 
90     if (strlen(mqName) > (PATH_MAX - 1)) {
91         errno = ENAMETOOLONG;
92         return -1;
93     }
94     return 0;
95 }
96 
GetMqueueCBByID(UINT32 queueID,LosQueueCB ** queueCB)97 STATIC INLINE UINT32 GetMqueueCBByID(UINT32 queueID, LosQueueCB **queueCB)
98 {
99     LosQueueCB *tmpQueueCB = NULL;
100     if (queueCB == NULL) {
101         errno = EINVAL;
102         return LOS_ERRNO_QUEUE_READ_PTR_NULL;
103     }
104     tmpQueueCB = GET_QUEUE_HANDLE(queueID);
105     if ((GET_QUEUE_INDEX(queueID) >= LOSCFG_BASE_IPC_QUEUE_LIMIT) || (tmpQueueCB->queueID != queueID)) {
106         return LOS_ERRNO_QUEUE_INVALID;
107     }
108     *queueCB = tmpQueueCB;
109 
110     return LOS_OK;
111 }
112 
GetMqueueCBByName(const CHAR * name)113 STATIC INLINE struct mqarray *GetMqueueCBByName(const CHAR *name)
114 {
115     UINT32 index;
116     UINT32 mylen = strlen(name);
117 
118     for (index = 0; index < LOSCFG_BASE_IPC_QUEUE_LIMIT; index++) {
119         if ((g_queueTable[index].mq_name == NULL) || (strlen(g_queueTable[index].mq_name) != mylen)) {
120             continue;
121         }
122 
123         if (strncmp(name, (const CHAR *)(g_queueTable[index].mq_name), mylen) == 0) {
124             return &(g_queueTable[index]);
125         }
126     }
127 
128     return NULL;
129 }
130 
DoMqueueDelete(struct mqarray * mqueueCB)131 STATIC INT32 DoMqueueDelete(struct mqarray *mqueueCB)
132 {
133     UINT32 ret;
134 
135     if (mqueueCB->mq_name != NULL) {
136         LOS_MemFree(OS_SYS_MEM_ADDR, mqueueCB->mq_name);
137         mqueueCB->mq_name = NULL;
138     }
139 
140     mqueueCB->mqcb = NULL;
141 
142     ret = LOS_QueueDelete(mqueueCB->mq_id);
143     switch (ret) {
144         case LOS_OK:
145             return 0;
146         case LOS_ERRNO_QUEUE_NOT_FOUND:
147         case LOS_ERRNO_QUEUE_NOT_CREATE:
148         case LOS_ERRNO_QUEUE_IN_TSKUSE:
149         case LOS_ERRNO_QUEUE_IN_TSKWRITE:
150             errno = EAGAIN;
151             return -1;
152         default:
153             errno = EINVAL;
154             return -1;
155     }
156 }
157 
SaveMqueueName(const CHAR * mqName,struct mqarray * mqueueCB)158 STATIC int SaveMqueueName(const CHAR *mqName, struct mqarray *mqueueCB)
159 {
160     size_t nameLen;
161 
162     nameLen = strlen(mqName); /* sys_mq_open has checked name and name length */
163     mqueueCB->mq_name = (char *)LOS_MemAlloc(OS_SYS_MEM_ADDR, nameLen + 1);
164     if (mqueueCB->mq_name == NULL) {
165         errno = ENOMEM;
166         return (int)LOS_NOK;
167     }
168 
169     if (strncpy_s(mqueueCB->mq_name, (nameLen + 1), mqName, nameLen) != EOK) {
170         LOS_MemFree(OS_SYS_MEM_ADDR, mqueueCB->mq_name);
171         mqueueCB->mq_name = NULL;
172         errno = EINVAL;
173         return (int)LOS_NOK;
174     }
175     mqueueCB->mq_name[nameLen] = '\0';
176     return LOS_OK;
177 }
178 
DoMqueueCreate(const struct mq_attr * attr,const CHAR * mqName,INT32 openFlag)179 STATIC struct mqpersonal *DoMqueueCreate(const struct mq_attr *attr, const CHAR *mqName, INT32 openFlag)
180 {
181     struct mqarray *mqueueCB = NULL;
182     UINT32 mqueueID;
183 
184     UINT32 err = LOS_QueueCreate(NULL, attr->mq_maxmsg, &mqueueID, 0, attr->mq_msgsize);
185     if (MapMqErrno(err) != ENOERR) {
186         goto ERROUT;
187     }
188 
189     if (g_queueTable[GET_QUEUE_INDEX(mqueueID)].mqcb == NULL) {
190         mqueueCB = &(g_queueTable[GET_QUEUE_INDEX(mqueueID)]);
191         mqueueCB->mq_id = mqueueID;
192     }
193 
194     if (mqueueCB == NULL) {
195         errno = EINVAL;
196         goto ERROUT;
197     }
198 
199     if (SaveMqueueName(mqName, mqueueCB) != LOS_OK) {
200         goto ERROUT;
201     }
202 
203     if (GetMqueueCBByID(mqueueCB->mq_id, &(mqueueCB->mqcb)) != LOS_OK) {
204         errno = ENOSPC;
205         goto ERROUT;
206     }
207 
208     mqueueCB->mq_personal = (struct mqpersonal *)LOS_MemAlloc(OS_SYS_MEM_ADDR, sizeof(struct mqpersonal));
209     if (mqueueCB->mq_personal == NULL) {
210         (VOID)LOS_QueueDelete(mqueueCB->mq_id);
211         mqueueCB->mqcb->queue = NULL;
212         mqueueCB->mqcb = NULL;
213         errno = ENOSPC;
214         goto ERROUT;
215     }
216 
217     mqueueCB->unlinkflag = FALSE;
218     mqueueCB->mq_personal->mq_status = MQ_USE_MAGIC;
219     mqueueCB->mq_personal->mq_next = NULL;
220     mqueueCB->mq_personal->mq_posixdes = mqueueCB;
221     mqueueCB->mq_personal->mq_flags = (INT32)((UINT32)openFlag | ((UINT32)attr->mq_flags & (UINT32)FNONBLOCK));
222 
223     return mqueueCB->mq_personal;
224 ERROUT:
225 
226     if ((mqueueCB != NULL) && (mqueueCB->mq_name != NULL)) {
227         LOS_MemFree(OS_SYS_MEM_ADDR, mqueueCB->mq_name);
228         mqueueCB->mq_name = NULL;
229     }
230     return (struct mqpersonal *)-1;
231 }
232 
DoMqueueOpen(struct mqarray * mqueueCB,INT32 openFlag)233 STATIC struct mqpersonal *DoMqueueOpen(struct mqarray *mqueueCB, INT32 openFlag)
234 {
235     struct mqpersonal *privateMqPersonal = NULL;
236 
237     /* already have the same name of g_squeuetable */
238     if (mqueueCB->unlinkflag == TRUE) {
239         errno = EINVAL;
240         goto ERROUT;
241     }
242     /* alloc mqprivate and add to mqarray */
243     privateMqPersonal = (struct mqpersonal *)LOS_MemAlloc(OS_SYS_MEM_ADDR, sizeof(struct mqpersonal));
244     if (privateMqPersonal == NULL) {
245         errno = ENOSPC;
246         goto ERROUT;
247     }
248 
249     privateMqPersonal->mq_next = mqueueCB->mq_personal;
250     mqueueCB->mq_personal = privateMqPersonal;
251 
252     privateMqPersonal->mq_posixdes = mqueueCB;
253     privateMqPersonal->mq_flags = openFlag;
254     privateMqPersonal->mq_status = MQ_USE_MAGIC;
255 
256     return privateMqPersonal;
257 
258 ERROUT:
259     return (struct mqpersonal *)-1;
260 }
261 
mq_open(const char * mqName,int openFlag,...)262 mqd_t mq_open(const char *mqName, int openFlag, ...)
263 {
264     struct mqarray *mqueueCB = NULL;
265     struct mqpersonal *privateMqPersonal = (struct mqpersonal *)-1;
266     struct mq_attr *attr = NULL;
267     struct mq_attr defaultAttr = { 0, MQ_MAX_MSG_NUM, MQ_MAX_MSG_LEN, 0, {0} };
268 
269     va_list ap;
270 
271     if (MqNameCheck(mqName) == -1) {
272         return (mqd_t)-1;
273     }
274 
275     (VOID)pthread_mutex_lock(&g_mqueueMutex);
276     mqueueCB = GetMqueueCBByName(mqName);
277     if ((UINT32)openFlag & (UINT32)O_CREAT) {
278         if (mqueueCB != NULL) {
279             if (((UINT32)openFlag & (UINT32)O_EXCL)) {
280                 errno = EEXIST;
281                 goto OUT;
282             }
283             privateMqPersonal = DoMqueueOpen(mqueueCB, openFlag);
284         } else {
285             va_start(ap, openFlag);
286             (VOID)va_arg(ap, int);
287             attr = va_arg(ap, struct mq_attr *);
288             va_end(ap);
289 
290             if (attr != NULL) {
291                 (VOID)memcpy_s(&defaultAttr, sizeof(struct mq_attr), attr, sizeof(struct mq_attr));
292                 if ((defaultAttr.mq_maxmsg < 0) || (defaultAttr.mq_maxmsg > (long int)USHRT_MAX) ||
293                     (defaultAttr.mq_msgsize < 0) || (defaultAttr.mq_msgsize > (long int)(USHRT_MAX - sizeof(UINT32)))) {
294                     errno = EINVAL;
295                     goto OUT;
296                 }
297             }
298             privateMqPersonal = DoMqueueCreate(&defaultAttr, mqName, openFlag);
299         }
300     } else {
301         if (mqueueCB == NULL) {
302             errno = ENOENT;
303             goto OUT;
304         }
305         privateMqPersonal = DoMqueueOpen(mqueueCB, openFlag);
306     }
307 
308 OUT:
309     (VOID)pthread_mutex_unlock(&g_mqueueMutex);
310     return (mqd_t)privateMqPersonal;
311 }
312 
mq_close(mqd_t personal)313 int mq_close(mqd_t personal)
314 {
315     INT32 ret = -1;
316     struct mqarray *mqueueCB = NULL;
317     struct mqpersonal *privateMqPersonal = NULL;
318     struct mqpersonal *tmp = NULL;
319 
320     if ((personal == (mqd_t)NULL) || (personal == (mqd_t)-1)) {
321         errno = EBADF;
322         return -1;
323     }
324 
325     (VOID)pthread_mutex_lock(&g_mqueueMutex);
326     privateMqPersonal = (struct mqpersonal *)personal;
327     if (privateMqPersonal->mq_status != MQ_USE_MAGIC) {
328         errno = EBADF;
329         goto OUT_UNLOCK;
330     }
331 
332     mqueueCB = privateMqPersonal->mq_posixdes;
333     if (mqueueCB->mq_personal == NULL) {
334         errno = EBADF;
335         goto OUT_UNLOCK;
336     }
337 
338     /* find the personal and remove */
339     if (mqueueCB->mq_personal == privateMqPersonal) {
340         mqueueCB->mq_personal = privateMqPersonal->mq_next;
341     } else {
342         for (tmp = mqueueCB->mq_personal; tmp->mq_next != NULL; tmp = tmp->mq_next) {
343             if (tmp->mq_next == privateMqPersonal) {
344                 break;
345             }
346         }
347         if (tmp->mq_next == NULL) {
348             errno = EBADF;
349             goto OUT_UNLOCK;
350         }
351         tmp->mq_next = privateMqPersonal->mq_next;
352     }
353     /* flag no use */
354     privateMqPersonal->mq_status = 0;
355 
356     /* free the personal */
357     ret = LOS_MemFree(OS_SYS_MEM_ADDR, privateMqPersonal);
358     if (ret != LOS_OK) {
359         errno = EFAULT;
360         ret = -1;
361         goto OUT_UNLOCK;
362     }
363 
364     if ((mqueueCB->unlinkflag == TRUE) && (mqueueCB->mq_personal == NULL)) {
365         ret = DoMqueueDelete(mqueueCB);
366     }
367 OUT_UNLOCK:
368     (VOID)pthread_mutex_unlock(&g_mqueueMutex);
369     return ret;
370 }
371 
OsMqGetAttr(mqd_t personal,struct mq_attr * mqAttr)372 int OsMqGetAttr(mqd_t personal, struct mq_attr *mqAttr)
373 {
374     struct mqarray *mqueueCB = NULL;
375     struct mqpersonal *privateMqPersonal = NULL;
376 
377     if (mqAttr == NULL) {
378         errno = EINVAL;
379         return -1;
380     }
381 
382     (VOID)pthread_mutex_lock(&g_mqueueMutex);
383     privateMqPersonal = (struct mqpersonal *)personal;
384     if (privateMqPersonal->mq_status != MQ_USE_MAGIC) {
385         errno = EBADF;
386         (VOID)pthread_mutex_unlock(&g_mqueueMutex);
387         return -1;
388     }
389 
390     mqueueCB = privateMqPersonal->mq_posixdes;
391     mqAttr->mq_maxmsg = mqueueCB->mqcb->queueLen;
392     mqAttr->mq_msgsize = mqueueCB->mqcb->queueSize - sizeof(UINT32);
393     mqAttr->mq_curmsgs = mqueueCB->mqcb->readWriteableCnt[OS_QUEUE_READ];
394     mqAttr->mq_flags = privateMqPersonal->mq_flags;
395     (VOID)pthread_mutex_unlock(&g_mqueueMutex);
396     return 0;
397 }
398 
OsMqSetAttr(mqd_t personal,const struct mq_attr * mqSetAttr,struct mq_attr * mqOldAttr)399 int OsMqSetAttr(mqd_t personal, const struct mq_attr *mqSetAttr, struct mq_attr *mqOldAttr)
400 {
401     struct mqpersonal *privateMqPersonal = NULL;
402 
403     if (mqSetAttr == NULL) {
404         errno = EINVAL;
405         return -1;
406     }
407 
408     (VOID)pthread_mutex_lock(&g_mqueueMutex);
409     privateMqPersonal = (struct mqpersonal *)personal;
410     if (privateMqPersonal->mq_status != MQ_USE_MAGIC) {
411         errno = EBADF;
412         (VOID)pthread_mutex_unlock(&g_mqueueMutex);
413         return -1;
414     }
415 
416     if (mqOldAttr != NULL) {
417         (VOID)OsMqGetAttr((mqd_t)privateMqPersonal, mqOldAttr);
418     }
419 
420     privateMqPersonal->mq_flags = (INT32)((UINT32)privateMqPersonal->mq_flags & (UINT32)(~FNONBLOCK)); /* clear */
421     if (((UINT32)mqSetAttr->mq_flags & (UINT32)FNONBLOCK) == (UINT32)FNONBLOCK) {
422         privateMqPersonal->mq_flags = (INT32)((UINT32)privateMqPersonal->mq_flags | (UINT32)FNONBLOCK);
423     }
424     (VOID)pthread_mutex_unlock(&g_mqueueMutex);
425     return 0;
426 }
427 
MqGetSetAttr(mqd_t mqd,const struct mq_attr * new,struct mq_attr * old)428 static int MqGetSetAttr(mqd_t mqd, const struct mq_attr *new, struct mq_attr *old)
429 {
430     if (new == NULL) {
431         return OsMqGetAttr(mqd, old);
432     }
433     return OsMqSetAttr(mqd, new, old);
434 }
435 
mq_getattr(mqd_t mqd,struct mq_attr * attr)436 int mq_getattr(mqd_t mqd, struct mq_attr *attr)
437 {
438     if ((mqd == (mqd_t)NULL) || (mqd == (mqd_t)-1)) {
439         errno = EBADF;
440         return -1;
441     }
442     return MqGetSetAttr(mqd, NULL, attr);
443 }
444 
mq_setattr(mqd_t mqd,const struct mq_attr * new,struct mq_attr * old)445 int mq_setattr(mqd_t mqd, const struct mq_attr *new, struct mq_attr *old)
446 {
447     if ((mqd == (mqd_t)NULL) || (mqd == (mqd_t)-1)) {
448         errno = EBADF;
449         return -1;
450     }
451     if (new == NULL) {
452         errno = EINVAL;
453         return -1;
454     }
455     return MqGetSetAttr(mqd, new, old);
456 }
457 
mq_unlink(const char * mqName)458 int mq_unlink(const char *mqName)
459 {
460     INT32 ret = 0;
461     struct mqarray *mqueueCB = NULL;
462 
463     if (MqNameCheck(mqName) == -1) {
464         return -1;
465     }
466 
467     (VOID)pthread_mutex_lock(&g_mqueueMutex);
468     mqueueCB = GetMqueueCBByName(mqName);
469     if (mqueueCB == NULL) {
470         errno = ENOENT;
471         goto ERROUT_UNLOCK;
472     }
473 
474     if (mqueueCB->mq_personal != NULL) {
475         errno = EINTR;
476         mqueueCB->unlinkflag = TRUE;
477         goto ERROUT_UNLOCK;
478     } else {
479         ret = DoMqueueDelete(mqueueCB);
480     }
481 
482     (VOID)pthread_mutex_unlock(&g_mqueueMutex);
483     return ret;
484 
485 ERROUT_UNLOCK:
486     (VOID)pthread_mutex_unlock(&g_mqueueMutex);
487     return -1;
488 }
489 
ConvertTimeout(long flags,const struct timespec * absTimeout,UINT64 * ticks)490 STATIC INT32 ConvertTimeout(long flags, const struct timespec *absTimeout, UINT64 *ticks)
491 {
492     if ((UINT32)flags & (UINT32)FNONBLOCK) {
493         *ticks = LOS_NO_WAIT;
494         return 0;
495     }
496 
497     if (absTimeout == NULL) {
498         *ticks = LOS_WAIT_FOREVER;
499         return 0;
500     }
501 
502     if (!ValidTimeSpec(absTimeout)) {
503         errno = EINVAL;
504         return -1;
505     }
506 
507     *ticks = OsTimeSpec2Tick(absTimeout);
508     return 0;
509 }
510 
MqParamCheck(mqd_t personal,const char * msg,size_t msgLen)511 STATIC INLINE BOOL MqParamCheck(mqd_t personal, const char *msg, size_t msgLen)
512 {
513     if ((personal == (mqd_t)NULL) || (personal == (mqd_t)-1)) {
514         errno = EBADF;
515         return FALSE;
516     }
517     if ((msg == NULL) || (msgLen == 0)) {
518         errno = EINVAL;
519         return FALSE;
520     }
521     return TRUE;
522 }
523 
524 #define OS_MQ_GOTO_ERROUT_UNLOCK_IF(expr, errcode) \
525     if (expr) {                        \
526         errno = errcode;                 \
527         goto ERROUT_UNLOCK;                     \
528     }
529 #define OS_MQ_GOTO_ERROUT_IF(expr, errcode) \
530     if (expr) {                        \
531         errno = errcode;                 \
532         goto ERROUT;                     \
533     }
mq_timedsend(mqd_t personal,const char * msg,size_t msgLen,unsigned int msgPrio,const struct timespec * absTimeout)534 int mq_timedsend(mqd_t personal, const char *msg, size_t msgLen, unsigned int msgPrio,
535                  const struct timespec *absTimeout)
536 {
537     UINT32 mqueueID, err;
538     UINT64 absTicks;
539     struct mqarray *mqueueCB = NULL;
540     struct mqpersonal *privateMqPersonal = NULL;
541 
542     OS_MQ_GOTO_ERROUT_IF(!MqParamCheck(personal, msg, msgLen), errno);
543 
544     OS_MQ_GOTO_ERROUT_IF(msgPrio > (MQ_PRIO_MAX - 1), EINVAL);
545 
546     (VOID)pthread_mutex_lock(&g_mqueueMutex);
547     privateMqPersonal = (struct mqpersonal *)personal;
548     OS_MQ_GOTO_ERROUT_UNLOCK_IF(privateMqPersonal->mq_status != MQ_USE_MAGIC, EBADF);
549 
550     mqueueCB = privateMqPersonal->mq_posixdes;
551     OS_MQ_GOTO_ERROUT_UNLOCK_IF(msgLen > (size_t)(mqueueCB->mqcb->queueSize - sizeof(UINT32)), EMSGSIZE);
552 
553     OS_MQ_GOTO_ERROUT_UNLOCK_IF((((UINT32)privateMqPersonal->mq_flags & (UINT32)O_WRONLY) != (UINT32)O_WRONLY) &&
554                                 (((UINT32)privateMqPersonal->mq_flags & (UINT32)O_RDWR) != (UINT32)O_RDWR),
555                                 EBADF);
556 
557     OS_MQ_GOTO_ERROUT_UNLOCK_IF(ConvertTimeout(privateMqPersonal->mq_flags, absTimeout, &absTicks) == -1, errno);
558     mqueueID = mqueueCB->mq_id;
559     (VOID)pthread_mutex_unlock(&g_mqueueMutex);
560 
561     err = LOS_QueueWriteCopy(mqueueID, (VOID *)msg, (UINT32)msgLen, (UINT32)absTicks);
562     if (MapMqErrno(err) != ENOERR) {
563         goto ERROUT;
564     }
565     return 0;
566 ERROUT_UNLOCK:
567     (VOID)pthread_mutex_unlock(&g_mqueueMutex);
568 ERROUT:
569     return -1;
570 }
571 
mq_timedreceive(mqd_t personal,char * msg,size_t msgLen,unsigned int * msgPrio,const struct timespec * absTimeout)572 ssize_t mq_timedreceive(mqd_t personal, char *msg, size_t msgLen, unsigned int *msgPrio,
573                         const struct timespec *absTimeout)
574 {
575     UINT32 mqueueID, err;
576     UINT32 receiveLen;
577     UINT64 absTicks;
578     struct mqarray *mqueueCB = NULL;
579     struct mqpersonal *privateMqPersonal = NULL;
580 
581     if (!MqParamCheck(personal, msg, msgLen)) {
582         goto ERROUT;
583     }
584 
585     if (msgPrio != NULL) {
586         *msgPrio = 0;
587     }
588 
589     (VOID)pthread_mutex_lock(&g_mqueueMutex);
590     privateMqPersonal = (struct mqpersonal *)personal;
591     if (privateMqPersonal->mq_status != MQ_USE_MAGIC) {
592         errno = EBADF;
593         goto ERROUT_UNLOCK;
594     }
595 
596     mqueueCB = privateMqPersonal->mq_posixdes;
597     if (msgLen < (size_t)(mqueueCB->mqcb->queueSize - sizeof(UINT32))) {
598         errno = EMSGSIZE;
599         goto ERROUT_UNLOCK;
600     }
601 
602     if (((UINT32)privateMqPersonal->mq_flags & (UINT32)O_WRONLY) == (UINT32)O_WRONLY) {
603         errno = EBADF;
604         goto ERROUT_UNLOCK;
605     }
606 
607     if (ConvertTimeout(privateMqPersonal->mq_flags, absTimeout, &absTicks) == -1) {
608         goto ERROUT_UNLOCK;
609     }
610 
611     receiveLen = msgLen;
612     mqueueID = mqueueCB->mq_id;
613     (VOID)pthread_mutex_unlock(&g_mqueueMutex);
614 
615     err = LOS_QueueReadCopy(mqueueID, (VOID *)msg, &receiveLen, (UINT32)absTicks);
616     if (MapMqErrno(err) == ENOERR) {
617         return (ssize_t)receiveLen;
618     } else {
619         goto ERROUT;
620     }
621 
622 ERROUT_UNLOCK:
623     (VOID)pthread_mutex_unlock(&g_mqueueMutex);
624 ERROUT:
625     return -1;
626 }
627 
628 /* not support the prio */
mq_send(mqd_t personal,const char * msg_ptr,size_t msg_len,unsigned int msg_prio)629 int mq_send(mqd_t personal, const char *msg_ptr, size_t msg_len, unsigned int msg_prio)
630 {
631     return mq_timedsend(personal, msg_ptr, msg_len, msg_prio, NULL);
632 }
633 
mq_receive(mqd_t personal,char * msg_ptr,size_t msg_len,unsigned int * msg_prio)634 ssize_t mq_receive(mqd_t personal, char *msg_ptr, size_t msg_len, unsigned int *msg_prio)
635 {
636     return mq_timedreceive(personal, msg_ptr, msg_len, msg_prio, NULL);
637 }
638 
639