Deleted Added
full compact
uipc_mqueue.c (152864) uipc_mqueue.c (152948)
1/*-
2 * Copyright (c) 2005 David Xu <davidxu@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 29 unchanged lines hidden (view full) ---

38 * times at different mount points but shows same contents.
39 *
40 * 2) Standard POSIX message queue API. The syscalls do not use vfs layer,
41 * but directly operate on internal data structure, this allows user to
42 * use the IPC facility without having to mount mqueue file system.
43 */
44
45#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2005 David Xu <davidxu@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 29 unchanged lines hidden (view full) ---

38 * times at different mount points but shows same contents.
39 *
40 * 2) Standard POSIX message queue API. The syscalls do not use vfs layer,
41 * but directly operate on internal data structure, this allows user to
42 * use the IPC facility without having to mount mqueue file system.
43 */
44
45#include <sys/cdefs.h>
46__FBSDID("$FreeBSD: head/sys/kern/uipc_mqueue.c 152864 2005-11-27 22:59:47Z davidxu $");
46__FBSDID("$FreeBSD: head/sys/kern/uipc_mqueue.c 152948 2005-11-30 05:12:03Z davidxu $");
47
48#include <sys/param.h>
49#include <sys/kernel.h>
50#include <sys/systm.h>
51#include <sys/limits.h>
52#include <sys/buf.h>
53#include <sys/dirent.h>
54#include <sys/event.h>
47
48#include <sys/param.h>
49#include <sys/kernel.h>
50#include <sys/systm.h>
51#include <sys/limits.h>
52#include <sys/buf.h>
53#include <sys/dirent.h>
54#include <sys/event.h>
55#include <sys/eventhandler.h>
55#include <sys/fcntl.h>
56#include <sys/filedesc.h>
57#include <sys/file.h>
58#include <sys/limits.h>
59#include <sys/lock.h>
60#include <sys/malloc.h>
61#include <sys/module.h>
62#include <sys/mount.h>

--- 75 unchanged lines hidden (view full) ---

138 uid_t mn_uid;
139 gid_t mn_gid;
140 int mn_mode;
141};
142
143#define VTON(vp) (((struct mqfs_vdata *)((vp)->v_data))->mv_node)
144#define VTOMQ(vp) ((struct mqueue *)(VTON(vp)->mn_data))
145#define VFSTOMQFS(m) ((struct mqfs_info *)((m)->mnt_data))
56#include <sys/fcntl.h>
57#include <sys/filedesc.h>
58#include <sys/file.h>
59#include <sys/limits.h>
60#include <sys/lock.h>
61#include <sys/malloc.h>
62#include <sys/module.h>
63#include <sys/mount.h>

--- 75 unchanged lines hidden (view full) ---

139 uid_t mn_uid;
140 gid_t mn_gid;
141 int mn_mode;
142};
143
144#define VTON(vp) (((struct mqfs_vdata *)((vp)->v_data))->mv_node)
145#define VTOMQ(vp) ((struct mqueue *)(VTON(vp)->mn_data))
146#define VFSTOMQFS(m) ((struct mqfs_info *)((m)->mnt_data))
146#define FPTOMQ(fp) (((struct mqueue_user *) \
147 (fp)->f_data)->mu_node->mn_data)
147#define FPTOMQ(fp) ((struct mqueue *)(((struct mqfs_node *) \
148 (fp)->f_data)->mn_data))
149
148TAILQ_HEAD(msgq, mqueue_msg);
149
150struct mqueue;
150TAILQ_HEAD(msgq, mqueue_msg);
151
152struct mqueue;
151struct mqueue_user
152{
153 struct sigevent mu_sigev;
154 struct ksiginfo mu_ksi;
155 struct mqfs_node *mu_node;
156 struct proc *mu_proc;
153
154struct mqueue_notifier {
155 LIST_ENTRY(mqueue_notifier) nt_link;
156 struct sigevent nt_sigev;
157 ksiginfo_t nt_ksi;
158 struct proc *nt_proc;
159 int nt_fd;
157};
158
159struct mqueue {
160 struct mtx mq_mutex;
161 int mq_flags;
162 long mq_maxmsg;
163 long mq_msgsize;
164 long mq_curmsgs;
165 long mq_totalbytes;
166 struct msgq mq_msgq;
167 int mq_receivers;
168 int mq_senders;
169 struct selinfo mq_rsel;
170 struct selinfo mq_wsel;
160};
161
162struct mqueue {
163 struct mtx mq_mutex;
164 int mq_flags;
165 long mq_maxmsg;
166 long mq_msgsize;
167 long mq_curmsgs;
168 long mq_totalbytes;
169 struct msgq mq_msgq;
170 int mq_receivers;
171 int mq_senders;
172 struct selinfo mq_rsel;
173 struct selinfo mq_wsel;
171 struct mqueue_user *mq_notifier;
174 struct mqueue_notifier *mq_notifier;
172};
173
174#define MQ_RSEL 0x01
175#define MQ_WSEL 0x02
176
177struct mqueue_msg {
178 TAILQ_ENTRY(mqueue_msg) msg_link;
179 unsigned int msg_prio;

--- 17 unchanged lines hidden (view full) ---

197SYSCTL_INT(_kern_mqueue, OID_AUTO, maxmq, CTLFLAG_RW,
198 &maxmq, 0, "maximum message queues");
199static int curmq = 0;
200SYSCTL_INT(_kern_mqueue, OID_AUTO, curmq, CTLFLAG_RW,
201 &curmq, 0, "current message queue number");
202static int unloadable = 0;
203static MALLOC_DEFINE(M_MQUEUEDATA, "mqdata", "mqueue data");
204
175};
176
177#define MQ_RSEL 0x01
178#define MQ_WSEL 0x02
179
180struct mqueue_msg {
181 TAILQ_ENTRY(mqueue_msg) msg_link;
182 unsigned int msg_prio;

--- 17 unchanged lines hidden (view full) ---

200SYSCTL_INT(_kern_mqueue, OID_AUTO, maxmq, CTLFLAG_RW,
201 &maxmq, 0, "maximum message queues");
202static int curmq = 0;
203SYSCTL_INT(_kern_mqueue, OID_AUTO, curmq, CTLFLAG_RW,
204 &curmq, 0, "current message queue number");
205static int unloadable = 0;
206static MALLOC_DEFINE(M_MQUEUEDATA, "mqdata", "mqueue data");
207
208static eventhandler_tag exit_tag;
209
205/* Only one instance per-system */
206static struct mqfs_info mqfs_data;
207static uma_zone_t mqnode_zone;
208static uma_zone_t mqueue_zone;
209static uma_zone_t mvdata_zone;
210/* Only one instance per-system */
211static struct mqfs_info mqfs_data;
212static uma_zone_t mqnode_zone;
213static uma_zone_t mqueue_zone;
214static uma_zone_t mvdata_zone;
210static uma_zone_t mquser_zone;
215static uma_zone_t mqnoti_zone;
211static struct vop_vector mqfs_vnodeops;
212static struct fileops mqueueops;
213
214/*
215 * Directory structure construction and manipulation
216 */
217#ifdef notyet
218static struct mqfs_node *mqfs_create_dir(struct mqfs_node *parent,

--- 20 unchanged lines hidden (view full) ---

239static int mqueue_receive(struct mqueue *mq, char *msg_ptr,
240 size_t msg_len, unsigned *msg_prio, int waitok,
241 const struct timespec *abs_timeout);
242static int _mqueue_send(struct mqueue *mq, struct mqueue_msg *msg,
243 int timo);
244static int _mqueue_recv(struct mqueue *mq, struct mqueue_msg **msg,
245 int timo);
246static void mqueue_send_notification(struct mqueue *mq);
216static struct vop_vector mqfs_vnodeops;
217static struct fileops mqueueops;
218
219/*
220 * Directory structure construction and manipulation
221 */
222#ifdef notyet
223static struct mqfs_node *mqfs_create_dir(struct mqfs_node *parent,

--- 20 unchanged lines hidden (view full) ---

244static int mqueue_receive(struct mqueue *mq, char *msg_ptr,
245 size_t msg_len, unsigned *msg_prio, int waitok,
246 const struct timespec *abs_timeout);
247static int _mqueue_send(struct mqueue *mq, struct mqueue_msg *msg,
248 int timo);
249static int _mqueue_recv(struct mqueue *mq, struct mqueue_msg **msg,
250 int timo);
251static void mqueue_send_notification(struct mqueue *mq);
252static void mqueue_fdclose(struct thread *td, int fd, struct file *fp);
253static void mq_proc_exit(void *arg, struct proc *p);
247
254
248/* kqueue filters */
255/*
256 * kqueue filters
257 */
249static void filt_mqdetach(struct knote *kn);
250static int filt_mqread(struct knote *kn, long hint);
251static int filt_mqwrite(struct knote *kn, long hint);
252
253struct filterops mq_rfiltops =
254 { 1, NULL, filt_mqdetach, filt_mqread };
255struct filterops mq_wfiltops =
256 { 1, NULL, filt_mqdetach, filt_mqwrite };

--- 16 unchanged lines hidden (view full) ---

273static void
274mqfs_fileno_uninit(struct mqfs_info *mi)
275{
276 struct unrhdr *up;
277
278 up = mi->mi_unrhdr;
279 mi->mi_unrhdr = NULL;
280 delete_unrhdr(up);
258static void filt_mqdetach(struct knote *kn);
259static int filt_mqread(struct knote *kn, long hint);
260static int filt_mqwrite(struct knote *kn, long hint);
261
262struct filterops mq_rfiltops =
263 { 1, NULL, filt_mqdetach, filt_mqread };
264struct filterops mq_wfiltops =
265 { 1, NULL, filt_mqdetach, filt_mqwrite };

--- 16 unchanged lines hidden (view full) ---

282static void
283mqfs_fileno_uninit(struct mqfs_info *mi)
284{
285 struct unrhdr *up;
286
287 up = mi->mi_unrhdr;
288 mi->mi_unrhdr = NULL;
289 delete_unrhdr(up);
281
282 uma_zdestroy(mqnode_zone);
283 uma_zdestroy(mqueue_zone);
284 uma_zdestroy(mvdata_zone);
285 uma_zdestroy(mquser_zone);
286}
287
288/*
289 * Allocate a file number
290 */
290}
291
292/*
293 * Allocate a file number
294 */
291void
295static void
292mqfs_fileno_alloc(struct mqfs_info *mi, struct mqfs_node *mn)
293{
294 /* make sure our parent has a file number */
295 if (mn->mn_parent && !mn->mn_parent->mn_fileno)
296 mqfs_fileno_alloc(mi, mn->mn_parent);
297
298 switch (mn->mn_type) {
299 case mqfstype_root:

--- 24 unchanged lines hidden (view full) ---

324 mn->mn_type));
325 break;
326 }
327}
328
329/*
330 * Release a file number
331 */
296mqfs_fileno_alloc(struct mqfs_info *mi, struct mqfs_node *mn)
297{
298 /* make sure our parent has a file number */
299 if (mn->mn_parent && !mn->mn_parent->mn_fileno)
300 mqfs_fileno_alloc(mi, mn->mn_parent);
301
302 switch (mn->mn_type) {
303 case mqfstype_root:

--- 24 unchanged lines hidden (view full) ---

328 mn->mn_type));
329 break;
330 }
331}
332
333/*
334 * Release a file number
335 */
332void
336static void
333mqfs_fileno_free(struct mqfs_info *mi, struct mqfs_node *mn)
334{
335 switch (mn->mn_type) {
336 case mqfstype_root:
337 case mqfstype_dir:
338 case mqfstype_file:
339 case mqfstype_symlink:
340 free_unr(mi->mi_unrhdr, mn->mn_fileno);

--- 95 unchanged lines hidden (view full) ---

436 return (0);
437}
438
439#ifdef notyet
440
441/*
442 * Create a directory
443 */
337mqfs_fileno_free(struct mqfs_info *mi, struct mqfs_node *mn)
338{
339 switch (mn->mn_type) {
340 case mqfstype_root:
341 case mqfstype_dir:
342 case mqfstype_file:
343 case mqfstype_symlink:
344 free_unr(mi->mi_unrhdr, mn->mn_fileno);

--- 95 unchanged lines hidden (view full) ---

440 return (0);
441}
442
443#ifdef notyet
444
445/*
446 * Create a directory
447 */
444struct mqfs_node *
448static struct mqfs_node *
445mqfs_create_dir(struct mqfs_node *parent, const char *name, int namelen)
446{
447 struct mqfs_node *dir;
448
449 dir = mqnode_alloc();
450 strncpy(dir->mn_name, name, namelen);
451 dir->mn_type = mqfstype_dir;
452 dir->mn_refcount = 1;

--- 4 unchanged lines hidden (view full) ---

457
458 if (mqfs_fixup_dir(dir) != 0) {
459 mqfs_destroy(dir);
460 return (NULL);
461 }
462
463 return (dir);
464}
449mqfs_create_dir(struct mqfs_node *parent, const char *name, int namelen)
450{
451 struct mqfs_node *dir;
452
453 dir = mqnode_alloc();
454 strncpy(dir->mn_name, name, namelen);
455 dir->mn_type = mqfstype_dir;
456 dir->mn_refcount = 1;

--- 4 unchanged lines hidden (view full) ---

461
462 if (mqfs_fixup_dir(dir) != 0) {
463 mqfs_destroy(dir);
464 return (NULL);
465 }
466
467 return (dir);
468}
469
470/*
471 * Create a symlink
472 */
473static struct mqfs_node *
474mqfs_create_link(struct mqfs_node *parent, const char *name, int namelen)
475{
476 struct mqfs_node *node;
477
478 node = mqfs_create_file(parent, name, namelen);
479 if (node == NULL)
480 return (NULL);
481 node->mn_type = mqfstype_symlink;
482 return (node);
483}
484
465#endif
466
467/*
468 * Create a file
469 */
485#endif
486
487/*
488 * Create a file
489 */
470struct mqfs_node *
490static struct mqfs_node *
471mqfs_create_file(struct mqfs_node *parent, const char *name, int namelen)
472{
473 struct mqfs_node *node;
474
475 node = mqnode_alloc();
476 strncpy(node->mn_name, name, namelen);
477 node->mn_type = mqfstype_file;
478 node->mn_refcount = 1;
479
480 if (mqfs_add_node(parent, node) != 0) {
481 mqnode_free(node);
482 return (NULL);
483 }
484 return (node);
485}
486
487/*
491mqfs_create_file(struct mqfs_node *parent, const char *name, int namelen)
492{
493 struct mqfs_node *node;
494
495 node = mqnode_alloc();
496 strncpy(node->mn_name, name, namelen);
497 node->mn_type = mqfstype_file;
498 node->mn_refcount = 1;
499
500 if (mqfs_add_node(parent, node) != 0) {
501 mqnode_free(node);
502 return (NULL);
503 }
504 return (node);
505}
506
507/*
488 * Create a symlink
489 */
490struct mqfs_node *
491mqfs_create_link(struct mqfs_node *parent, const char *name, int namelen)
492{
493 struct mqfs_node *node;
494
495 node = mqfs_create_file(parent, name, namelen);
496 if (node == NULL)
497 return (NULL);
498 node->mn_type = mqfstype_symlink;
499 return (node);
500}
501
502/*
503 * Destroy a node or a tree of nodes
504 */
508 * Destroy a node or a tree of nodes
509 */
505int
510static int
506mqfs_destroy(struct mqfs_node *node)
507{
508 struct mqfs_node *parent;
509
510 KASSERT(node != NULL,
511 ("%s(): node is NULL", __func__));
512 KASSERT(node->mn_info != NULL,
513 ("%s(): node has no mn_info", __func__));

--- 95 unchanged lines hidden (view full) ---

609
610 mqnode_zone = uma_zcreate("mqnode", sizeof(struct mqfs_node),
611 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
612 mqueue_zone = uma_zcreate("mqueue", sizeof(struct mqueue),
613 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
614 mvdata_zone = uma_zcreate("mvdata",
615 sizeof(struct mqfs_vdata), NULL, NULL, NULL,
616 NULL, UMA_ALIGN_PTR, 0);
511mqfs_destroy(struct mqfs_node *node)
512{
513 struct mqfs_node *parent;
514
515 KASSERT(node != NULL,
516 ("%s(): node is NULL", __func__));
517 KASSERT(node->mn_info != NULL,
518 ("%s(): node has no mn_info", __func__));

--- 95 unchanged lines hidden (view full) ---

614
615 mqnode_zone = uma_zcreate("mqnode", sizeof(struct mqfs_node),
616 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
617 mqueue_zone = uma_zcreate("mqueue", sizeof(struct mqueue),
618 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
619 mvdata_zone = uma_zcreate("mvdata",
620 sizeof(struct mqfs_vdata), NULL, NULL, NULL,
621 NULL, UMA_ALIGN_PTR, 0);
617 mquser_zone = uma_zcreate("mquser", sizeof(struct mqueue_user),
622 mqnoti_zone = uma_zcreate("mqnotifier", sizeof(struct mqueue_notifier),
618 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
619 mi = &mqfs_data;
620 sx_init(&mi->mi_lock, "mqfs lock");
621 /* set up the root diretory */
622 root = mqnode_alloc();
623 root->mn_type = mqfstype_root;
624 root->mn_refcount = 1;
625 root->mn_name[0] = '/';
626 root->mn_info = mi;
627 LIST_INIT(&root->mn_children);
628 LIST_INIT(&root->mn_vnodes);
629 root->mn_mode = 01777;
630 mi->mi_root = root;
631 mqfs_fileno_init(mi);
632 mqfs_fileno_alloc(mi, root);
633 mqfs_fixup_dir(root);
623 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
624 mi = &mqfs_data;
625 sx_init(&mi->mi_lock, "mqfs lock");
626 /* set up the root diretory */
627 root = mqnode_alloc();
628 root->mn_type = mqfstype_root;
629 root->mn_refcount = 1;
630 root->mn_name[0] = '/';
631 root->mn_info = mi;
632 LIST_INIT(&root->mn_children);
633 LIST_INIT(&root->mn_vnodes);
634 root->mn_mode = 01777;
635 mi->mi_root = root;
636 mqfs_fileno_init(mi);
637 mqfs_fileno_alloc(mi, root);
638 mqfs_fixup_dir(root);
639 exit_tag = EVENTHANDLER_REGISTER(process_exit, mq_proc_exit, NULL,
640 EVENTHANDLER_PRI_ANY);
641 mq_fdclose = mqueue_fdclose;
634 return (0);
635}
636
637/*
638 * Destroy a mqfs instance
639 */
640static int
641mqfs_uninit(struct vfsconf *vfc)
642{
643 struct mqfs_info *mi;
644
645 if (!unloadable)
646 return (EOPNOTSUPP);
642 return (0);
643}
644
645/*
646 * Destroy a mqfs instance
647 */
648static int
649mqfs_uninit(struct vfsconf *vfc)
650{
651 struct mqfs_info *mi;
652
653 if (!unloadable)
654 return (EOPNOTSUPP);
655 EVENTHANDLER_DEREGISTER(process_exit, exit_tag);
647 mi = &mqfs_data;
648 mqfs_destroy(mi->mi_root);
649 mi->mi_root = NULL;
650 mqfs_fileno_uninit(mi);
651 sx_destroy(&mi->mi_lock);
656 mi = &mqfs_data;
657 mqfs_destroy(mi->mi_root);
658 mi->mi_root = NULL;
659 mqfs_fileno_uninit(mi);
660 sx_destroy(&mi->mi_lock);
661 uma_zdestroy(mqnode_zone);
662 uma_zdestroy(mqueue_zone);
663 uma_zdestroy(mvdata_zone);
664 uma_zdestroy(mqnoti_zone);
652 return (0);
653}
654
655/*
656 * task routine
657 */
658static void
659do_recycle(void *context, int pending __unused)
660{
661 struct vnode *vp = (struct vnode *)context;
662
663 vrecycle(vp, curthread);
664 vdrop(vp);
665}
666
667/*
668 * Allocate a vnode
669 */
665 return (0);
666}
667
668/*
669 * task routine
670 */
671static void
672do_recycle(void *context, int pending __unused)
673{
674 struct vnode *vp = (struct vnode *)context;
675
676 vrecycle(vp, curthread);
677 vdrop(vp);
678}
679
680/*
681 * Allocate a vnode
682 */
670int
683static int
671mqfs_allocv(struct mount *mp, struct vnode **vpp, struct mqfs_node *pn)
672{
673 struct mqfs_vdata *vd;
674 int error;
675
676 LIST_FOREACH(vd, &pn->mn_vnodes, mv_link) {
677 if (vd->mv_vnode->v_mount == mp)
678 break;

--- 843 unchanged lines hidden (view full) ---

1522 */
1523static int
1524mqueue_savemsg(struct mqueue_msg *msg, char *msg_ptr, int *msg_prio)
1525{
1526 int error;
1527
1528 error = copyout(((char *)msg) + sizeof(*msg), msg_ptr,
1529 msg->msg_size);
684mqfs_allocv(struct mount *mp, struct vnode **vpp, struct mqfs_node *pn)
685{
686 struct mqfs_vdata *vd;
687 int error;
688
689 LIST_FOREACH(vd, &pn->mn_vnodes, mv_link) {
690 if (vd->mv_vnode->v_mount == mp)
691 break;

--- 843 unchanged lines hidden (view full) ---

1535 */
1536static int
1537mqueue_savemsg(struct mqueue_msg *msg, char *msg_ptr, int *msg_prio)
1538{
1539 int error;
1540
1541 error = copyout(((char *)msg) + sizeof(*msg), msg_ptr,
1542 msg->msg_size);
1530 if (error == 0)
1543 if (error == 0 && msg_prio != NULL)
1531 error = copyout(&msg->msg_prio, msg_prio, sizeof(int));
1532 return (error);
1533}
1534
1535/*
1536 * Free a message's memory
1537 */
1538static __inline void

--- 132 unchanged lines hidden (view full) ---

1671
1672/*
1673 * Send realtime a signal to process which registered itself
1674 * successfully by mq_notify.
1675 */
1676static void
1677mqueue_send_notification(struct mqueue *mq)
1678{
1544 error = copyout(&msg->msg_prio, msg_prio, sizeof(int));
1545 return (error);
1546}
1547
1548/*
1549 * Free a message's memory
1550 */
1551static __inline void

--- 132 unchanged lines hidden (view full) ---

1684
1685/*
1686 * Send realtime a signal to process which registered itself
1687 * successfully by mq_notify.
1688 */
1689static void
1690mqueue_send_notification(struct mqueue *mq)
1691{
1679 struct mqueue_user *mu;
1692 struct mqueue_notifier *nt;
1693 struct proc *p;
1680
1681 mtx_assert(&mq->mq_mutex, MA_OWNED);
1694
1695 mtx_assert(&mq->mq_mutex, MA_OWNED);
1682 mu = mq->mq_notifier;
1683 PROC_LOCK(mu->mu_proc);
1684 if (!KSI_ONQ(&mu->mu_ksi))
1685 psignal_event(mu->mu_proc, &mu->mu_sigev, &mu->mu_ksi);
1686 PROC_UNLOCK(mu->mu_proc);
1696 nt = mq->mq_notifier;
1697 p = nt->nt_proc;
1698 PROC_LOCK(p);
1699 if (!KSI_ONQ(&nt->nt_ksi))
1700 psignal_event(p, &nt->nt_sigev, &nt->nt_ksi);
1701 PROC_UNLOCK(p);
1687 mq->mq_notifier = NULL;
1688}
1689
1690/*
1691 * Get a message. if waitok is false, thread will not be
1692 * blocked if there is no data in queue, otherwise, absolute
1693 * time will be checked.
1694 */

--- 105 unchanged lines hidden (view full) ---

1800 if (mq->mq_notifier != NULL && mq->mq_receivers == 0 &&
1801 !TAILQ_EMPTY(&mq->mq_msgq)) {
1802 mqueue_send_notification(mq);
1803 }
1804 mtx_unlock(&mq->mq_mutex);
1805 return (error);
1806}
1807
1702 mq->mq_notifier = NULL;
1703}
1704
1705/*
1706 * Get a message. if waitok is false, thread will not be
1707 * blocked if there is no data in queue, otherwise, absolute
1708 * time will be checked.
1709 */

--- 105 unchanged lines hidden (view full) ---

1815 if (mq->mq_notifier != NULL && mq->mq_receivers == 0 &&
1816 !TAILQ_EMPTY(&mq->mq_msgq)) {
1817 mqueue_send_notification(mq);
1818 }
1819 mtx_unlock(&mq->mq_mutex);
1820 return (error);
1821}
1822
1808static __inline struct mqueue_user *
1809mquser_alloc(void)
1823static __inline struct mqueue_notifier *
1824notifier_alloc(void)
1810{
1825{
1811 return (uma_zalloc(mquser_zone, M_WAITOK | M_ZERO));
1826 return (uma_zalloc(mqnoti_zone, M_WAITOK | M_ZERO));
1812}
1813
1814static __inline void
1827}
1828
1829static __inline void
1815mquser_free(struct mqueue_user *p)
1830notifier_free(struct mqueue_notifier *p)
1816{
1831{
1817 uma_zfree(mquser_zone, p);
1832 uma_zfree(mqnoti_zone, p);
1818}
1819
1833}
1834
1835static struct mqueue_notifier *
1836notifier_search(struct proc *p, int fd)
1837{
1838 struct mqueue_notifier *nt;
1839
1840 LIST_FOREACH(nt, &p->p_mqnotifier, nt_link) {
1841 if (nt->nt_fd == fd)
1842 break;
1843 }
1844 return (nt);
1845}
1846
1847static void
1848notifier_insert(struct proc *p, struct mqueue_notifier *nt)
1849{
1850 LIST_INSERT_HEAD(&p->p_mqnotifier, nt, nt_link);
1851}
1852
1853static void
1854notifier_delete(struct proc *p, struct mqueue_notifier *nt)
1855{
1856 LIST_REMOVE(nt, nt_link);
1857 notifier_free(nt);
1858}
1859
1860static void
1861notifier_remove(struct proc *p, struct mqueue *mq, int fd)
1862{
1863 struct mqueue_notifier *nt;
1864
1865 mtx_assert(&mq->mq_mutex, MA_OWNED);
1866 PROC_LOCK(p);
1867 nt = notifier_search(p, fd);
1868 if (nt != NULL) {
1869 if (mq->mq_notifier == nt)
1870 mq->mq_notifier = NULL;
1871 sigqueue_take(&nt->nt_ksi);
1872 notifier_delete(p, nt);
1873 }
1874 PROC_UNLOCK(p);
1875}
1876
1820/*
1821 * Syscall to open a message queue
1822 */
1823int
1824mq_open(struct thread *td, struct mq_open_args *uap)
1825{
1877/*
1878 * Syscall to open a message queue
1879 */
1880int
1881mq_open(struct thread *td, struct mq_open_args *uap)
1882{
1826 char path[MQFS_NAMELEN+1];
1883 char path[MQFS_NAMELEN + 1];
1827 struct mq_attr attr, *pattr;
1828 struct mqfs_node *pn;
1829 struct filedesc *fdp;
1830 struct file *fp;
1884 struct mq_attr attr, *pattr;
1885 struct mqfs_node *pn;
1886 struct filedesc *fdp;
1887 struct file *fp;
1831 struct mqueue_user *mu;
1832 struct mqueue *mq;
1833 int fd, error, len, flags, cmode;
1834
1835 if ((uap->flags & O_ACCMODE) == O_ACCMODE)
1836 return (EINVAL);
1837
1838 fdp = td->td_proc->p_fd;
1839 flags = FFLAGS(uap->flags);

--- 8 unchanged lines hidden (view full) ---

1848 if (attr.mq_msgsize <= 0 || attr.mq_msgsize > maxmsgsize)
1849 return (EINVAL);
1850 pattr = &attr;
1851 } else
1852 pattr = NULL;
1853
1854 error = copyinstr(uap->path, path, MQFS_NAMELEN + 1, NULL);
1855 if (error)
1888 struct mqueue *mq;
1889 int fd, error, len, flags, cmode;
1890
1891 if ((uap->flags & O_ACCMODE) == O_ACCMODE)
1892 return (EINVAL);
1893
1894 fdp = td->td_proc->p_fd;
1895 flags = FFLAGS(uap->flags);

--- 8 unchanged lines hidden (view full) ---

1904 if (attr.mq_msgsize <= 0 || attr.mq_msgsize > maxmsgsize)
1905 return (EINVAL);
1906 pattr = &attr;
1907 } else
1908 pattr = NULL;
1909
1910 error = copyinstr(uap->path, path, MQFS_NAMELEN + 1, NULL);
1911 if (error)
1856 return (error);
1912 return (error);
1857
1858 /*
1859 * The first character of name must be a slash (/) character
1860 * and the remaining characters of name cannot include any slash
1861 * characters.
1862 */
1863 len = strlen(path);
1864 if (len < 2 || path[0] != '/' || index(path + 1, '/') != NULL)

--- 5 unchanged lines hidden (view full) ---

1870
1871 sx_xlock(&mqfs_data.mi_lock);
1872 pn = mqfs_search(mqfs_data.mi_root, path + 1, len - 1);
1873 if (pn == NULL) {
1874 if (!(flags & O_CREAT)) {
1875 error = ENOENT;
1876 } else {
1877 mq = mqueue_alloc(pattr);
1913
1914 /*
1915 * The first character of name must be a slash (/) character
1916 * and the remaining characters of name cannot include any slash
1917 * characters.
1918 */
1919 len = strlen(path);
1920 if (len < 2 || path[0] != '/' || index(path + 1, '/') != NULL)

--- 5 unchanged lines hidden (view full) ---

1926
1927 sx_xlock(&mqfs_data.mi_lock);
1928 pn = mqfs_search(mqfs_data.mi_root, path + 1, len - 1);
1929 if (pn == NULL) {
1930 if (!(flags & O_CREAT)) {
1931 error = ENOENT;
1932 } else {
1933 mq = mqueue_alloc(pattr);
1878 if (mq != NULL)
1934 if (mq == NULL) {
1935 error = ENFILE;
1936 } else {
1879 pn = mqfs_create_file(mqfs_data.mi_root,
1880 path + 1, len - 1);
1937 pn = mqfs_create_file(mqfs_data.mi_root,
1938 path + 1, len - 1);
1881 if (pn == NULL) {
1882 if (mq != NULL)
1939 if (pn == NULL) {
1940 error = ENOSPC;
1883 mqueue_free(mq);
1941 mqueue_free(mq);
1884 error = ENOSPC;
1942 }
1885 }
1886 }
1887
1888 if (error == 0) {
1889 pn->mn_data = mq;
1890 getnanotime(&pn->mn_birth);
1891 pn->mn_ctime = pn->mn_atime = pn->mn_mtime
1892 = pn->mn_birth;

--- 21 unchanged lines hidden (view full) ---

1914 fdclose(fdp, fp, fd, td);
1915 fdrop(fp, td);
1916 return (error);
1917 }
1918
1919 mqnode_addref(pn);
1920 sx_xunlock(&mqfs_data.mi_lock);
1921
1943 }
1944 }
1945
1946 if (error == 0) {
1947 pn->mn_data = mq;
1948 getnanotime(&pn->mn_birth);
1949 pn->mn_ctime = pn->mn_atime = pn->mn_mtime
1950 = pn->mn_birth;

--- 21 unchanged lines hidden (view full) ---

1972 fdclose(fdp, fp, fd, td);
1973 fdrop(fp, td);
1974 return (error);
1975 }
1976
1977 mqnode_addref(pn);
1978 sx_xunlock(&mqfs_data.mi_lock);
1979
1922 mu = mquser_alloc();
1923 mu->mu_node = pn;
1924 ksiginfo_init(&mu->mu_ksi);
1925 mu->mu_ksi.ksi_flags |= KSI_INS | KSI_EXT;
1926 mu->mu_ksi.ksi_code = SI_MESGQ;
1927 mu->mu_proc = td->td_proc;
1928 FILE_LOCK(fp);
1929 fp->f_flag = (flags & (FREAD | FWRITE | O_NONBLOCK));
1930 fp->f_type = DTYPE_MQUEUE;
1931 fp->f_ops = &mqueueops;
1980 FILE_LOCK(fp);
1981 fp->f_flag = (flags & (FREAD | FWRITE | O_NONBLOCK));
1982 fp->f_type = DTYPE_MQUEUE;
1983 fp->f_ops = &mqueueops;
1932 fp->f_data = mu;
1984 fp->f_data = pn;
1933 FILE_UNLOCK(fp);
1934
1935 FILEDESC_LOCK_FAST(fdp);
1936 if (fdp->fd_ofiles[fd] == fp)
1937 fdp->fd_ofileflags[fd] |= UF_EXCLOSE;
1938 FILEDESC_UNLOCK_FAST(fdp);
1939 td->td_retval[0] = fd;
1940 fdrop(fp, td);

--- 32 unchanged lines hidden (view full) ---

1973
1974/*
1975 * Get message queue by giving file slot
1976 */
1977static int
1978_getmq(struct thread *td, int fd, _fgetf func,
1979 struct file **fpp, struct mqfs_node **ppn, struct mqueue **pmq)
1980{
1985 FILE_UNLOCK(fp);
1986
1987 FILEDESC_LOCK_FAST(fdp);
1988 if (fdp->fd_ofiles[fd] == fp)
1989 fdp->fd_ofileflags[fd] |= UF_EXCLOSE;
1990 FILEDESC_UNLOCK_FAST(fdp);
1991 td->td_retval[0] = fd;
1992 fdrop(fp, td);

--- 32 unchanged lines hidden (view full) ---

2025
2026/*
2027 * Get message queue by giving file slot
2028 */
2029static int
2030_getmq(struct thread *td, int fd, _fgetf func,
2031 struct file **fpp, struct mqfs_node **ppn, struct mqueue **pmq)
2032{
1981 struct mqueue_user *mu;
1982 struct mqfs_node *pn;
1983 int error;
1984
1985 error = func(td, fd, fpp);
1986 if (error)
1987 return (error);
1988 if (&mqueueops != (*fpp)->f_ops) {
1989 fdrop(*fpp, td);
1990 return (EBADF);
1991 }
2033 struct mqfs_node *pn;
2034 int error;
2035
2036 error = func(td, fd, fpp);
2037 if (error)
2038 return (error);
2039 if (&mqueueops != (*fpp)->f_ops) {
2040 fdrop(*fpp, td);
2041 return (EBADF);
2042 }
1992 mu = (*fpp)->f_data;
1993 pn = mu->mu_node;
2043 pn = (*fpp)->f_data;
1994 if (ppn)
1995 *ppn = pn;
1996 if (pmq)
1997 *pmq = pn->mn_data;
1998 return (0);
1999}
2000
2001static __inline int

--- 97 unchanged lines hidden (view full) ---

2099
2100/*
2101 * Syscall
2102 */
2103int
2104mq_notify(struct thread *td, struct mq_notify_args *uap)
2105{
2106 struct sigevent ev;
2044 if (ppn)
2045 *ppn = pn;
2046 if (pmq)
2047 *pmq = pn->mn_data;
2048 return (0);
2049}
2050
2051static __inline int

--- 97 unchanged lines hidden (view full) ---

2149
2150/*
2151 * Syscall
2152 */
2153int
2154mq_notify(struct thread *td, struct mq_notify_args *uap)
2155{
2156 struct sigevent ev;
2107 struct mqueue_user *mu;
2157 struct filedesc *fdp;
2158 struct proc *p;
2108 struct mqueue *mq;
2109 struct file *fp;
2159 struct mqueue *mq;
2160 struct file *fp;
2161 struct mqueue_notifier *nt, *newnt = NULL;
2110 int error;
2111
2162 int error;
2163
2164 p = td->td_proc;
2165 fdp = td->td_proc->p_fd;
2112 if (uap->sigev) {
2113 error = copyin(uap->sigev, &ev, sizeof(ev));
2114 if (error)
2115 return (error);
2116 if (ev.sigev_notify != SIGEV_SIGNAL &&
2117 ev.sigev_notify != SIGEV_THREAD_ID)
2118 return (EINVAL);
2119 if ((ev.sigev_notify == SIGEV_SIGNAL ||
2120 ev.sigev_notify == SIGEV_THREAD_ID) &&
2121 !_SIG_VALID(ev.sigev_signo))
2122 return (EINVAL);
2123 }
2124 error = getmq(td, uap->mqd, &fp, NULL, &mq);
2125 if (error)
2126 return (error);
2166 if (uap->sigev) {
2167 error = copyin(uap->sigev, &ev, sizeof(ev));
2168 if (error)
2169 return (error);
2170 if (ev.sigev_notify != SIGEV_SIGNAL &&
2171 ev.sigev_notify != SIGEV_THREAD_ID)
2172 return (EINVAL);
2173 if ((ev.sigev_notify == SIGEV_SIGNAL ||
2174 ev.sigev_notify == SIGEV_THREAD_ID) &&
2175 !_SIG_VALID(ev.sigev_signo))
2176 return (EINVAL);
2177 }
2178 error = getmq(td, uap->mqd, &fp, NULL, &mq);
2179 if (error)
2180 return (error);
2127 mu = fp->f_data;
2181again:
2182 FILEDESC_LOCK_FAST(fdp);
2183 if (fget_locked(fdp, uap->mqd) != fp) {
2184 FILEDESC_UNLOCK_FAST(fdp);
2185 error = EBADF;
2186 goto out;
2187 }
2128 mtx_lock(&mq->mq_mutex);
2188 mtx_lock(&mq->mq_mutex);
2189 FILEDESC_UNLOCK_FAST(fdp);
2129 if (uap->sigev != NULL) {
2130 if (mq->mq_notifier != NULL) {
2131 error = EBUSY;
2132 } else {
2190 if (uap->sigev != NULL) {
2191 if (mq->mq_notifier != NULL) {
2192 error = EBUSY;
2193 } else {
2133 PROC_LOCK(td->td_proc);
2134 sigqueue_take(&mu->mu_ksi);
2135 PROC_UNLOCK(td->td_proc);
2136 mq->mq_notifier = mu;
2137 mu->mu_sigev = ev;
2194 PROC_LOCK(p);
2195 nt = notifier_search(p, uap->mqd);
2196 if (nt == NULL) {
2197 if (newnt == NULL) {
2198 PROC_UNLOCK(p);
2199 mtx_unlock(&mq->mq_mutex);
2200 newnt = notifier_alloc();
2201 goto again;
2202 }
2203 }
2204
2205 if (nt != NULL) {
2206 sigqueue_take(&nt->nt_ksi);
2207 if (newnt != NULL) {
2208 notifier_free(newnt);
2209 newnt = NULL;
2210 }
2211 } else {
2212 nt = newnt;
2213 newnt = NULL;
2214 ksiginfo_init(&nt->nt_ksi);
2215 nt->nt_ksi.ksi_flags |= KSI_INS | KSI_EXT;
2216 nt->nt_ksi.ksi_code = SI_MESGQ;
2217 nt->nt_proc = p;
2218 nt->nt_fd = uap->mqd;
2219 notifier_insert(p, nt);
2220 }
2221 nt->nt_sigev = ev;
2222 mq->mq_notifier = nt;
2223 PROC_UNLOCK(p);
2138 /*
2224 /*
2139 * if there is no receivers and message queue is not
2140 * empty, we should send notification as soon as
2141 * possible.
2225 * if there is no receivers and message queue
2226 * is not empty, we should send notification
2227 * as soon as possible.
2142 */
2143 if (mq->mq_receivers == 0 &&
2144 !TAILQ_EMPTY(&mq->mq_msgq))
2145 mqueue_send_notification(mq);
2146 }
2147 } else {
2228 */
2229 if (mq->mq_receivers == 0 &&
2230 !TAILQ_EMPTY(&mq->mq_msgq))
2231 mqueue_send_notification(mq);
2232 }
2233 } else {
2148 if (mq->mq_notifier == mu)
2149 mq->mq_notifier = NULL;
2150 else
2151 error = EPERM;
2234 notifier_remove(p, mq, uap->mqd);
2152 }
2153 mtx_unlock(&mq->mq_mutex);
2235 }
2236 mtx_unlock(&mq->mq_mutex);
2237
2238out:
2154 fdrop(fp, td);
2239 fdrop(fp, td);
2240 if (newnt != NULL)
2241 notifier_free(newnt);
2155 return (error);
2156}
2157
2242 return (error);
2243}
2244
2245static void
2246mqueue_fdclose(struct thread *td, int fd, struct file *fp)
2247{
2248 struct filedesc *fdp;
2249 struct mqueue *mq;
2250
2251 fdp = td->td_proc->p_fd;
2252 FILEDESC_LOCK_ASSERT(fdp, MA_OWNED);
2253 if (fp->f_ops == &mqueueops) {
2254 mq = FPTOMQ(fp);
2255 mtx_lock(&mq->mq_mutex);
2256 notifier_remove(td->td_proc, mq, fd);
2257
2258 /* have to wakeup thread in same process */
2259 if (mq->mq_flags & MQ_RSEL) {
2260 mq->mq_flags &= ~MQ_RSEL;
2261 selwakeuppri(&mq->mq_rsel, PSOCK);
2262 }
2263 if (mq->mq_flags & MQ_WSEL) {
2264 mq->mq_flags &= ~MQ_WSEL;
2265 selwakeuppri(&mq->mq_wsel, PSOCK);
2266 }
2267 mtx_unlock(&mq->mq_mutex);
2268 }
2269}
2270
2271static void
2272mq_proc_exit(void *arg __unused, struct proc *p)
2273{
2274 struct filedesc *fdp;
2275 struct file *fp;
2276 struct mqueue *mq;
2277 int i;
2278
2279 fdp = p->p_fd;
2280 FILEDESC_LOCK_FAST(fdp);
2281 for (i = 0; i < fdp->fd_nfiles; ++i) {
2282 fp = fget_locked(fdp, i);
2283 if (fp != NULL && fp->f_ops == &mqueueops) {
2284 mq = FPTOMQ(fp);
2285 mtx_lock(&mq->mq_mutex);
2286 notifier_remove(p, FPTOMQ(fp), i);
2287 mtx_unlock(&mq->mq_mutex);
2288 }
2289 }
2290 FILEDESC_UNLOCK_FAST(fdp);
2291 KASSERT(LIST_EMPTY(&p->p_mqnotifier), ("mq notifiers left"));
2292}
2293
2158static int
2159mqf_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
2160 int flags, struct thread *td)
2161{
2162 return (EOPNOTSUPP);
2163}
2164
2165static int

--- 36 unchanged lines hidden (view full) ---

2202 }
2203 mtx_unlock(&mq->mq_mutex);
2204 return (revents);
2205}
2206
2207static int
2208mqf_close(struct file *fp, struct thread *td)
2209{
2294static int
2295mqf_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
2296 int flags, struct thread *td)
2297{
2298 return (EOPNOTSUPP);
2299}
2300
2301static int

--- 36 unchanged lines hidden (view full) ---

2338 }
2339 mtx_unlock(&mq->mq_mutex);
2340 return (revents);
2341}
2342
2343static int
2344mqf_close(struct file *fp, struct thread *td)
2345{
2210 struct mqueue_user *mu;
2211 struct mqfs_node *pn;
2346 struct mqfs_node *pn;
2212 struct mqueue *mq;
2213
2214 FILE_LOCK(fp);
2215 fp->f_ops = &badfileops;
2216 FILE_UNLOCK(fp);
2347
2348 FILE_LOCK(fp);
2349 fp->f_ops = &badfileops;
2350 FILE_UNLOCK(fp);
2217 mu = fp->f_data;
2351 pn = fp->f_data;
2218 fp->f_data = NULL;
2352 fp->f_data = NULL;
2219 pn = mu->mu_node;
2220 mq = pn->mn_data;
2221 mtx_lock(&mq->mq_mutex);
2222 if (mq->mq_notifier == mu) {
2223 PROC_LOCK(td->td_proc);
2224 sigqueue_take(&mu->mu_ksi);
2225 PROC_UNLOCK(td->td_proc);
2226 mq->mq_notifier = NULL;
2227 }
2228 /* have to wakeup thread in same process */
2229 if (mq->mq_flags & MQ_RSEL) {
2230 mq->mq_flags &= ~MQ_RSEL;
2231 selwakeuppri(&mq->mq_rsel, PSOCK);
2232 }
2233 if (mq->mq_flags & MQ_WSEL) {
2234 mq->mq_flags &= ~MQ_WSEL;
2235 selwakeuppri(&mq->mq_wsel, PSOCK);
2236 }
2237 mtx_unlock(&mq->mq_mutex);
2238 sx_xlock(&mqfs_data.mi_lock);
2239 mqnode_release(pn);
2240 sx_xunlock(&mqfs_data.mi_lock);
2353 sx_xlock(&mqfs_data.mi_lock);
2354 mqnode_release(pn);
2355 sx_xunlock(&mqfs_data.mi_lock);
2241 mquser_free(mu);
2242 return (0);
2243}
2244
2245static int
2246mqf_stat(struct file *fp, struct stat *st, struct ucred *active_cred,
2247 struct thread *td)
2248{
2356 return (0);
2357}
2358
2359static int
2360mqf_stat(struct file *fp, struct stat *st, struct ucred *active_cred,
2361 struct thread *td)
2362{
2249 struct mqueue_user *mu = fp->f_data;
2250 struct mqfs_node *pn = mu->mu_node;
2363 struct mqfs_node *pn = fp->f_data;
2251
2252 bzero(st, sizeof *st);
2253 st->st_atimespec = pn->mn_atime;
2254 st->st_mtimespec = pn->mn_mtime;
2255 st->st_ctimespec = pn->mn_ctime;
2256 st->st_birthtimespec = pn->mn_birth;
2257 st->st_uid = pn->mn_uid;
2258 st->st_gid = pn->mn_gid;

--- 100 unchanged lines hidden ---
2364
2365 bzero(st, sizeof *st);
2366 st->st_atimespec = pn->mn_atime;
2367 st->st_mtimespec = pn->mn_mtime;
2368 st->st_ctimespec = pn->mn_ctime;
2369 st->st_birthtimespec = pn->mn_birth;
2370 st->st_uid = pn->mn_uid;
2371 st->st_gid = pn->mn_gid;

--- 100 unchanged lines hidden ---