更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
mqueue.c
浏览该文件的文档.
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.h"
33#ifdef LOSCFG_FS_VFS
34#include "fcntl.h"
35#include "pthread.h"
36#include "map_error.h"
37#include "time_posix.h"
38#include "los_memory.h"
39#include "los_vm_map.h"
40#include "los_process_pri.h"
41#include "fs/file.h"
42#include "user_copy.h"
43
44
45#define FNONBLOCK O_NONBLOCK
46
47#ifndef MAX_MQ_FD
48#define MAX_MQ_FD CONFIG_NQUEUE_DESCRIPTORS
49#endif
50
51/* GLOBALS */
52STATIC fd_set g_queueFdSet;
53STATIC struct mqarray g_queueTable[LOSCFG_BASE_IPC_QUEUE_LIMIT];
54STATIC pthread_mutex_t g_mqueueMutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
55STATIC struct mqpersonal *g_mqPrivBuf[MAX_MQ_FD];
56
57/* LOCAL FUNCTIONS */
58STATIC INLINE INT32 MqNameCheck(const CHAR *mqName)
59{
60 if (mqName == NULL) {
61 errno = EINVAL;
62 return -1;
63 }
64
65 if (strlen(mqName) == 0) {
66 errno = EINVAL;
67 return -1;
68 }
69
70 if (strlen(mqName) > (PATH_MAX - 1)) {
71 errno = ENAMETOOLONG;
72 return -1;
73 }
74 return 0;
75}
76
77STATIC INLINE UINT32 GetMqueueCBByID(UINT32 queueID, LosQueueCB **queueCB)
78{
79 LosQueueCB *tmpQueueCB = NULL;
80 if (queueCB == NULL) {
81 errno = EINVAL;
82 return LOS_ERRNO_QUEUE_READ_PTR_NULL;
83 }
84 tmpQueueCB = GET_QUEUE_HANDLE(queueID);
85 if ((GET_QUEUE_INDEX(queueID) >= LOSCFG_BASE_IPC_QUEUE_LIMIT) || (tmpQueueCB->queueID != queueID)) {
86 return LOS_ERRNO_QUEUE_INVALID;
87 }
88 *queueCB = tmpQueueCB;
89
90 return LOS_OK;
91}
92
93STATIC INLINE struct mqarray *GetMqueueCBByName(const CHAR *name)
94{
95 UINT32 index;
96 UINT32 mylen = strlen(name);
97
98 for (index = 0; index < LOSCFG_BASE_IPC_QUEUE_LIMIT; index++) {
99 if ((g_queueTable[index].mq_name == NULL) || (strlen(g_queueTable[index].mq_name) != mylen)) {
100 continue;
101 }
102
103 if (strncmp(name, (const CHAR *)(g_queueTable[index].mq_name), mylen) == 0) {
104 return &(g_queueTable[index]);
105 }
106 }
107 return NULL;
108}
109
110STATIC INT32 DoMqueueDelete(struct mqarray *mqueueCB)
111{
112 UINT32 ret;
113
114 if (mqueueCB->mq_name != NULL) {
115 LOS_MemFree(OS_SYS_MEM_ADDR, mqueueCB->mq_name);
116 mqueueCB->mq_name = NULL;
117 }
118
119 mqueueCB->mqcb = NULL;
120 /* When mqueue-list head node needed free ,reset the mode_data */
121 mqueueCB->mode_data.data = 0;
122 mqueueCB->euid = -1;
123 mqueueCB->egid = -1;
124 mqueueCB->mq_notify.pid = 0;
125
126 ret = LOS_QueueDelete(mqueueCB->mq_id);
127 switch (ret) {
128 case LOS_OK:
129 return 0;
130 case LOS_ERRNO_QUEUE_NOT_FOUND:
131 case LOS_ERRNO_QUEUE_NOT_CREATE:
132 case LOS_ERRNO_QUEUE_IN_TSKUSE:
133 case LOS_ERRNO_QUEUE_IN_TSKWRITE:
134 errno = EAGAIN;
135 return -1;
136 default:
137 errno = EINVAL;
138 return -1;
139 }
140}
141
142STATIC int SaveMqueueName(const CHAR *mqName, struct mqarray *mqueueCB)
143{
144 size_t nameLen;
145
146 nameLen = strlen(mqName); /* sys_mq_open has checked name and name length */
147 mqueueCB->mq_name = (char *)LOS_MemAlloc(OS_SYS_MEM_ADDR, nameLen + 1);
148 if (mqueueCB->mq_name == NULL) {
149 errno = ENOMEM;
150 return LOS_NOK;
151 }
152
153 if (strncpy_s(mqueueCB->mq_name, (nameLen + 1), mqName, nameLen) != EOK) {
154 LOS_MemFree(OS_SYS_MEM_ADDR, mqueueCB->mq_name);
155 mqueueCB->mq_name = NULL;
156 errno = EINVAL;
157 return LOS_NOK;
158 }
159 mqueueCB->mq_name[nameLen] = '\0';
160 return LOS_OK;
161}
162
163STATIC struct mqpersonal *DoMqueueCreate(const struct mq_attr *attr, const CHAR *mqName, INT32 openFlag, UINT32 mode)
164{
165 struct mqarray *mqueueCB = NULL;
166 UINT32 mqueueID;
167
168 UINT32 err = LOS_QueueCreate(NULL, attr->mq_maxmsg, &mqueueID, 0, attr->mq_msgsize);
169 if (map_errno(err) != ENOERR) {
170 goto ERROUT;
171 }
172
173 if (g_queueTable[GET_QUEUE_INDEX(mqueueID)].mqcb == NULL) {
174 mqueueCB = &(g_queueTable[GET_QUEUE_INDEX(mqueueID)]);
175 mqueueCB->mq_id = mqueueID;
176 }
177
178 if (mqueueCB == NULL) {
179 errno = EINVAL;
180 goto ERROUT;
181 }
182
183 if (SaveMqueueName(mqName, mqueueCB) != LOS_OK) {
184 goto ERROUT;
185 }
186
187 if (GetMqueueCBByID(mqueueCB->mq_id, &(mqueueCB->mqcb)) != LOS_OK) {
188 errno = ENOSPC;
189 goto ERROUT;
190 }
191
192 mqueueCB->mq_personal = (struct mqpersonal *)LOS_MemAlloc(OS_SYS_MEM_ADDR, sizeof(struct mqpersonal));
193 if (mqueueCB->mq_personal == NULL) {
194 (VOID)LOS_QueueDelete(mqueueCB->mq_id);
195 mqueueCB->mqcb->queueHandle = NULL;
196 mqueueCB->mqcb = NULL;
197 errno = ENOSPC;
198 goto ERROUT;
199 }
200
201 mqueueCB->unlinkflag = FALSE;
202 mqueueCB->unlink_ref = 0;
203 mqueueCB->mq_personal->mq_status = MQ_USE_MAGIC;
204 mqueueCB->mq_personal->mq_next = NULL;
205 mqueueCB->mq_personal->mq_posixdes = mqueueCB;
206 mqueueCB->mq_personal->mq_flags = (INT32)((UINT32)openFlag | ((UINT32)attr->mq_flags & (UINT32)FNONBLOCK));
207 mqueueCB->mq_personal->mq_mode = mode;
208 mqueueCB->mq_personal->mq_refcount = 0;
209 mqueueCB->mq_notify.pid = 0;
210
211 return mqueueCB->mq_personal;
212ERROUT:
213
214 if ((mqueueCB != NULL) && (mqueueCB->mq_name != NULL)) {
215 LOS_MemFree(OS_SYS_MEM_ADDR, mqueueCB->mq_name);
216 mqueueCB->mq_name = NULL;
217 }
218 return (struct mqpersonal *)-1;
219}
220
221STATIC struct mqpersonal *DoMqueueOpen(struct mqarray *mqueueCB, INT32 openFlag)
222{
223 struct mqpersonal *privateMqPersonal = NULL;
224
225 /* already have the same name of g_squeuetable */
226 if (mqueueCB->unlinkflag == TRUE) {
227 errno = EINVAL;
228 goto ERROUT;
229 }
230 /* alloc mqprivate and add to mqarray */
231 privateMqPersonal = (struct mqpersonal *)LOS_MemAlloc(OS_SYS_MEM_ADDR, sizeof(struct mqpersonal));
232 if (privateMqPersonal == NULL) {
233 errno = ENOSPC;
234 goto ERROUT;
235 }
236
237 privateMqPersonal->mq_next = mqueueCB->mq_personal;
238 mqueueCB->mq_personal = privateMqPersonal;
239
240 privateMqPersonal->mq_posixdes = mqueueCB;
241 privateMqPersonal->mq_flags = openFlag;
242 privateMqPersonal->mq_status = MQ_USE_MAGIC;
243 privateMqPersonal->mq_refcount = 0;
244
245 return privateMqPersonal;
246
247ERROUT:
248 return (struct mqpersonal *)-1;
249}
250
251STATIC INT32 DoMqueueClose(struct mqpersonal *privateMqPersonal)
252{
253 struct mqarray *mqueueCB = NULL;
254 struct mqpersonal *tmp = NULL;
255
256 mqueueCB = privateMqPersonal->mq_posixdes;
257 if (mqueueCB == NULL || mqueueCB->mq_personal == NULL) {
258 errno = EBADF;
259 return LOS_NOK;
260 }
261
262 /* find the personal and remove */
263 if (mqueueCB->mq_personal == privateMqPersonal) {
264 mqueueCB->mq_personal = privateMqPersonal->mq_next;
265 } else {
266 for (tmp = mqueueCB->mq_personal; tmp->mq_next != NULL; tmp = tmp->mq_next) {
267 if (tmp->mq_next == privateMqPersonal) {
268 break;
269 }
270 }
271 if (tmp->mq_next == NULL) {
272 errno = EBADF;
273 return LOS_NOK;
274 }
275 tmp->mq_next = privateMqPersonal->mq_next;
276 }
277 /* flag no use */
278 privateMqPersonal->mq_status = 0;
279
280 /* free the personal */
281 (VOID)LOS_MemFree(OS_SYS_MEM_ADDR, privateMqPersonal);
282
283 if ((mqueueCB->unlinkflag == TRUE) && (mqueueCB->mq_personal == NULL)) {
284 return DoMqueueDelete(mqueueCB);
285 }
286 return LOS_OK;
287}
288
289/* Translate a sysFd into privateMqPersonal */
290STATIC struct mqpersonal *MqGetPrivDataBuff(mqd_t personal)
291{
292 INT32 sysFd = (INT32)personal;
293 INT32 id = sysFd - MQUEUE_FD_OFFSET;
294
295 /* Filter illegal id */
296 if ((id < 0) || (id >= MAX_MQ_FD)) {
297 errno = EBADF;
298 return NULL;
299 }
300 return g_mqPrivBuf[id];
301}
302
303/**
304 * Alloc sysFd, storage mq private data, set using bit.
305 *
306 * @param maxfdp: Maximum allowed application of mqueue sysFd.
307 * @param fdset: Mqueue sysFd bit map.
308 * @param privateMqPersonal: Private data.
309 * @return the index of the new fd; -1 on error
310 */
311STATIC INT32 MqAllocSysFd(int maxfdp, struct mqpersonal *privateMqPersonal)
312{
313 INT32 i;
314 fd_set *fdset = &g_queueFdSet;
315 for (i = 0; i < maxfdp; i++) {
316 /* sysFd: used bit setting, and get the index of swtmrID buffer */
317 if (fdset && !(FD_ISSET(i + MQUEUE_FD_OFFSET, fdset))) {
318 FD_SET(i + MQUEUE_FD_OFFSET, fdset);
319 if (!g_mqPrivBuf[i]) {
320 g_mqPrivBuf[i] = privateMqPersonal;
321 return i + MQUEUE_FD_OFFSET;
322 }
323 }
324 }
325 return -1;
326}
327
328STATIC VOID MqFreeSysFd(mqd_t personal)
329{
330 INT32 sysFd = (INT32)personal;
331 fd_set *fdset = &g_queueFdSet;
332 if (fdset && FD_ISSET(sysFd, fdset)) {
333 FD_CLR(sysFd, fdset);
334 g_mqPrivBuf[sysFd - MQUEUE_FD_OFFSET] = NULL;
335 }
336}
337
338/* Mqueue fd reference count */
339void MqueueRefer(int sysFd)
340{
341 struct mqarray *mqueueCB = NULL;
342 struct mqpersonal *privateMqPersonal = NULL;
343
345 /* Get the personal sysFd and reset personal fd -1 */
346 privateMqPersonal = MqGetPrivDataBuff((mqd_t)sysFd);
347 if (privateMqPersonal == NULL) {
348 goto OUT_UNLOCK;
349 }
350 mqueueCB = privateMqPersonal->mq_posixdes;
351 if (mqueueCB == NULL) {
352 goto OUT_UNLOCK;
353 }
354
355 privateMqPersonal->mq_refcount++;
356OUT_UNLOCK:
358 return;
359}
360
361STATIC INT32 MqTryClose(struct mqpersonal *privateMqPersonal)
362{
363 struct mqarray *mqueueCB = NULL;
364 mqueueCB = privateMqPersonal->mq_posixdes;
365 if (mqueueCB == NULL) {
366 errno = ENFILE;
367 return false;
368 }
369
370 if (privateMqPersonal->mq_refcount == 0) {
371 return TRUE;
372 }
373 privateMqPersonal->mq_refcount--;
374 return FALSE;
375}
376
377/* Set the mode data bit,for consumer's mode comparing. */
378STATIC INT32 MqueueModeAnalysisSet(struct mqpersonal *privateMqPersonal)
379{
380 UINT32 mode;
381 UINT32 intSave;
382 User *user = NULL;
383 struct mqarray *mqueueCB = NULL;
384
385 if ((INT32)(UINTPTR)privateMqPersonal < 0) {
386 return -1;
387 }
388 /* Get mqueueCB of first time creating mqueue */
389 mqueueCB = privateMqPersonal->mq_posixdes;
390 if (mqueueCB == NULL) {
391 errno = ENFILE;
392 return -1;
393 }
394
395 mode = mqueueCB->mq_personal->mq_mode;
396 /* Set mqueue gid uid */
397 SCHEDULER_LOCK(intSave);
398 user = OsCurrUserGet();
399 mqueueCB->euid = user->effUserID;
400 mqueueCB->egid = user->effGid;
401 SCHEDULER_UNLOCK(intSave);
402
403 /* Set mode data bit */
404 if (mode & S_IRUSR) {
405 mqueueCB->mode_data.usr |= S_IRUSR;
406 }
407 if (mode & S_IWUSR) {
408 mqueueCB->mode_data.usr |= S_IWUSR;
409 }
410 if (mode & S_IRGRP) {
411 mqueueCB->mode_data.grp |= S_IRGRP;
412 }
413 if (mode & S_IWGRP) {
414 mqueueCB->mode_data.grp |= S_IWGRP;
415 }
416 if (mode & S_IROTH) {
417 mqueueCB->mode_data.oth |= S_IROTH;
418 }
419 if (mode & S_IWOTH) {
420 mqueueCB->mode_data.oth |= S_IWOTH;
421 }
422 return 0;
423}
424
425STATIC INT32 GetPermissionOfVisitor(struct mqarray *mqueueCB)
426{
427 uid_t euid;
428 gid_t egid;
429 UINT32 intSave;
430 User *user = NULL;
431
432 if (mqueueCB == NULL) {
433 errno = ENOENT;
434 return -EPERM;
435 }
436
437 /* Get the visitor process euid and egid */
438 SCHEDULER_LOCK(intSave);
439 user = OsCurrUserGet();
440 euid = user->effUserID;
441 egid = user->effGid;
442 SCHEDULER_UNLOCK(intSave);
443
444 /* root */
445 if (euid == 0) {
446 return ENOERR;
447 }
448 if (euid == mqueueCB->euid) { /* usr */
449 if (!((mqueueCB->mode_data.usr & S_IRUSR) || (mqueueCB->mode_data.usr & S_IWUSR))) {
450 errno = EACCES;
451 goto ERR_OUT;
452 }
453 } else if (egid == mqueueCB->egid) { /* grp */
454 if (!((mqueueCB->mode_data.grp & S_IRGRP) || (mqueueCB->mode_data.grp & S_IWGRP))) {
455 errno = EACCES;
456 goto ERR_OUT;
457 }
458 } else { /* oth */
459 if (!((mqueueCB->mode_data.oth & S_IROTH) || (mqueueCB->mode_data.oth & S_IWOTH))) {
460 errno = EACCES;
461 goto ERR_OUT;
462 }
463 }
464 return ENOERR;
465
466ERR_OUT:
467 return -EPERM;
468}
469
470STATIC INT32 GetMqueueAttr(struct mq_attr *defaultAttr, struct mq_attr *attr)
471{
472 if (attr != NULL) {
473 if (LOS_ArchCopyFromUser(defaultAttr, attr, sizeof(struct mq_attr))) {
474 errno = EFAULT;
475 return -1;
476 }
477 if ((defaultAttr->mq_maxmsg < 0) || (defaultAttr->mq_maxmsg > (long int)USHRT_MAX) ||
478 (defaultAttr->mq_msgsize < 0) || (defaultAttr->mq_msgsize > (long int)(USHRT_MAX - sizeof(UINT32)))) {
479 errno = EINVAL;
480 return -1;
481 }
482 }
483 return 0;
484}
485
486mqd_t mq_open(const char *mqName, int openFlag, ...)
487{
488 struct mqarray *mqueueCB = NULL;
489 struct mqpersonal *privateMqPersonal = (struct mqpersonal *)-1;
490 struct mq_attr *attr = NULL;
491 struct mq_attr defaultAttr = { 0, MQ_MAX_MSG_NUM, MQ_MAX_MSG_LEN, 0 };
492 va_list ap;
493 int sysFd;
494 mqd_t mqFd = -1;
495 unsigned int mode = 0;
496
497 if (MqNameCheck(mqName) == -1) {
498 return (mqd_t)-1;
499 }
500
502 mqueueCB = GetMqueueCBByName(mqName);
503 if ((UINT32)openFlag & (UINT32)O_CREAT) {
504 if (mqueueCB != NULL) {
505 if (((UINT32)openFlag & (UINT32)O_EXCL)) {
506 errno = EEXIST;
507 goto OUT;
508 }
509 privateMqPersonal = DoMqueueOpen(mqueueCB, openFlag);
510 } else {
511 va_start(ap, openFlag);
512 mode = va_arg(ap, unsigned int);
513 attr = va_arg(ap, struct mq_attr *);
514 va_end(ap);
515
516 if (GetMqueueAttr(&defaultAttr, attr)) {
517 goto OUT;
518 }
519 privateMqPersonal = DoMqueueCreate(&defaultAttr, mqName, openFlag, mode);
520 }
521 /* Set mode data bit ,just for the first node */
522 if (MqueueModeAnalysisSet(privateMqPersonal)) {
523 if ((INT32)(UINTPTR)privateMqPersonal > 0) {
524 (VOID)DoMqueueClose(privateMqPersonal);
525 }
526 goto OUT;
527 }
528 } else {
529 if (GetPermissionOfVisitor(mqueueCB)) {
530 goto OUT;
531 }
532 privateMqPersonal = DoMqueueOpen(mqueueCB, openFlag);
533 }
534
535 if ((INT32)(UINTPTR)privateMqPersonal > 0) {
536 /* alloc sysFd */
537 sysFd = MqAllocSysFd(MAX_MQ_FD, privateMqPersonal);
538 if (sysFd == -1) {
539 /* there are no more mq sysFd to use, close the personal */
540 (VOID)DoMqueueClose(privateMqPersonal);
541 errno = ENFILE;
542 }
543 mqFd = (mqd_t)sysFd;
544 }
545OUT:
547 return mqFd;
548}
549
550int mq_close(mqd_t personal)
551{
552 INT32 ret = -1;
553 struct mqpersonal *privateMqPersonal = NULL;
554
556
557 /* Get the personal sysFd and reset personal fd -1 */
558 privateMqPersonal = MqGetPrivDataBuff(personal);
559 if (privateMqPersonal == NULL) {
560 goto OUT_UNLOCK;
561 }
562
563 if (privateMqPersonal->mq_status != MQ_USE_MAGIC) {
564 errno = EBADF;
565 goto OUT_UNLOCK;
566 }
567
568 if (!MqTryClose(privateMqPersonal)) {
569 ret = 0;
570 goto OUT_UNLOCK;
571 }
572
573 ret = DoMqueueClose(privateMqPersonal);
574 if (ret < 0) {
575 goto OUT_UNLOCK;
576 }
577 MqFreeSysFd(personal);
578
579OUT_UNLOCK:
581 return ret;
582}
583
584int OsMqGetAttr(mqd_t personal, struct mq_attr *mqAttr)
585{
586 struct mqarray *mqueueCB = NULL;
587 struct mqpersonal *privateMqPersonal = NULL;
588
589 privateMqPersonal = MqGetPrivDataBuff(personal);
590 if (privateMqPersonal == NULL) {
591 return -1;
592 }
593
594 if (mqAttr == NULL) {
595 errno = EINVAL;
596 return -1;
597 }
598
600 if (privateMqPersonal->mq_status != MQ_USE_MAGIC) {
601 errno = EBADF;
603 return -1;
604 }
605
606 mqueueCB = privateMqPersonal->mq_posixdes;
607 mqAttr->mq_maxmsg = mqueueCB->mqcb->queueLen;
608 mqAttr->mq_msgsize = mqueueCB->mqcb->queueSize - sizeof(UINT32);
609 mqAttr->mq_curmsgs = mqueueCB->mqcb->readWriteableCnt[OS_QUEUE_READ];
610 mqAttr->mq_flags = privateMqPersonal->mq_flags;
612 return 0;
613}
614
615int OsMqSetAttr(mqd_t personal, const struct mq_attr *mqSetAttr, struct mq_attr *mqOldAttr)
616{
617 struct mqpersonal *privateMqPersonal = NULL;
618
619 privateMqPersonal = MqGetPrivDataBuff(personal);
620 if (privateMqPersonal == NULL) {
621 return -1;
622 }
623
624 if (mqSetAttr == NULL) {
625 errno = EINVAL;
626 return -1;
627 }
628
630 if (privateMqPersonal->mq_status != MQ_USE_MAGIC) {
631 errno = EBADF;
633 return -1;
634 }
635
636 if (mqOldAttr != NULL) {
637 (VOID)OsMqGetAttr(personal, mqOldAttr);
638 }
639
640 privateMqPersonal->mq_flags = (INT32)((UINT32)privateMqPersonal->mq_flags & (UINT32)(~FNONBLOCK)); /* clear */
641 if (((UINT32)mqSetAttr->mq_flags & (UINT32)FNONBLOCK) == (UINT32)FNONBLOCK) {
642 privateMqPersonal->mq_flags = (INT32)((UINT32)privateMqPersonal->mq_flags | (UINT32)FNONBLOCK);
643 }
645 return 0;
646}
647
648int mq_getsetattr(mqd_t mqd, const struct mq_attr *new, struct mq_attr *old)
649{
650 if (new == NULL) {
651 return OsMqGetAttr(mqd, old);
652 }
653 return OsMqSetAttr(mqd, new, old);
654}
655
656int mq_unlink(const char *mqName)
657{
658 INT32 ret = 0;
659 struct mqarray *mqueueCB = NULL;
660
661 if (MqNameCheck(mqName) == -1) {
662 return -1;
663 }
664
666 mqueueCB = GetMqueueCBByName(mqName);
667 if (mqueueCB == NULL) {
668 errno = ENOENT;
669 goto ERROUT_UNLOCK;
670 }
671
672 if (mqueueCB->mq_personal != NULL) {
673 mqueueCB->unlinkflag = TRUE;
674 } else if (mqueueCB->unlink_ref == 0) {
675 ret = DoMqueueDelete(mqueueCB);
676 }
677
679 return ret;
680
681ERROUT_UNLOCK:
683 return -1;
684}
685
686STATIC INT32 ConvertTimeout(long flags, const struct timespec *absTimeout, UINT64 *ticks)
687{
688 if ((UINT32)flags & (UINT32)FNONBLOCK) {
689 *ticks = LOS_NO_WAIT;
690 return 0;
691 }
692
693 if (absTimeout == NULL) {
694 *ticks = LOS_WAIT_FOREVER;
695 return 0;
696 }
697
698 if (!ValidTimeSpec(absTimeout)) {
699 errno = EINVAL;
700 return -1;
701 }
702
703 *ticks = OsTimeSpec2Tick(absTimeout);
704 return 0;
705}
706
707STATIC INLINE BOOL MqParamCheck(mqd_t personal, const char *msg, size_t msgLen)
708{
709 if (personal < 0) {
710 return FALSE;
711 }
712
713 if ((msg == NULL) || (msgLen == 0)) {
714 errno = EINVAL;
715 return FALSE;
716 }
717 return TRUE;
718}
719
720/*
721 * Send realtime a signal to process which registered itself
722 * successfully by mq_notify.
723 */
724static void MqSendNotify(struct mqarray *mqueueCB)
725{
726 struct mqnotify *mqnotify = &mqueueCB->mq_notify;
727
728 if ((mqnotify->pid) && (mqueueCB->mqcb->readWriteableCnt[OS_QUEUE_READ] == 0)) {
729 siginfo_t info;
730
731 switch (mqnotify->notify.sigev_notify) {
732 case SIGEV_SIGNAL:
733 /* sends signal */
734 /* Create the siginfo structure */
735 info.si_signo = mqnotify->notify.sigev_signo;
736 info.si_code = SI_MESGQ;
737 info.si_value = mqnotify->notify.sigev_value;
738 OsDispatch(mqnotify->pid, &info, OS_USER_KILL_PERMISSION);
739 break;
740 case SIGEV_NONE:
741 default:
742 break;
743 }
744 /* after notification unregisters process */
745 mqnotify->pid = 0;
746 }
747}
748
749#define OS_MQ_GOTO_ERROUT_UNLOCK_IF(expr, errcode) \
750 if (expr) { \
751 errno = errcode; \
752 goto ERROUT_UNLOCK; \
753 }
754#define OS_MQ_GOTO_ERROUT_IF(expr, errcode) \
755 if (expr) { \
756 errno = errcode; \
757 goto ERROUT; \
758 }
759int mq_timedsend(mqd_t personal, const char *msg, size_t msgLen, unsigned int msgPrio,
760 const struct timespec *absTimeout)
761{
762 UINT32 mqueueID, err;
763 UINT64 absTicks;
764 struct mqarray *mqueueCB = NULL;
765 struct mqpersonal *privateMqPersonal = NULL;
766
767 OS_MQ_GOTO_ERROUT_IF(!MqParamCheck(personal, msg, msgLen), errno);
768 OS_MQ_GOTO_ERROUT_IF(msgPrio > (MQ_PRIO_MAX - 1), EINVAL);
769
771 privateMqPersonal = MqGetPrivDataBuff(personal);
772
773 OS_MQ_GOTO_ERROUT_UNLOCK_IF(privateMqPersonal == NULL || privateMqPersonal->mq_status != MQ_USE_MAGIC, EBADF);
774
775 mqueueCB = privateMqPersonal->mq_posixdes;
776 OS_MQ_GOTO_ERROUT_UNLOCK_IF(msgLen > (size_t)(mqueueCB->mqcb->queueSize - sizeof(UINT32)), EMSGSIZE);
777
778 OS_MQ_GOTO_ERROUT_UNLOCK_IF((((UINT32)privateMqPersonal->mq_flags & (UINT32)O_WRONLY) != (UINT32)O_WRONLY) &&
779 (((UINT32)privateMqPersonal->mq_flags & (UINT32)O_RDWR) != (UINT32)O_RDWR),
780 EBADF);
781
782 OS_MQ_GOTO_ERROUT_UNLOCK_IF(ConvertTimeout(privateMqPersonal->mq_flags, absTimeout, &absTicks) == -1, errno);
783 mqueueID = mqueueCB->mq_id;
785
786 if (LOS_ListEmpty(&mqueueCB->mqcb->readWriteList[OS_QUEUE_READ])) {
787 MqSendNotify(mqueueCB);
788 }
789
790 err = LOS_QueueWriteCopy(mqueueID, (VOID *)msg, (UINT32)msgLen, (UINT32)absTicks);
791 if (map_errno(err) != ENOERR) {
792 goto ERROUT;
793 }
794 return 0;
795ERROUT_UNLOCK:
797ERROUT:
798 return -1;
799}
800
801ssize_t mq_timedreceive(mqd_t personal, char *msg, size_t msgLen, unsigned int *msgPrio,
802 const struct timespec *absTimeout)
803{
804 UINT32 mqueueID, err;
805 UINT32 receiveLen;
806 UINT64 absTicks;
807 struct mqarray *mqueueCB = NULL;
808 struct mqpersonal *privateMqPersonal = NULL;
809
810 if (!MqParamCheck(personal, msg, msgLen)) {
811 goto ERROUT;
812 }
813
814 if (msgPrio != NULL) {
815 *msgPrio = 0;
816 }
817
819 privateMqPersonal = MqGetPrivDataBuff(personal);
820 if (privateMqPersonal == NULL || privateMqPersonal->mq_status != MQ_USE_MAGIC) {
821 errno = EBADF;
822 goto ERROUT_UNLOCK;
823 }
824
825 mqueueCB = privateMqPersonal->mq_posixdes;
826 if (msgLen < (size_t)(mqueueCB->mqcb->queueSize - sizeof(UINT32))) {
827 errno = EMSGSIZE;
828 goto ERROUT_UNLOCK;
829 }
830
831 if (((UINT32)privateMqPersonal->mq_flags & (UINT32)O_WRONLY) == (UINT32)O_WRONLY) {
832 errno = EBADF;
833 goto ERROUT_UNLOCK;
834 }
835
836 if (ConvertTimeout(privateMqPersonal->mq_flags, absTimeout, &absTicks) == -1) {
837 goto ERROUT_UNLOCK;
838 }
839
840 receiveLen = msgLen;
841 mqueueID = mqueueCB->mq_id;
843
844 err = LOS_QueueReadCopy(mqueueID, (VOID *)msg, &receiveLen, (UINT32)absTicks);
845 if (map_errno(err) == ENOERR) {
846 return (ssize_t)receiveLen;
847 } else {
848 goto ERROUT;
849 }
850
851ERROUT_UNLOCK:
853ERROUT:
854 return -1;
855}
856
857/* not support the prio */
858int mq_send(mqd_t personal, const char *msg_ptr, size_t msg_len, unsigned int msg_prio)
859{
860 return mq_timedsend(personal, msg_ptr, msg_len, msg_prio, NULL);
861}
862
863ssize_t mq_receive(mqd_t personal, char *msg_ptr, size_t msg_len, unsigned int *msg_prio)
864{
865 return mq_timedreceive(personal, msg_ptr, msg_len, msg_prio, NULL);
866}
867
868STATIC INLINE BOOL MqNotifyParamCheck(mqd_t personal, const struct sigevent *sigev)
869{
870 if (personal < 0) {
871 errno = EBADF;
872 goto ERROUT;
873 }
874
875 if (sigev != NULL) {
876 if (sigev->sigev_notify != SIGEV_NONE && sigev->sigev_notify != SIGEV_SIGNAL) {
877 errno = EINVAL;
878 goto ERROUT;
879 }
880 if (sigev->sigev_notify == SIGEV_SIGNAL && !GOOD_SIGNO(sigev->sigev_signo)) {
881 errno = EINVAL;
882 goto ERROUT;
883 }
884 }
885
886 return TRUE;
887ERROUT:
888 return FALSE;
889}
890
891int OsMqNotify(mqd_t personal, const struct sigevent *sigev)
892{
893 struct mqarray *mqueueCB = NULL;
894 struct mqnotify *mqnotify = NULL;
895 struct mqpersonal *privateMqPersonal = NULL;
896
897 if (!MqNotifyParamCheck(personal, sigev)) {
898 goto ERROUT;
899 }
900
902 privateMqPersonal = MqGetPrivDataBuff(personal);
903 if (privateMqPersonal == NULL) {
904 goto OUT_UNLOCK;
905 }
906
907 if (privateMqPersonal->mq_status != MQ_USE_MAGIC) {
908 errno = EBADF;
909 goto OUT_UNLOCK;
910 }
911
912 mqueueCB = privateMqPersonal->mq_posixdes;
913 mqnotify = &mqueueCB->mq_notify;
914
915 if (sigev == NULL) {
917 mqnotify->pid = 0;
918 }
919 } else if (mqnotify->pid != 0) {
920 errno = EBUSY;
921 goto OUT_UNLOCK;
922 } else {
923 switch (sigev->sigev_notify) {
924 case SIGEV_NONE:
925 mqnotify->notify.sigev_notify = SIGEV_NONE;
926 break;
927 case SIGEV_SIGNAL:
928 mqnotify->notify.sigev_signo = sigev->sigev_signo;
929 mqnotify->notify.sigev_value = sigev->sigev_value;
930 mqnotify->notify.sigev_notify = SIGEV_SIGNAL;
931 break;
932 default:
933 break;
934 }
935
937 }
938
940 return 0;
941OUT_UNLOCK:
943ERROUT:
944 return -1;
945}
946#endif
LITE_OS_SEC_ALW_INLINE STATIC INLINE BOOL LOS_ListEmpty(LOS_DL_LIST *list)
Identify whether a specified doubly linked list is empty. | 判断链表是否为空
Definition: los_list.h:321
VOID * LOS_MemAlloc(VOID *pool, UINT32 size)
从指定内存池中申请size长度的内存,注意这可不是从内核堆空间中申请内存
Definition: los_memory.c:1123
UINT32 LOS_MemFree(VOID *pool, VOID *ptr)
释放从指定动态内存中申请的内存
Definition: los_memory.c:1369
LITE_OS_SEC_TEXT UINT32 LOS_QueueReadCopy(UINT32 queueID, VOID *bufferAddr, UINT32 *bufferSize, UINT32 timeout)
接口函数定时读取消息队列
Definition: los_queue.c:377
LITE_OS_SEC_TEXT_INIT UINT32 LOS_QueueCreate(CHAR *queueName, UINT16 len, UINT32 *queueID, UINT32 flags, UINT16 maxMsgSize)
创建一个队列,根据用户传入队列长度和消息节点大小来开辟相应的内存空间以供该队列使用,参数queueID带走队列ID
Definition: los_queue.c:131
LITE_OS_SEC_TEXT_INIT UINT32 LOS_QueueDelete(UINT32 queueID)
Delete a queue.
Definition: los_queue.c:486
LITE_OS_SEC_TEXT UINT32 LOS_QueueWriteCopy(UINT32 queueID, VOID *bufferAddr, UINT32 bufferSize, UINT32 timeout)
接口函数 从队列尾部开始写
Definition: los_queue.c:411
int mq_getsetattr(mqd_t mqd, const struct mq_attr *new, struct mq_attr *old)
Definition: mqueue.c:648
int mq_send(mqd_t personal, const char *msg_ptr, size_t msg_len, unsigned int msg_prio)
Definition: mqueue.c:858
mqd_t mq_open(const char *mqName, int openFlag,...)
Definition: mqueue.c:486
int mq_close(mqd_t personal)
Definition: mqueue.c:550
ssize_t mq_receive(mqd_t personal, char *msg_ptr, size_t msg_len, unsigned int *msg_prio)
Definition: mqueue.c:863
int mq_timedsend(mqd_t personal, const char *msg, size_t msgLen, unsigned int msgPrio, const struct timespec *absTimeout)
Definition: mqueue.c:759
int mq_unlink(const char *mqName)
Definition: mqueue.c:656
UINTPTR mqd_t
Definition: mqueue.h:127
ssize_t mq_timedreceive(mqd_t personal, char *msg, size_t msgLen, unsigned int *msgPrio, const struct timespec *absTimeout)
Definition: mqueue.c:801
LITE_OS_SEC_TEXT UINT32 LOS_GetCurrProcessID(VOID)
获取当前进程的进程ID
Definition: los_process.c:2161
STATIC INLINE User * OsCurrUserGet(VOID)
@ OS_QUEUE_READ
读队列
Definition: los_queue_pri.h:63
int OsDispatch(pid_t pid, siginfo_t *info, int permission)
信号分发,发送信号权限/进程组过滤.
Definition: los_signal.c:412
static int GOOD_SIGNO(unsigned int sig)
信号ID是否有效
Definition: los_signal.h:158
signed int INT32
Definition: los_typedef.h:60
long unsigned int UINT64
Definition: los_typedef.h:66
INT64 ssize_t
Definition: los_typedef.h:79
unsigned long UINTPTR
Definition: los_typedef.h:68
unsigned int UINT32
Definition: los_typedef.h:57
char CHAR
Definition: los_typedef.h:63
size_t BOOL
Definition: los_typedef.h:88
int map_errno(UINT32 err)
Definition: map_error.c:38
int OsMqSetAttr(mqd_t personal, const struct mq_attr *mqSetAttr, struct mq_attr *mqOldAttr)
Definition: mqueue.c:615
int OsMqGetAttr(mqd_t personal, struct mq_attr *mqAttr)
Definition: mqueue.c:584
void MqueueRefer(int sysFd)
Definition: mqueue.c:339
STATIC INLINE UINT32 GetMqueueCBByID(UINT32 queueID, LosQueueCB **queueCB)
Definition: mqueue.c:77
STATIC struct mqpersonal * DoMqueueCreate(const struct mq_attr *attr, const CHAR *mqName, INT32 openFlag, UINT32 mode)
Definition: mqueue.c:163
STATIC INLINE BOOL MqNotifyParamCheck(mqd_t personal, const struct sigevent *sigev)
Definition: mqueue.c:868
STATIC INT32 GetPermissionOfVisitor(struct mqarray *mqueueCB)
Definition: mqueue.c:425
STATIC struct mqpersonal * g_mqPrivBuf[MAX_MQ_FD]
Definition: mqueue.c:55
STATIC fd_set g_queueFdSet
Definition: mqueue.c:52
STATIC struct mqarray g_queueTable[LOSCFG_BASE_IPC_QUEUE_LIMIT]
Definition: mqueue.c:53
STATIC struct mqpersonal * DoMqueueOpen(struct mqarray *mqueueCB, INT32 openFlag)
Definition: mqueue.c:221
STATIC INT32 MqAllocSysFd(int maxfdp, struct mqpersonal *privateMqPersonal)
Definition: mqueue.c:311
STATIC INLINE INT32 MqNameCheck(const CHAR *mqName)
Definition: mqueue.c:58
STATIC INT32 DoMqueueDelete(struct mqarray *mqueueCB)
Definition: mqueue.c:110
STATIC pthread_mutex_t g_mqueueMutex
Definition: mqueue.c:54
STATIC int SaveMqueueName(const CHAR *mqName, struct mqarray *mqueueCB)
Definition: mqueue.c:142
STATIC VOID MqFreeSysFd(mqd_t personal)
Definition: mqueue.c:328
STATIC struct mqpersonal * MqGetPrivDataBuff(mqd_t personal)
Definition: mqueue.c:290
STATIC INT32 MqueueModeAnalysisSet(struct mqpersonal *privateMqPersonal)
Definition: mqueue.c:378
STATIC INT32 DoMqueueClose(struct mqpersonal *privateMqPersonal)
Definition: mqueue.c:251
STATIC INT32 ConvertTimeout(long flags, const struct timespec *absTimeout, UINT64 *ticks)
Definition: mqueue.c:686
STATIC INT32 GetMqueueAttr(struct mq_attr *defaultAttr, struct mq_attr *attr)
Definition: mqueue.c:470
STATIC INLINE struct mqarray * GetMqueueCBByName(const CHAR *name)
Definition: mqueue.c:93
static void MqSendNotify(struct mqarray *mqueueCB)
Definition: mqueue.c:724
STATIC INLINE BOOL MqParamCheck(mqd_t personal, const char *msg, size_t msgLen)
Definition: mqueue.c:707
int OsMqNotify(mqd_t personal, const struct sigevent *sigev)
Definition: mqueue.c:891
STATIC INT32 MqTryClose(struct mqpersonal *privateMqPersonal)
Definition: mqueue.c:361
int pthread_mutex_lock(pthread_mutex_t *mutex)
互斥锁加锁操作
int pthread_mutex_unlock(pthread_mutex_t *mutex)
解锁互斥锁
UINT16 readWriteableCnt[OS_QUEUE_N_RW]
Definition: los_queue_pri.h:96
UINT16 queueLen
Definition: los_queue_pri.h:91
UINT16 queueSize
Definition: los_queue_pri.h:92
UINT8 * queueHandle
Definition: los_queue_pri.h:89
UINT32 queueID
Definition: los_queue_pri.h:93
LOS_DL_LIST readWriteList[OS_QUEUE_N_RW]
Definition: los_queue_pri.h:98
UINT32 effUserID
UINT32 effGid
long mq_curmsgs
Definition: mqueue.h:120
long mq_flags
Definition: mqueue.h:117
long mq_maxmsg
Definition: mqueue.h:118
long mq_msgsize
Definition: mqueue.h:119
Definition: mqueue.h:90
mode_s mode_data
Definition: mqueue.h:95
gid_t egid
Definition: mqueue.h:97
char * mq_name
Definition: mqueue.h:93
uid_t euid
Definition: mqueue.h:96
LosQueueCB * mqcb
Definition: mqueue.h:99
UINT32 unlink_ref
Definition: mqueue.h:94
UINT32 unlinkflag
Definition: mqueue.h:92
struct mqpersonal * mq_personal
Definition: mqueue.h:100
UINT32 mq_id
Definition: mqueue.h:91
struct mqnotify mq_notify
Definition: mqueue.h:98
pid_t pid
Definition: mqueue.h:85
struct sigevent notify
Definition: mqueue.h:86
struct mqarray * mq_posixdes
Definition: mqueue.h:104
UINT32 mq_refcount
Definition: mqueue.h:109
int mq_mode
Definition: mqueue.h:107
struct mqpersonal * mq_next
Definition: mqueue.h:105
UINT32 mq_status
Definition: mqueue.h:108
int mq_flags
Definition: mqueue.h:106
STATIC INLINE BOOL ValidTimeSpec(const struct timespec *tp)
Definition: time_posix.h:53
STATIC INLINE UINT32 OsTimeSpec2Tick(const struct timespec *tp)
Definition: time_posix.h:68
unsigned oth
Definition: mqueue.h:78
unsigned grp
Definition: mqueue.h:79
short data
Definition: mqueue.h:81
unsigned usr
Definition: mqueue.h:80
size_t LOS_ArchCopyFromUser(void *dst, const void *src, size_t len)
Definition: user_copy.c:58