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