- Support for select/poll.
- Convert pool to pool-cache. - Wrap long lines, adjust the license.
This commit is contained in:
parent
a4783b9a2e
commit
579caa1e17
@ -1,7 +1,7 @@
|
||||
/* $NetBSD: sys_mqueue.c,v 1.7 2008/03/21 21:55:00 ad Exp $ */
|
||||
/* $NetBSD: sys_mqueue.c,v 1.8 2008/03/23 00:44:15 rmind Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007, Mindaugas Rasiukevicius <rmind at NetBSD org>
|
||||
* Copyright (c) 2007, 2008 Mindaugas Rasiukevicius <rmind at NetBSD org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -13,17 +13,17 @@
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -38,14 +38,10 @@
|
||||
* Lock order:
|
||||
* mqlist_mtx
|
||||
* -> mqueue::mq_mtx
|
||||
*
|
||||
* TODO:
|
||||
* - Hashing or RB-tree for the global list.
|
||||
* - Support for select(), poll() and perhaps kqueue().
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sys_mqueue.c,v 1.7 2008/03/21 21:55:00 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: sys_mqueue.c,v 1.8 2008/03/23 00:44:15 rmind Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
@ -61,8 +57,10 @@ __KERNEL_RCSID(0, "$NetBSD: sys_mqueue.c,v 1.7 2008/03/21 21:55:00 ad Exp $");
|
||||
#include <sys/mqueue.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/pool.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/signalvar.h>
|
||||
#include <sys/sysctl.h>
|
||||
@ -79,14 +77,15 @@ static u_int mq_max_msgsize = 16 * MQ_DEF_MSGSIZE;
|
||||
static u_int mq_def_maxmsg = 32;
|
||||
|
||||
static kmutex_t mqlist_mtx;
|
||||
static struct pool mqmsg_poll;
|
||||
static pool_cache_t mqmsg_cache;
|
||||
static LIST_HEAD(, mqueue) mqueue_head =
|
||||
LIST_HEAD_INITIALIZER(mqueue_head);
|
||||
|
||||
static int mq_poll_fop(file_t *, int);
|
||||
static int mq_close_fop(file_t *);
|
||||
|
||||
static const struct fileops mqops = {
|
||||
fbadop_read, fbadop_write, fbadop_ioctl, fnullop_fcntl, fnullop_poll,
|
||||
fbadop_read, fbadop_write, fbadop_ioctl, fnullop_fcntl, mq_poll_fop,
|
||||
fbadop_stat, mq_close_fop, fnullop_kqfilter
|
||||
};
|
||||
|
||||
@ -97,8 +96,8 @@ void
|
||||
mqueue_sysinit(void)
|
||||
{
|
||||
|
||||
pool_init(&mqmsg_poll, MQ_DEF_MSGSIZE, 0, 0, 0,
|
||||
"mqmsg_poll", &pool_allocator_nointr, IPL_NONE);
|
||||
mqmsg_cache = pool_cache_init(MQ_DEF_MSGSIZE, CACHE_LINE_SIZE,
|
||||
0, 0, "mqmsg_cache", NULL, IPL_NONE, NULL, NULL, NULL);
|
||||
mutex_init(&mqlist_mtx, MUTEX_DEFAULT, IPL_NONE);
|
||||
}
|
||||
|
||||
@ -112,7 +111,7 @@ mqueue_freemsg(struct mq_msg *msg, const size_t size)
|
||||
if (size > MQ_DEF_MSGSIZE)
|
||||
kmem_free(msg, size);
|
||||
else
|
||||
pool_put(&mqmsg_poll, msg);
|
||||
pool_cache_put(mqmsg_cache, msg);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -127,6 +126,8 @@ mqueue_destroy(struct mqueue *mq)
|
||||
TAILQ_REMOVE(&mq->mq_head, msg, msg_queue);
|
||||
mqueue_freemsg(msg, sizeof(struct mq_msg) + msg->msg_len);
|
||||
}
|
||||
seldestroy(&mq->mq_rsel);
|
||||
seldestroy(&mq->mq_wsel);
|
||||
cv_destroy(&mq->mq_send_cv);
|
||||
cv_destroy(&mq->mq_recv_cv);
|
||||
mutex_destroy(&mq->mq_mtx);
|
||||
@ -222,6 +223,32 @@ abstimeout2timo(const void *uaddr, int *timo)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mq_poll_fop(file_t *fp, int events)
|
||||
{
|
||||
struct mqueue *mq = fp->f_data;
|
||||
int revents = 0;
|
||||
|
||||
mutex_enter(&mq->mq_mtx);
|
||||
if (events & (POLLIN | POLLRDNORM)) {
|
||||
/* Ready for receiving, if there are messages in the queue */
|
||||
if (mq->mq_attrib.mq_curmsgs)
|
||||
revents |= (POLLIN | POLLRDNORM);
|
||||
else
|
||||
selrecord(curlwp, &mq->mq_rsel);
|
||||
}
|
||||
if (events & (POLLOUT | POLLWRNORM)) {
|
||||
/* Ready for sending, if the message queue is not full */
|
||||
if (mq->mq_attrib.mq_curmsgs < mq->mq_attrib.mq_maxmsg)
|
||||
revents |= (POLLOUT | POLLWRNORM);
|
||||
else
|
||||
selrecord(curlwp, &mq->mq_wsel);
|
||||
}
|
||||
mutex_exit(&mq->mq_mtx);
|
||||
|
||||
return revents;
|
||||
}
|
||||
|
||||
static int
|
||||
mq_close_fop(file_t *fp)
|
||||
{
|
||||
@ -264,7 +291,8 @@ mq_close_fop(file_t *fp)
|
||||
*/
|
||||
|
||||
int
|
||||
sys_mq_open(struct lwp *l, const struct sys_mq_open_args *uap, register_t *retval)
|
||||
sys_mq_open(struct lwp *l, const struct sys_mq_open_args *uap,
|
||||
register_t *retval)
|
||||
{
|
||||
/* {
|
||||
syscallarg(const char *) name;
|
||||
@ -331,6 +359,8 @@ sys_mq_open(struct lwp *l, const struct sys_mq_open_args *uap, register_t *retva
|
||||
cv_init(&mq_new->mq_send_cv, "mqsendcv");
|
||||
cv_init(&mq_new->mq_recv_cv, "mqrecvcv");
|
||||
TAILQ_INIT(&mq_new->mq_head);
|
||||
selinit(&mq_new->mq_rsel);
|
||||
selinit(&mq_new->mq_wsel);
|
||||
|
||||
strlcpy(mq_new->mq_name, name, MQ_NAMELEN);
|
||||
memcpy(&mq_new->mq_attrib, &attr, sizeof(struct mq_attr));
|
||||
@ -420,7 +450,8 @@ exit:
|
||||
}
|
||||
|
||||
int
|
||||
sys_mq_close(struct lwp *l, const struct sys_mq_close_args *uap, register_t *retval)
|
||||
sys_mq_close(struct lwp *l, const struct sys_mq_close_args *uap,
|
||||
register_t *retval)
|
||||
{
|
||||
|
||||
return sys_close(l, (const void *)uap, retval);
|
||||
@ -481,6 +512,9 @@ mq_receive1(struct lwp *l, mqd_t mqdes, void *msg_ptr, size_t msg_len,
|
||||
/* Decrement the counter and signal waiter, if any */
|
||||
mq->mq_attrib.mq_curmsgs--;
|
||||
cv_signal(&mq->mq_recv_cv);
|
||||
|
||||
/* Ready for sending now */
|
||||
selnotify(&mq->mq_wsel, POLLOUT | POLLWRNORM, 0);
|
||||
error:
|
||||
mutex_exit(&mq->mq_mtx);
|
||||
fd_putfile((int)mqdes);
|
||||
@ -502,7 +536,8 @@ error:
|
||||
}
|
||||
|
||||
int
|
||||
sys_mq_receive(struct lwp *l, const struct sys_mq_receive_args *uap, register_t *retval)
|
||||
sys_mq_receive(struct lwp *l, const struct sys_mq_receive_args *uap,
|
||||
register_t *retval)
|
||||
{
|
||||
/* {
|
||||
syscallarg(mqd_t) mqdes;
|
||||
@ -522,7 +557,8 @@ sys_mq_receive(struct lwp *l, const struct sys_mq_receive_args *uap, register_t
|
||||
}
|
||||
|
||||
int
|
||||
sys_mq_timedreceive(struct lwp *l, const struct sys_mq_timedreceive_args *uap, register_t *retval)
|
||||
sys_mq_timedreceive(struct lwp *l, const struct sys_mq_timedreceive_args *uap,
|
||||
register_t *retval)
|
||||
{
|
||||
/* {
|
||||
syscallarg(mqd_t) mqdes;
|
||||
@ -577,7 +613,7 @@ mq_send1(struct lwp *l, mqd_t mqdes, const char *msg_ptr, size_t msg_len,
|
||||
if (size > MQ_DEF_MSGSIZE)
|
||||
msg = kmem_alloc(size, KM_SLEEP);
|
||||
else
|
||||
msg = pool_get(&mqmsg_poll, PR_WAITOK);
|
||||
msg = pool_cache_get(mqmsg_cache, PR_WAITOK);
|
||||
|
||||
/* Get the data from user-space */
|
||||
error = copyin(msg_ptr, msg->msg_ptr, msg_len);
|
||||
@ -646,6 +682,9 @@ mq_send1(struct lwp *l, mqd_t mqdes, const char *msg_ptr, size_t msg_len,
|
||||
/* Increment the counter and signal waiter, if any */
|
||||
mq->mq_attrib.mq_curmsgs++;
|
||||
cv_signal(&mq->mq_send_cv);
|
||||
|
||||
/* Ready for receiving now */
|
||||
selnotify(&mq->mq_rsel, POLLIN | POLLRDNORM, 0);
|
||||
error:
|
||||
mutex_exit(&mq->mq_mtx);
|
||||
fd_putfile((int)mqdes);
|
||||
@ -663,7 +702,8 @@ error:
|
||||
}
|
||||
|
||||
int
|
||||
sys_mq_send(struct lwp *l, const struct sys_mq_send_args *uap, register_t *retval)
|
||||
sys_mq_send(struct lwp *l, const struct sys_mq_send_args *uap,
|
||||
register_t *retval)
|
||||
{
|
||||
/* {
|
||||
syscallarg(mqd_t) mqdes;
|
||||
@ -677,7 +717,8 @@ sys_mq_send(struct lwp *l, const struct sys_mq_send_args *uap, register_t *retva
|
||||
}
|
||||
|
||||
int
|
||||
sys_mq_timedsend(struct lwp *l, const struct sys_mq_timedsend_args *uap, register_t *retval)
|
||||
sys_mq_timedsend(struct lwp *l, const struct sys_mq_timedsend_args *uap,
|
||||
register_t *retval)
|
||||
{
|
||||
/* {
|
||||
syscallarg(mqd_t) mqdes;
|
||||
@ -701,7 +742,8 @@ sys_mq_timedsend(struct lwp *l, const struct sys_mq_timedsend_args *uap, registe
|
||||
}
|
||||
|
||||
int
|
||||
sys_mq_notify(struct lwp *l, const struct sys_mq_notify_args *uap, register_t *retval)
|
||||
sys_mq_notify(struct lwp *l, const struct sys_mq_notify_args *uap,
|
||||
register_t *retval)
|
||||
{
|
||||
/* {
|
||||
syscallarg(mqd_t) mqdes;
|
||||
@ -746,7 +788,8 @@ sys_mq_notify(struct lwp *l, const struct sys_mq_notify_args *uap, register_t *r
|
||||
}
|
||||
|
||||
int
|
||||
sys_mq_getattr(struct lwp *l, const struct sys_mq_getattr_args *uap, register_t *retval)
|
||||
sys_mq_getattr(struct lwp *l, const struct sys_mq_getattr_args *uap,
|
||||
register_t *retval)
|
||||
{
|
||||
/* {
|
||||
syscallarg(mqd_t) mqdes;
|
||||
@ -770,7 +813,8 @@ sys_mq_getattr(struct lwp *l, const struct sys_mq_getattr_args *uap, register_t
|
||||
}
|
||||
|
||||
int
|
||||
sys_mq_setattr(struct lwp *l, const struct sys_mq_setattr_args *uap, register_t *retval)
|
||||
sys_mq_setattr(struct lwp *l, const struct sys_mq_setattr_args *uap,
|
||||
register_t *retval)
|
||||
{
|
||||
/* {
|
||||
syscallarg(mqd_t) mqdes;
|
||||
@ -819,7 +863,8 @@ sys_mq_setattr(struct lwp *l, const struct sys_mq_setattr_args *uap, register_t
|
||||
}
|
||||
|
||||
int
|
||||
sys_mq_unlink(struct lwp *l, const struct sys_mq_unlink_args *uap, register_t *retval)
|
||||
sys_mq_unlink(struct lwp *l, const struct sys_mq_unlink_args *uap,
|
||||
register_t *retval)
|
||||
{
|
||||
/* {
|
||||
syscallarg(const char *) name;
|
||||
@ -858,6 +903,9 @@ sys_mq_unlink(struct lwp *l, const struct sys_mq_unlink_args *uap, register_t *r
|
||||
cv_broadcast(&mq->mq_send_cv);
|
||||
cv_broadcast(&mq->mq_recv_cv);
|
||||
|
||||
selnotify(&mq->mq_rsel, POLLHUP, 0);
|
||||
selnotify(&mq->mq_wsel, POLLHUP, 0);
|
||||
|
||||
refcnt = mq->mq_refcnt;
|
||||
if (refcnt == 0)
|
||||
LIST_REMOVE(mq, mq_list);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: mqueue.h,v 1.3 2007/11/28 19:30:56 rmind Exp $ */
|
||||
/* $NetBSD: mqueue.h,v 1.4 2008/03/23 00:44:15 rmind Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007, Mindaugas Rasiukevicius <rmind at NetBSD org>
|
||||
@ -13,17 +13,17 @@
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_MQUEUE_H_
|
||||
@ -48,6 +48,7 @@ struct mq_attr {
|
||||
#include <sys/condvar.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/selinfo.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/*
|
||||
@ -58,7 +59,7 @@ struct mq_attr {
|
||||
/* Message queue is unlinking */
|
||||
#define MQ_UNLINK 0x10000000
|
||||
/* There are receive-waiters */
|
||||
#define MQ_RECEIVE 0x40000000
|
||||
#define MQ_RECEIVE 0x20000000
|
||||
|
||||
/* Maximal length of mqueue name */
|
||||
#define MQ_NAMELEN (NAME_MAX + 1)
|
||||
@ -74,6 +75,8 @@ struct mqueue {
|
||||
char mq_name[MQ_NAMELEN];
|
||||
struct mq_attr mq_attrib;
|
||||
/* Notification */
|
||||
struct selinfo mq_rsel;
|
||||
struct selinfo mq_wsel;
|
||||
struct sigevent mq_sig_notify;
|
||||
struct proc * mq_notify_proc;
|
||||
/* Permissions */
|
||||
|
Loading…
Reference in New Issue
Block a user