- Support for select/poll.

- Convert pool to pool-cache.
- Wrap long lines, adjust the license.
This commit is contained in:
rmind 2008-03-23 00:44:15 +00:00
parent a4783b9a2e
commit 579caa1e17
2 changed files with 98 additions and 47 deletions

View File

@ -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);

View File

@ -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 */