Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys - Move some checks into mqueue_get() and avoid some dupl...
details: https://anonhg.NetBSD.org/src/rev/2b42b56c16cf
branches: trunk
changeset: 764466:2b42b56c16cf
user: rmind <rmind%NetBSD.org@localhost>
date: Sun Apr 24 20:17:53 2011 +0000
description:
- Move some checks into mqueue_get() and avoid some duplication.
- Simplify message queue descriptor unlinking and closure operations.
- Update proc_t::p_mqueue_cnt atomically. Inherit it on fork().
- Use separate allocation for the name of message queue.
diffstat:
sys/kern/kern_fork.c | 7 +-
sys/kern/sys_mqueue.c | 515 +++++++++++++++++++++++--------------------------
sys/sys/mqueue.h | 24 +-
3 files changed, 260 insertions(+), 286 deletions(-)
diffs (truncated from 898 to 300 lines):
diff -r d881d5dd5a5a -r 2b42b56c16cf sys/kern/kern_fork.c
--- a/sys/kern/kern_fork.c Sun Apr 24 19:00:56 2011 +0000
+++ b/sys/kern/kern_fork.c Sun Apr 24 20:17:53 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_fork.c,v 1.180 2011/03/23 13:57:40 joerg Exp $ */
+/* $NetBSD: kern_fork.c,v 1.181 2011/04/24 20:17:53 rmind Exp $ */
/*-
* Copyright (c) 1999, 2001, 2004, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -67,7 +67,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_fork.c,v 1.180 2011/03/23 13:57:40 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_fork.c,v 1.181 2011/04/24 20:17:53 rmind Exp $");
#include "opt_ktrace.h"
@@ -349,6 +349,9 @@
else
p2->p_fd = fd_copy();
+ /* XXX racy */
+ p2->p_mqueue_cnt = p1->p_mqueue_cnt;
+
if (flags & FORK_SHARECWD)
cwdshare(p2);
else
diff -r d881d5dd5a5a -r 2b42b56c16cf sys/kern/sys_mqueue.c
--- a/sys/kern/sys_mqueue.c Sun Apr 24 19:00:56 2011 +0000
+++ b/sys/kern/sys_mqueue.c Sun Apr 24 20:17:53 2011 +0000
@@ -1,7 +1,7 @@
-/* $NetBSD: sys_mqueue.c,v 1.31 2011/01/18 20:32:53 rmind Exp $ */
+/* $NetBSD: sys_mqueue.c,v 1.32 2011/04/24 20:17:53 rmind Exp $ */
/*
- * Copyright (c) 2007-2009 Mindaugas Rasiukevicius <rmind at NetBSD org>
+ * Copyright (c) 2007-2011 Mindaugas Rasiukevicius <rmind at NetBSD org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,37 +31,30 @@
* Defined in the Base Definitions volume of IEEE Std 1003.1-2001.
*
* Locking
- *
- * Global list of message queues (mqueue_head) and proc_t::p_mqueue_cnt
- * counter are protected by mqlist_mtx lock. The very message queue and
- * its members are protected by mqueue::mq_mtx.
- *
+ *
+ * Global list of message queues (mqueue_head) is protected by mqlist_lock.
+ * Each message queue and its members are protected by mqueue::mq_mtx.
+ * Note that proc_t::p_mqueue_cnt is updated atomically.
+ *
* Lock order:
- * mqlist_mtx ->
- * mqueue::mq_mtx
+ *
+ * mqlist_lock ->
+ * mqueue::mq_mtx
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_mqueue.c,v 1.31 2011/01/18 20:32:53 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_mqueue.c,v 1.32 2011/04/24 20:17:53 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
-#include <sys/condvar.h>
-#include <sys/errno.h>
-#include <sys/fcntl.h>
+
#include <sys/file.h>
#include <sys/filedesc.h>
#include <sys/kauth.h>
-#include <sys/kernel.h>
-#include <sys/kmem.h>
#include <sys/lwp.h>
#include <sys/mqueue.h>
#include <sys/module.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>
@@ -70,8 +63,6 @@
#include <sys/syscall.h>
#include <sys/syscallvar.h>
#include <sys/syscallargs.h>
-#include <sys/systm.h>
-#include <sys/unistd.h>
#include <miscfs/genfs/genfs.h>
@@ -84,10 +75,10 @@
static u_int mq_def_maxmsg = 32;
static u_int mq_max_maxmsg = 16 * 32;
-static kmutex_t mqlist_mtx;
-static pool_cache_t mqmsg_cache;
-static LIST_HEAD(, mqueue) mqueue_head;
-static struct sysctllog *mqsysctl_log;
+static pool_cache_t mqmsg_cache __read_mostly;
+static kmutex_t mqlist_lock __cacheline_aligned;
+static LIST_HEAD(, mqueue) mqueue_head __cacheline_aligned;
+static struct sysctllog * mqsysctl_log;
static int mqueue_sysinit(void);
static int mqueue_sysfini(bool);
@@ -133,7 +124,7 @@
mqmsg_cache = pool_cache_init(MQ_DEF_MSGSIZE, coherency_unit,
0, 0, "mqmsgpl", NULL, IPL_NONE, NULL, NULL, NULL);
- mutex_init(&mqlist_mtx, MUTEX_DEFAULT, IPL_NONE);
+ mutex_init(&mqlist_lock, MUTEX_DEFAULT, IPL_NONE);
LIST_INIT(&mqueue_head);
error = mqueue_sysctl_init();
@@ -160,13 +151,10 @@
error = syscall_disestablish(NULL, mqueue_syscalls);
if (error)
return error;
- /*
- * Check if there are any message queues in use.
- * TODO: We shall support forced unload.
- */
- mutex_enter(&mqlist_mtx);
+ /* Check if there are any message queues in use. */
+ mutex_enter(&mqlist_lock);
inuse = !LIST_EMPTY(&mqueue_head);
- mutex_exit(&mqlist_mtx);
+ mutex_exit(&mqlist_lock);
if (inuse) {
error = syscall_establish(NULL, mqueue_syscalls);
KASSERT(error == 0);
@@ -177,7 +165,7 @@
if (mqsysctl_log != NULL)
sysctl_teardown(&mqsysctl_log);
- mutex_destroy(&mqlist_mtx);
+ mutex_destroy(&mqlist_lock);
pool_cache_destroy(mqmsg_cache);
return 0;
}
@@ -231,6 +219,9 @@
mqueue_freemsg(msg, msz);
}
}
+ if (mq->mq_name) {
+ kmem_free(mq->mq_name, MQ_NAMELEN);
+ }
seldestroy(&mq->mq_rsel);
seldestroy(&mq->mq_wsel);
cv_destroy(&mq->mq_send_cv);
@@ -240,14 +231,16 @@
}
/*
- * Lookup for file name in general list of message queues.
- * => locks the message queue
+ * mqueue_lookup: lookup for file name in general list of message queues.
+ *
+ * => locks the message queue on success
*/
-static void *
-mqueue_lookup(char *name)
+static mqueue_t *
+mqueue_lookup(const char *name)
{
- struct mqueue *mq;
- KASSERT(mutex_owned(&mqlist_mtx));
+ mqueue_t *mq;
+
+ KASSERT(mutex_owned(&mqlist_lock));
LIST_FOREACH(mq, &mqueue_head, mq_list) {
if (strncmp(mq->mq_name, name, MQ_NAMELEN) == 0) {
@@ -255,33 +248,38 @@
return mq;
}
}
-
return NULL;
}
/*
* mqueue_get: get the mqueue from the descriptor.
- * => locks the message queue, if found.
- * => holds a reference on the file descriptor.
+ *
+ * => locks the message queue, if found.
+ * => holds a reference on the file descriptor.
*/
static int
-mqueue_get(mqd_t mqd, file_t **fpr)
+mqueue_get(mqd_t mqd, int fflag, mqueue_t **mqret)
{
- struct mqueue *mq;
+ const int fd = (int)mqd;
+ mqueue_t *mq;
file_t *fp;
- fp = fd_getfile((int)mqd);
+ fp = fd_getfile(fd);
if (__predict_false(fp == NULL)) {
return EBADF;
}
if (__predict_false(fp->f_type != DTYPE_MQUEUE)) {
- fd_putfile((int)mqd);
+ fd_putfile(fd);
+ return EBADF;
+ }
+ if (fflag && (fp->f_flag & fflag) == 0) {
+ fd_putfile(fd);
return EBADF;
}
mq = fp->f_data;
mutex_enter(&mq->mq_mtx);
- *fpr = fp;
+ *mqret = mq;
return 0;
}
@@ -358,49 +356,111 @@
static int
mq_close_fop(file_t *fp)
{
- struct proc *p = curproc;
- struct mqueue *mq = fp->f_data;
- bool destroy;
-
- mutex_enter(&mqlist_mtx);
- mutex_enter(&mq->mq_mtx);
+ proc_t *p = curproc;
+ mqueue_t *mq = fp->f_data;
+ bool destroy = false;
- /* Decrease the counters */
- p->p_mqueue_cnt--;
- mq->mq_refcnt--;
-
- /* Remove notification if registered for this process */
- if (mq->mq_notify_proc == p)
- mq->mq_notify_proc = NULL;
+ mutex_enter(&mq->mq_mtx);
+ KASSERT(mq->mq_refcnt > 0);
+ if (--mq->mq_refcnt == 0) {
+ /* Destroy if the last reference and unlinked. */
+ destroy = (mq->mq_attrib.mq_flags & MQ_UNLINKED) != 0;
+ }
+ mutex_exit(&mq->mq_mtx);
- /*
- * If this is the last reference and mqueue is marked for unlink,
- * remove and later destroy the message queue.
- */
- if (mq->mq_refcnt == 0 && (mq->mq_attrib.mq_flags & MQ_UNLINK)) {
- LIST_REMOVE(mq, mq_list);
- destroy = true;
- } else
- destroy = false;
+ if (destroy) {
+ mqueue_destroy(mq);
+ }
+ atomic_dec_uint(&p->p_mqueue_cnt);
+ return 0;
+}
+
+static int
+mqueue_access(mqueue_t *mq, int access, kauth_cred_t cred)
+{
+ mode_t acc_mode = 0;
- mutex_exit(&mq->mq_mtx);
- mutex_exit(&mqlist_mtx);
-
- if (destroy)
- mqueue_destroy(mq);
-
+ /* Note the difference between VREAD/VWRITE and FREAD/FWRITE. */
+ if (access & FREAD) {
+ acc_mode |= VREAD;
+ }
+ if (access & FWRITE) {
+ acc_mode |= VWRITE;
+ }
+ if (genfs_can_access(VNON, mq->mq_mode, mq->mq_euid,
+ mq->mq_egid, acc_mode, cred)) {
+ return EACCES;
+ }
return 0;
}
static int
-mqueue_access(struct mqueue *mq, mode_t mode, kauth_cred_t cred)
Home |
Main Index |
Thread Index |
Old Index