Mon Apr 25 11:39:42 2011 UTC ()
Add missing <sys/atomic.h> include.


(martin)
diff -r1.32 -r1.33 src/sys/kern/sys_mqueue.c

cvs diff -r1.32 -r1.33 src/sys/kern/sys_mqueue.c (switch to unified diff)

--- src/sys/kern/sys_mqueue.c 2011/04/24 20:17:53 1.32
+++ src/sys/kern/sys_mqueue.c 2011/04/25 11:39:42 1.33
@@ -1,1048 +1,1049 @@ @@ -1,1048 +1,1049 @@
1/* $NetBSD: sys_mqueue.c,v 1.32 2011/04/24 20:17:53 rmind Exp $ */ 1/* $NetBSD: sys_mqueue.c,v 1.33 2011/04/25 11:39:42 martin Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2007-2011 Mindaugas Rasiukevicius <rmind at NetBSD org> 4 * Copyright (c) 2007-2011 Mindaugas Rasiukevicius <rmind at NetBSD org>
5 * All rights reserved. 5 * All rights reserved.
6 *  6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE. 26 * SUCH DAMAGE.
27 */ 27 */
28 28
29/* 29/*
30 * Implementation of POSIX message queues. 30 * Implementation of POSIX message queues.
31 * Defined in the Base Definitions volume of IEEE Std 1003.1-2001. 31 * Defined in the Base Definitions volume of IEEE Std 1003.1-2001.
32 * 32 *
33 * Locking 33 * Locking
34 * 34 *
35 * Global list of message queues (mqueue_head) is protected by mqlist_lock. 35 * Global list of message queues (mqueue_head) is protected by mqlist_lock.
36 * Each message queue and its members are protected by mqueue::mq_mtx. 36 * Each message queue and its members are protected by mqueue::mq_mtx.
37 * Note that proc_t::p_mqueue_cnt is updated atomically. 37 * Note that proc_t::p_mqueue_cnt is updated atomically.
38 * 38 *
39 * Lock order: 39 * Lock order:
40 * 40 *
41 * mqlist_lock -> 41 * mqlist_lock ->
42 * mqueue::mq_mtx 42 * mqueue::mq_mtx
43 */ 43 */
44 44
45#include <sys/cdefs.h> 45#include <sys/cdefs.h>
46__KERNEL_RCSID(0, "$NetBSD: sys_mqueue.c,v 1.32 2011/04/24 20:17:53 rmind Exp $"); 46__KERNEL_RCSID(0, "$NetBSD: sys_mqueue.c,v 1.33 2011/04/25 11:39:42 martin Exp $");
47 47
48#include <sys/param.h> 48#include <sys/param.h>
49#include <sys/types.h> 49#include <sys/types.h>
 50#include <sys/atomic.h>
50 51
51#include <sys/file.h> 52#include <sys/file.h>
52#include <sys/filedesc.h> 53#include <sys/filedesc.h>
53#include <sys/kauth.h> 54#include <sys/kauth.h>
54#include <sys/lwp.h> 55#include <sys/lwp.h>
55#include <sys/mqueue.h> 56#include <sys/mqueue.h>
56#include <sys/module.h> 57#include <sys/module.h>
57#include <sys/poll.h> 58#include <sys/poll.h>
58#include <sys/select.h> 59#include <sys/select.h>
59#include <sys/signal.h> 60#include <sys/signal.h>
60#include <sys/signalvar.h> 61#include <sys/signalvar.h>
61#include <sys/stat.h> 62#include <sys/stat.h>
62#include <sys/sysctl.h> 63#include <sys/sysctl.h>
63#include <sys/syscall.h> 64#include <sys/syscall.h>
64#include <sys/syscallvar.h> 65#include <sys/syscallvar.h>
65#include <sys/syscallargs.h> 66#include <sys/syscallargs.h>
66 67
67#include <miscfs/genfs/genfs.h> 68#include <miscfs/genfs/genfs.h>
68 69
69MODULE(MODULE_CLASS_MISC, mqueue, NULL); 70MODULE(MODULE_CLASS_MISC, mqueue, NULL);
70 71
71/* System-wide limits. */ 72/* System-wide limits. */
72static u_int mq_open_max = MQ_OPEN_MAX; 73static u_int mq_open_max = MQ_OPEN_MAX;
73static u_int mq_prio_max = MQ_PRIO_MAX; 74static u_int mq_prio_max = MQ_PRIO_MAX;
74static u_int mq_max_msgsize = 16 * MQ_DEF_MSGSIZE; 75static u_int mq_max_msgsize = 16 * MQ_DEF_MSGSIZE;
75static u_int mq_def_maxmsg = 32; 76static u_int mq_def_maxmsg = 32;
76static u_int mq_max_maxmsg = 16 * 32; 77static u_int mq_max_maxmsg = 16 * 32;
77 78
78static pool_cache_t mqmsg_cache __read_mostly; 79static pool_cache_t mqmsg_cache __read_mostly;
79static kmutex_t mqlist_lock __cacheline_aligned; 80static kmutex_t mqlist_lock __cacheline_aligned;
80static LIST_HEAD(, mqueue) mqueue_head __cacheline_aligned; 81static LIST_HEAD(, mqueue) mqueue_head __cacheline_aligned;
81static struct sysctllog * mqsysctl_log; 82static struct sysctllog * mqsysctl_log;
82 83
83static int mqueue_sysinit(void); 84static int mqueue_sysinit(void);
84static int mqueue_sysfini(bool); 85static int mqueue_sysfini(bool);
85static int mqueue_sysctl_init(void); 86static int mqueue_sysctl_init(void);
86static int mq_poll_fop(file_t *, int); 87static int mq_poll_fop(file_t *, int);
87static int mq_stat_fop(file_t *, struct stat *); 88static int mq_stat_fop(file_t *, struct stat *);
88static int mq_close_fop(file_t *); 89static int mq_close_fop(file_t *);
89 90
90static const struct fileops mqops = { 91static const struct fileops mqops = {
91 .fo_read = fbadop_read, 92 .fo_read = fbadop_read,
92 .fo_write = fbadop_write, 93 .fo_write = fbadop_write,
93 .fo_ioctl = fbadop_ioctl, 94 .fo_ioctl = fbadop_ioctl,
94 .fo_fcntl = fnullop_fcntl, 95 .fo_fcntl = fnullop_fcntl,
95 .fo_poll = mq_poll_fop, 96 .fo_poll = mq_poll_fop,
96 .fo_stat = mq_stat_fop, 97 .fo_stat = mq_stat_fop,
97 .fo_close = mq_close_fop, 98 .fo_close = mq_close_fop,
98 .fo_kqfilter = fnullop_kqfilter, 99 .fo_kqfilter = fnullop_kqfilter,
99 .fo_restart = fnullop_restart, 100 .fo_restart = fnullop_restart,
100}; 101};
101 102
102static const struct syscall_package mqueue_syscalls[] = { 103static const struct syscall_package mqueue_syscalls[] = {
103 { SYS_mq_open, 0, (sy_call_t *)sys_mq_open }, 104 { SYS_mq_open, 0, (sy_call_t *)sys_mq_open },
104 { SYS_mq_close, 0, (sy_call_t *)sys_mq_close }, 105 { SYS_mq_close, 0, (sy_call_t *)sys_mq_close },
105 { SYS_mq_unlink, 0, (sy_call_t *)sys_mq_unlink }, 106 { SYS_mq_unlink, 0, (sy_call_t *)sys_mq_unlink },
106 { SYS_mq_getattr, 0, (sy_call_t *)sys_mq_getattr }, 107 { SYS_mq_getattr, 0, (sy_call_t *)sys_mq_getattr },
107 { SYS_mq_setattr, 0, (sy_call_t *)sys_mq_setattr }, 108 { SYS_mq_setattr, 0, (sy_call_t *)sys_mq_setattr },
108 { SYS_mq_notify, 0, (sy_call_t *)sys_mq_notify }, 109 { SYS_mq_notify, 0, (sy_call_t *)sys_mq_notify },
109 { SYS_mq_send, 0, (sy_call_t *)sys_mq_send }, 110 { SYS_mq_send, 0, (sy_call_t *)sys_mq_send },
110 { SYS_mq_receive, 0, (sy_call_t *)sys_mq_receive }, 111 { SYS_mq_receive, 0, (sy_call_t *)sys_mq_receive },
111 { SYS___mq_timedsend50, 0, (sy_call_t *)sys___mq_timedsend50 }, 112 { SYS___mq_timedsend50, 0, (sy_call_t *)sys___mq_timedsend50 },
112 { SYS___mq_timedreceive50, 0, (sy_call_t *)sys___mq_timedreceive50 }, 113 { SYS___mq_timedreceive50, 0, (sy_call_t *)sys___mq_timedreceive50 },
113 { 0, 0, NULL } 114 { 0, 0, NULL }
114}; 115};
115 116
116/* 117/*
117 * Initialisation and unloading of POSIX message queue subsystem. 118 * Initialisation and unloading of POSIX message queue subsystem.
118 */ 119 */
119 120
120static int 121static int
121mqueue_sysinit(void) 122mqueue_sysinit(void)
122{ 123{
123 int error; 124 int error;
124 125
125 mqmsg_cache = pool_cache_init(MQ_DEF_MSGSIZE, coherency_unit, 126 mqmsg_cache = pool_cache_init(MQ_DEF_MSGSIZE, coherency_unit,
126 0, 0, "mqmsgpl", NULL, IPL_NONE, NULL, NULL, NULL); 127 0, 0, "mqmsgpl", NULL, IPL_NONE, NULL, NULL, NULL);
127 mutex_init(&mqlist_lock, MUTEX_DEFAULT, IPL_NONE); 128 mutex_init(&mqlist_lock, MUTEX_DEFAULT, IPL_NONE);
128 LIST_INIT(&mqueue_head); 129 LIST_INIT(&mqueue_head);
129 130
130 error = mqueue_sysctl_init(); 131 error = mqueue_sysctl_init();
131 if (error) { 132 if (error) {
132 (void)mqueue_sysfini(false); 133 (void)mqueue_sysfini(false);
133 return error; 134 return error;
134 } 135 }
135 error = syscall_establish(NULL, mqueue_syscalls); 136 error = syscall_establish(NULL, mqueue_syscalls);
136 if (error) { 137 if (error) {
137 (void)mqueue_sysfini(false); 138 (void)mqueue_sysfini(false);
138 } 139 }
139 return error; 140 return error;
140} 141}
141 142
142static int 143static int
143mqueue_sysfini(bool interface) 144mqueue_sysfini(bool interface)
144{ 145{
145 146
146 if (interface) { 147 if (interface) {
147 int error; 148 int error;
148 bool inuse; 149 bool inuse;
149 150
150 /* Stop syscall activity. */ 151 /* Stop syscall activity. */
151 error = syscall_disestablish(NULL, mqueue_syscalls); 152 error = syscall_disestablish(NULL, mqueue_syscalls);
152 if (error) 153 if (error)
153 return error; 154 return error;
154 /* Check if there are any message queues in use. */ 155 /* Check if there are any message queues in use. */
155 mutex_enter(&mqlist_lock); 156 mutex_enter(&mqlist_lock);
156 inuse = !LIST_EMPTY(&mqueue_head); 157 inuse = !LIST_EMPTY(&mqueue_head);
157 mutex_exit(&mqlist_lock); 158 mutex_exit(&mqlist_lock);
158 if (inuse) { 159 if (inuse) {
159 error = syscall_establish(NULL, mqueue_syscalls); 160 error = syscall_establish(NULL, mqueue_syscalls);
160 KASSERT(error == 0); 161 KASSERT(error == 0);
161 return EBUSY; 162 return EBUSY;
162 } 163 }
163 } 164 }
164 165
165 if (mqsysctl_log != NULL) 166 if (mqsysctl_log != NULL)
166 sysctl_teardown(&mqsysctl_log); 167 sysctl_teardown(&mqsysctl_log);
167 168
168 mutex_destroy(&mqlist_lock); 169 mutex_destroy(&mqlist_lock);
169 pool_cache_destroy(mqmsg_cache); 170 pool_cache_destroy(mqmsg_cache);
170 return 0; 171 return 0;
171} 172}
172 173
173/* 174/*
174 * Module interface. 175 * Module interface.
175 */ 176 */
176static int 177static int
177mqueue_modcmd(modcmd_t cmd, void *arg) 178mqueue_modcmd(modcmd_t cmd, void *arg)
178{ 179{
179 180
180 switch (cmd) { 181 switch (cmd) {
181 case MODULE_CMD_INIT: 182 case MODULE_CMD_INIT:
182 return mqueue_sysinit(); 183 return mqueue_sysinit();
183 case MODULE_CMD_FINI: 184 case MODULE_CMD_FINI:
184 return mqueue_sysfini(true); 185 return mqueue_sysfini(true);
185 default: 186 default:
186 return ENOTTY; 187 return ENOTTY;
187 } 188 }
188} 189}
189 190
190/* 191/*
191 * Free the message. 192 * Free the message.
192 */ 193 */
193static void 194static void
194mqueue_freemsg(struct mq_msg *msg, const size_t size) 195mqueue_freemsg(struct mq_msg *msg, const size_t size)
195{ 196{
196 197
197 if (size > MQ_DEF_MSGSIZE) { 198 if (size > MQ_DEF_MSGSIZE) {
198 kmem_free(msg, size); 199 kmem_free(msg, size);
199 } else { 200 } else {
200 pool_cache_put(mqmsg_cache, msg); 201 pool_cache_put(mqmsg_cache, msg);
201 } 202 }
202} 203}
203 204
204/* 205/*
205 * Destroy the message queue. 206 * Destroy the message queue.
206 */ 207 */
207static void 208static void
208mqueue_destroy(struct mqueue *mq) 209mqueue_destroy(struct mqueue *mq)
209{ 210{
210 struct mq_msg *msg; 211 struct mq_msg *msg;
211 size_t msz; 212 size_t msz;
212 u_int i; 213 u_int i;
213 214
214 /* Note MQ_PQSIZE + 1. */ 215 /* Note MQ_PQSIZE + 1. */
215 for (i = 0; i <= MQ_PQSIZE; i++) { 216 for (i = 0; i <= MQ_PQSIZE; i++) {
216 while ((msg = TAILQ_FIRST(&mq->mq_head[i])) != NULL) { 217 while ((msg = TAILQ_FIRST(&mq->mq_head[i])) != NULL) {
217 TAILQ_REMOVE(&mq->mq_head[i], msg, msg_queue); 218 TAILQ_REMOVE(&mq->mq_head[i], msg, msg_queue);
218 msz = sizeof(struct mq_msg) + msg->msg_len; 219 msz = sizeof(struct mq_msg) + msg->msg_len;
219 mqueue_freemsg(msg, msz); 220 mqueue_freemsg(msg, msz);
220 } 221 }
221 } 222 }
222 if (mq->mq_name) { 223 if (mq->mq_name) {
223 kmem_free(mq->mq_name, MQ_NAMELEN); 224 kmem_free(mq->mq_name, MQ_NAMELEN);
224 } 225 }
225 seldestroy(&mq->mq_rsel); 226 seldestroy(&mq->mq_rsel);
226 seldestroy(&mq->mq_wsel); 227 seldestroy(&mq->mq_wsel);
227 cv_destroy(&mq->mq_send_cv); 228 cv_destroy(&mq->mq_send_cv);
228 cv_destroy(&mq->mq_recv_cv); 229 cv_destroy(&mq->mq_recv_cv);
229 mutex_destroy(&mq->mq_mtx); 230 mutex_destroy(&mq->mq_mtx);
230 kmem_free(mq, sizeof(struct mqueue)); 231 kmem_free(mq, sizeof(struct mqueue));
231} 232}
232 233
233/* 234/*
234 * mqueue_lookup: lookup for file name in general list of message queues. 235 * mqueue_lookup: lookup for file name in general list of message queues.
235 * 236 *
236 * => locks the message queue on success 237 * => locks the message queue on success
237 */ 238 */
238static mqueue_t * 239static mqueue_t *
239mqueue_lookup(const char *name) 240mqueue_lookup(const char *name)
240{ 241{
241 mqueue_t *mq; 242 mqueue_t *mq;
242 243
243 KASSERT(mutex_owned(&mqlist_lock)); 244 KASSERT(mutex_owned(&mqlist_lock));
244 245
245 LIST_FOREACH(mq, &mqueue_head, mq_list) { 246 LIST_FOREACH(mq, &mqueue_head, mq_list) {
246 if (strncmp(mq->mq_name, name, MQ_NAMELEN) == 0) { 247 if (strncmp(mq->mq_name, name, MQ_NAMELEN) == 0) {
247 mutex_enter(&mq->mq_mtx); 248 mutex_enter(&mq->mq_mtx);
248 return mq; 249 return mq;
249 } 250 }
250 } 251 }
251 return NULL; 252 return NULL;
252} 253}
253 254
254/* 255/*
255 * mqueue_get: get the mqueue from the descriptor. 256 * mqueue_get: get the mqueue from the descriptor.
256 * 257 *
257 * => locks the message queue, if found. 258 * => locks the message queue, if found.
258 * => holds a reference on the file descriptor. 259 * => holds a reference on the file descriptor.
259 */ 260 */
260static int 261static int
261mqueue_get(mqd_t mqd, int fflag, mqueue_t **mqret) 262mqueue_get(mqd_t mqd, int fflag, mqueue_t **mqret)
262{ 263{
263 const int fd = (int)mqd; 264 const int fd = (int)mqd;
264 mqueue_t *mq; 265 mqueue_t *mq;
265 file_t *fp; 266 file_t *fp;
266 267
267 fp = fd_getfile(fd); 268 fp = fd_getfile(fd);
268 if (__predict_false(fp == NULL)) { 269 if (__predict_false(fp == NULL)) {
269 return EBADF; 270 return EBADF;
270 } 271 }
271 if (__predict_false(fp->f_type != DTYPE_MQUEUE)) { 272 if (__predict_false(fp->f_type != DTYPE_MQUEUE)) {
272 fd_putfile(fd); 273 fd_putfile(fd);
273 return EBADF; 274 return EBADF;
274 } 275 }
275 if (fflag && (fp->f_flag & fflag) == 0) { 276 if (fflag && (fp->f_flag & fflag) == 0) {
276 fd_putfile(fd); 277 fd_putfile(fd);
277 return EBADF; 278 return EBADF;
278 } 279 }
279 mq = fp->f_data; 280 mq = fp->f_data;
280 mutex_enter(&mq->mq_mtx); 281 mutex_enter(&mq->mq_mtx);
281 282
282 *mqret = mq; 283 *mqret = mq;
283 return 0; 284 return 0;
284} 285}
285 286
286/* 287/*
287 * mqueue_linear_insert: perform linear insert according to the message 288 * mqueue_linear_insert: perform linear insert according to the message
288 * priority into the reserved queue (MQ_PQRESQ). Reserved queue is a 289 * priority into the reserved queue (MQ_PQRESQ). Reserved queue is a
289 * sorted list used only when mq_prio_max is increased via sysctl. 290 * sorted list used only when mq_prio_max is increased via sysctl.
290 */ 291 */
291static inline void 292static inline void
292mqueue_linear_insert(struct mqueue *mq, struct mq_msg *msg) 293mqueue_linear_insert(struct mqueue *mq, struct mq_msg *msg)
293{ 294{
294 struct mq_msg *mit; 295 struct mq_msg *mit;
295 296
296 TAILQ_FOREACH(mit, &mq->mq_head[MQ_PQRESQ], msg_queue) { 297 TAILQ_FOREACH(mit, &mq->mq_head[MQ_PQRESQ], msg_queue) {
297 if (msg->msg_prio > mit->msg_prio) 298 if (msg->msg_prio > mit->msg_prio)
298 break; 299 break;
299 } 300 }
300 if (mit == NULL) { 301 if (mit == NULL) {
301 TAILQ_INSERT_TAIL(&mq->mq_head[MQ_PQRESQ], msg, msg_queue); 302 TAILQ_INSERT_TAIL(&mq->mq_head[MQ_PQRESQ], msg, msg_queue);
302 } else { 303 } else {
303 TAILQ_INSERT_BEFORE(mit, msg, msg_queue); 304 TAILQ_INSERT_BEFORE(mit, msg, msg_queue);
304 } 305 }
305} 306}
306 307
307static int 308static int
308mq_stat_fop(file_t *fp, struct stat *st) 309mq_stat_fop(file_t *fp, struct stat *st)
309{ 310{
310 struct mqueue *mq = fp->f_data; 311 struct mqueue *mq = fp->f_data;
311 312
312 memset(st, 0, sizeof(*st)); 313 memset(st, 0, sizeof(*st));
313 314
314 mutex_enter(&mq->mq_mtx); 315 mutex_enter(&mq->mq_mtx);
315 st->st_mode = mq->mq_mode; 316 st->st_mode = mq->mq_mode;
316 st->st_uid = mq->mq_euid; 317 st->st_uid = mq->mq_euid;
317 st->st_gid = mq->mq_egid; 318 st->st_gid = mq->mq_egid;
318 st->st_atimespec = mq->mq_atime; 319 st->st_atimespec = mq->mq_atime;
319 st->st_mtimespec = mq->mq_mtime; 320 st->st_mtimespec = mq->mq_mtime;
320 st->st_ctimespec = st->st_birthtimespec = mq->mq_btime; 321 st->st_ctimespec = st->st_birthtimespec = mq->mq_btime;
321 st->st_uid = kauth_cred_geteuid(fp->f_cred); 322 st->st_uid = kauth_cred_geteuid(fp->f_cred);
322 st->st_gid = kauth_cred_getegid(fp->f_cred); 323 st->st_gid = kauth_cred_getegid(fp->f_cred);
323 mutex_exit(&mq->mq_mtx); 324 mutex_exit(&mq->mq_mtx);
324 325
325 return 0; 326 return 0;
326} 327}
327 328
328static int 329static int
329mq_poll_fop(file_t *fp, int events) 330mq_poll_fop(file_t *fp, int events)
330{ 331{
331 struct mqueue *mq = fp->f_data; 332 struct mqueue *mq = fp->f_data;
332 struct mq_attr *mqattr; 333 struct mq_attr *mqattr;
333 int revents = 0; 334 int revents = 0;
334 335
335 mutex_enter(&mq->mq_mtx); 336 mutex_enter(&mq->mq_mtx);
336 mqattr = &mq->mq_attrib; 337 mqattr = &mq->mq_attrib;
337 if (events & (POLLIN | POLLRDNORM)) { 338 if (events & (POLLIN | POLLRDNORM)) {
338 /* Ready for receiving, if there are messages in the queue. */ 339 /* Ready for receiving, if there are messages in the queue. */
339 if (mqattr->mq_curmsgs) 340 if (mqattr->mq_curmsgs)
340 revents |= events & (POLLIN | POLLRDNORM); 341 revents |= events & (POLLIN | POLLRDNORM);
341 else 342 else
342 selrecord(curlwp, &mq->mq_rsel); 343 selrecord(curlwp, &mq->mq_rsel);
343 } 344 }
344 if (events & (POLLOUT | POLLWRNORM)) { 345 if (events & (POLLOUT | POLLWRNORM)) {
345 /* Ready for sending, if the message queue is not full. */ 346 /* Ready for sending, if the message queue is not full. */
346 if (mqattr->mq_curmsgs < mqattr->mq_maxmsg) 347 if (mqattr->mq_curmsgs < mqattr->mq_maxmsg)
347 revents |= events & (POLLOUT | POLLWRNORM); 348 revents |= events & (POLLOUT | POLLWRNORM);
348 else 349 else
349 selrecord(curlwp, &mq->mq_wsel); 350 selrecord(curlwp, &mq->mq_wsel);
350 } 351 }
351 mutex_exit(&mq->mq_mtx); 352 mutex_exit(&mq->mq_mtx);
352 353
353 return revents; 354 return revents;
354} 355}
355 356
356static int 357static int
357mq_close_fop(file_t *fp) 358mq_close_fop(file_t *fp)
358{ 359{
359 proc_t *p = curproc; 360 proc_t *p = curproc;
360 mqueue_t *mq = fp->f_data; 361 mqueue_t *mq = fp->f_data;
361 bool destroy = false; 362 bool destroy = false;
362 363
363 mutex_enter(&mq->mq_mtx); 364 mutex_enter(&mq->mq_mtx);
364 KASSERT(mq->mq_refcnt > 0); 365 KASSERT(mq->mq_refcnt > 0);
365 if (--mq->mq_refcnt == 0) { 366 if (--mq->mq_refcnt == 0) {
366 /* Destroy if the last reference and unlinked. */ 367 /* Destroy if the last reference and unlinked. */
367 destroy = (mq->mq_attrib.mq_flags & MQ_UNLINKED) != 0; 368 destroy = (mq->mq_attrib.mq_flags & MQ_UNLINKED) != 0;
368 } 369 }
369 mutex_exit(&mq->mq_mtx); 370 mutex_exit(&mq->mq_mtx);
370 371
371 if (destroy) { 372 if (destroy) {
372 mqueue_destroy(mq); 373 mqueue_destroy(mq);
373 } 374 }
374 atomic_dec_uint(&p->p_mqueue_cnt); 375 atomic_dec_uint(&p->p_mqueue_cnt);
375 return 0; 376 return 0;
376} 377}
377 378
378static int 379static int
379mqueue_access(mqueue_t *mq, int access, kauth_cred_t cred) 380mqueue_access(mqueue_t *mq, int access, kauth_cred_t cred)
380{ 381{
381 mode_t acc_mode = 0; 382 mode_t acc_mode = 0;
382 383
383 /* Note the difference between VREAD/VWRITE and FREAD/FWRITE. */ 384 /* Note the difference between VREAD/VWRITE and FREAD/FWRITE. */
384 if (access & FREAD) { 385 if (access & FREAD) {
385 acc_mode |= VREAD; 386 acc_mode |= VREAD;
386 } 387 }
387 if (access & FWRITE) { 388 if (access & FWRITE) {
388 acc_mode |= VWRITE; 389 acc_mode |= VWRITE;
389 } 390 }
390 if (genfs_can_access(VNON, mq->mq_mode, mq->mq_euid, 391 if (genfs_can_access(VNON, mq->mq_mode, mq->mq_euid,
391 mq->mq_egid, acc_mode, cred)) { 392 mq->mq_egid, acc_mode, cred)) {
392 return EACCES; 393 return EACCES;
393 } 394 }
394 return 0; 395 return 0;
395} 396}
396 397
397static int 398static int
398mqueue_create(lwp_t *l, char *name, struct mq_attr *uattr, mode_t mode, 399mqueue_create(lwp_t *l, char *name, struct mq_attr *uattr, mode_t mode,
399 int oflag, mqueue_t **mqret) 400 int oflag, mqueue_t **mqret)
400{ 401{
401 proc_t *p = l->l_proc; 402 proc_t *p = l->l_proc;
402 struct cwdinfo *cwdi = p->p_cwdi; 403 struct cwdinfo *cwdi = p->p_cwdi;
403 mqueue_t *mq; 404 mqueue_t *mq;
404 struct mq_attr attr; 405 struct mq_attr attr;
405 u_int i; 406 u_int i;
406 407
407 /* Pre-check the limit. */ 408 /* Pre-check the limit. */
408 if (p->p_mqueue_cnt >= mq_open_max) { 409 if (p->p_mqueue_cnt >= mq_open_max) {
409 return EMFILE; 410 return EMFILE;
410 } 411 }
411 412
412 /* Empty name is invalid. */ 413 /* Empty name is invalid. */
413 if (name[0] == '\0') { 414 if (name[0] == '\0') {
414 return EINVAL; 415 return EINVAL;
415 } 416 }
416 417
417 /* Check for mqueue attributes. */ 418 /* Check for mqueue attributes. */
418 if (uattr) { 419 if (uattr) {
419 int error; 420 int error;
420 421
421 error = copyin(uattr, &attr, sizeof(struct mq_attr)); 422 error = copyin(uattr, &attr, sizeof(struct mq_attr));
422 if (error) { 423 if (error) {
423 return error; 424 return error;
424 } 425 }
425 if (attr.mq_maxmsg <= 0 || attr.mq_maxmsg > mq_max_maxmsg || 426 if (attr.mq_maxmsg <= 0 || attr.mq_maxmsg > mq_max_maxmsg ||
426 attr.mq_msgsize <= 0 || attr.mq_msgsize > mq_max_msgsize) { 427 attr.mq_msgsize <= 0 || attr.mq_msgsize > mq_max_msgsize) {
427 return EINVAL; 428 return EINVAL;
428 } 429 }
429 attr.mq_curmsgs = 0; 430 attr.mq_curmsgs = 0;
430 } else { 431 } else {
431 memset(&attr, 0, sizeof(struct mq_attr)); 432 memset(&attr, 0, sizeof(struct mq_attr));
432 attr.mq_maxmsg = mq_def_maxmsg; 433 attr.mq_maxmsg = mq_def_maxmsg;
433 attr.mq_msgsize = MQ_DEF_MSGSIZE - sizeof(struct mq_msg); 434 attr.mq_msgsize = MQ_DEF_MSGSIZE - sizeof(struct mq_msg);
434 } 435 }
435 436
436 /* 437 /*
437 * Allocate new message queue, initialize data structures, copy the 438 * Allocate new message queue, initialize data structures, copy the
438 * name attributes. Note that the initial reference is set here. 439 * name attributes. Note that the initial reference is set here.
439 */ 440 */
440 mq = kmem_zalloc(sizeof(mqueue_t), KM_SLEEP); 441 mq = kmem_zalloc(sizeof(mqueue_t), KM_SLEEP);
441 442
442 mutex_init(&mq->mq_mtx, MUTEX_DEFAULT, IPL_NONE); 443 mutex_init(&mq->mq_mtx, MUTEX_DEFAULT, IPL_NONE);
443 cv_init(&mq->mq_send_cv, "mqsendcv"); 444 cv_init(&mq->mq_send_cv, "mqsendcv");
444 cv_init(&mq->mq_recv_cv, "mqrecvcv"); 445 cv_init(&mq->mq_recv_cv, "mqrecvcv");
445 for (i = 0; i < (MQ_PQSIZE + 1); i++) { 446 for (i = 0; i < (MQ_PQSIZE + 1); i++) {
446 TAILQ_INIT(&mq->mq_head[i]); 447 TAILQ_INIT(&mq->mq_head[i]);
447 } 448 }
448 selinit(&mq->mq_rsel); 449 selinit(&mq->mq_rsel);
449 selinit(&mq->mq_wsel); 450 selinit(&mq->mq_wsel);
450 mq->mq_name = name; 451 mq->mq_name = name;
451 mq->mq_refcnt = 1; 452 mq->mq_refcnt = 1;
452 453
453 memcpy(&mq->mq_attrib, &attr, sizeof(struct mq_attr)); 454 memcpy(&mq->mq_attrib, &attr, sizeof(struct mq_attr));
454 455
455 CTASSERT((O_MASK & (MQ_UNLINKED | MQ_RECEIVE)) == 0); 456 CTASSERT((O_MASK & (MQ_UNLINKED | MQ_RECEIVE)) == 0);
456 mq->mq_attrib.mq_flags = (O_MASK & oflag); 457 mq->mq_attrib.mq_flags = (O_MASK & oflag);
457 458
458 /* Store mode and effective UID with GID. */ 459 /* Store mode and effective UID with GID. */
459 mq->mq_mode = ((mode & ~cwdi->cwdi_cmask) & ALLPERMS) & ~S_ISTXT; 460 mq->mq_mode = ((mode & ~cwdi->cwdi_cmask) & ALLPERMS) & ~S_ISTXT;
460 mq->mq_euid = kauth_cred_geteuid(l->l_cred); 461 mq->mq_euid = kauth_cred_geteuid(l->l_cred);
461 mq->mq_egid = kauth_cred_getegid(l->l_cred); 462 mq->mq_egid = kauth_cred_getegid(l->l_cred);
462 463
463 *mqret = mq; 464 *mqret = mq;
464 return 0; 465 return 0;
465} 466}
466 467
467/* 468/*
468 * General mqueue system calls. 469 * General mqueue system calls.
469 */ 470 */
470 471
471int 472int
472sys_mq_open(struct lwp *l, const struct sys_mq_open_args *uap, 473sys_mq_open(struct lwp *l, const struct sys_mq_open_args *uap,
473 register_t *retval) 474 register_t *retval)
474{ 475{
475 /* { 476 /* {
476 syscallarg(const char *) name; 477 syscallarg(const char *) name;
477 syscallarg(int) oflag; 478 syscallarg(int) oflag;
478 syscallarg(mode_t) mode; 479 syscallarg(mode_t) mode;
479 syscallarg(struct mq_attr) attr; 480 syscallarg(struct mq_attr) attr;
480 } */ 481 } */
481 struct proc *p = l->l_proc; 482 struct proc *p = l->l_proc;
482 struct mqueue *mq, *mq_new = NULL; 483 struct mqueue *mq, *mq_new = NULL;
483 int mqd, error, oflag = SCARG(uap, oflag); 484 int mqd, error, oflag = SCARG(uap, oflag);
484 file_t *fp; 485 file_t *fp;
485 char *name; 486 char *name;
486 487
487 /* Get the name from the user-space. */ 488 /* Get the name from the user-space. */
488 name = kmem_alloc(MQ_NAMELEN, KM_SLEEP); 489 name = kmem_alloc(MQ_NAMELEN, KM_SLEEP);
489 error = copyinstr(SCARG(uap, name), name, MQ_NAMELEN - 1, NULL); 490 error = copyinstr(SCARG(uap, name), name, MQ_NAMELEN - 1, NULL);
490 if (error) { 491 if (error) {
491 kmem_free(name, MQ_NAMELEN); 492 kmem_free(name, MQ_NAMELEN);
492 return error; 493 return error;
493 } 494 }
494 495
495 /* Allocate file structure and descriptor. */ 496 /* Allocate file structure and descriptor. */
496 error = fd_allocfile(&fp, &mqd); 497 error = fd_allocfile(&fp, &mqd);
497 if (error) { 498 if (error) {
498 kmem_free(name, MQ_NAMELEN); 499 kmem_free(name, MQ_NAMELEN);
499 return error; 500 return error;
500 } 501 }
501 fp->f_type = DTYPE_MQUEUE; 502 fp->f_type = DTYPE_MQUEUE;
502 fp->f_flag = FFLAGS(oflag) & (FREAD | FWRITE); 503 fp->f_flag = FFLAGS(oflag) & (FREAD | FWRITE);
503 fp->f_ops = &mqops; 504 fp->f_ops = &mqops;
504 505
505 if (oflag & O_CREAT) { 506 if (oflag & O_CREAT) {
506 /* Create a new message queue. */ 507 /* Create a new message queue. */
507 error = mqueue_create(l, name, SCARG(uap, attr), 508 error = mqueue_create(l, name, SCARG(uap, attr),
508 SCARG(uap, mode), oflag, &mq_new); 509 SCARG(uap, mode), oflag, &mq_new);
509 if (error) { 510 if (error) {
510 goto err; 511 goto err;
511 } 512 }
512 KASSERT(mq_new != NULL); 513 KASSERT(mq_new != NULL);
513 } 514 }
514 515
515 /* Lookup for a message queue with such name. */ 516 /* Lookup for a message queue with such name. */
516 mutex_enter(&mqlist_lock); 517 mutex_enter(&mqlist_lock);
517 mq = mqueue_lookup(name); 518 mq = mqueue_lookup(name);
518 if (mq) { 519 if (mq) {
519 KASSERT(mutex_owned(&mq->mq_mtx)); 520 KASSERT(mutex_owned(&mq->mq_mtx));
520 mutex_exit(&mqlist_lock); 521 mutex_exit(&mqlist_lock);
521 522
522 /* Check for exclusive create. */ 523 /* Check for exclusive create. */
523 if (oflag & O_EXCL) { 524 if (oflag & O_EXCL) {
524 mutex_exit(&mq->mq_mtx); 525 mutex_exit(&mq->mq_mtx);
525 error = EEXIST; 526 error = EEXIST;
526 goto err; 527 goto err;
527 } 528 }
528 529
529 /* Verify permissions. */ 530 /* Verify permissions. */
530 if (mqueue_access(mq, fp->f_flag, l->l_cred) != 0) { 531 if (mqueue_access(mq, fp->f_flag, l->l_cred) != 0) {
531 mutex_exit(&mq->mq_mtx); 532 mutex_exit(&mq->mq_mtx);
532 error = EACCES; 533 error = EACCES;
533 goto err; 534 goto err;
534 } 535 }
535 536
536 /* If we have the access, add a new reference. */ 537 /* If we have the access, add a new reference. */
537 mq->mq_refcnt++; 538 mq->mq_refcnt++;
538 mutex_exit(&mq->mq_mtx); 539 mutex_exit(&mq->mq_mtx);
539 } else { 540 } else {
540 /* Fail if not found and not creating. */ 541 /* Fail if not found and not creating. */
541 if ((oflag & O_CREAT) == 0) { 542 if ((oflag & O_CREAT) == 0) {
542 mutex_exit(&mqlist_lock); 543 mutex_exit(&mqlist_lock);
543 KASSERT(mq_new == NULL); 544 KASSERT(mq_new == NULL);
544 error = ENOENT; 545 error = ENOENT;
545 goto err; 546 goto err;
546 } 547 }
547 548
548 /* Account and check for the limit. */ 549 /* Account and check for the limit. */
549 if (atomic_inc_uint_nv(&p->p_mqueue_cnt) > mq_open_max) { 550 if (atomic_inc_uint_nv(&p->p_mqueue_cnt) > mq_open_max) {
550 mutex_exit(&mqlist_lock); 551 mutex_exit(&mqlist_lock);
551 atomic_dec_uint(&p->p_mqueue_cnt); 552 atomic_dec_uint(&p->p_mqueue_cnt);
552 error = EMFILE; 553 error = EMFILE;
553 goto err; 554 goto err;
554 } 555 }
555 556
556 /* Initial timestamps. */ 557 /* Initial timestamps. */
557 mq = mq_new; 558 mq = mq_new;
558 getnanotime(&mq->mq_btime); 559 getnanotime(&mq->mq_btime);
559 mq->mq_atime = mq->mq_mtime = mq->mq_btime; 560 mq->mq_atime = mq->mq_mtime = mq->mq_btime;
560 561
561 /* 562 /*
562 * Finally, insert message queue into the list. 563 * Finally, insert message queue into the list.
563 * Note: it already has the initial reference. 564 * Note: it already has the initial reference.
564 */ 565 */
565 LIST_INSERT_HEAD(&mqueue_head, mq, mq_list); 566 LIST_INSERT_HEAD(&mqueue_head, mq, mq_list);
566 mutex_exit(&mqlist_lock); 567 mutex_exit(&mqlist_lock);
567 568
568 mq_new = NULL; 569 mq_new = NULL;
569 name = NULL; 570 name = NULL;
570 } 571 }
571 KASSERT(mq != NULL); 572 KASSERT(mq != NULL);
572 fp->f_data = mq; 573 fp->f_data = mq;
573 fd_affix(p, fp, mqd); 574 fd_affix(p, fp, mqd);
574 *retval = mqd; 575 *retval = mqd;
575err: 576err:
576 if (error) { 577 if (error) {
577 fd_abort(p, fp, mqd); 578 fd_abort(p, fp, mqd);
578 } 579 }
579 if (mq_new) { 580 if (mq_new) {
580 /* Note: will free the 'name'. */ 581 /* Note: will free the 'name'. */
581 mqueue_destroy(mq_new); 582 mqueue_destroy(mq_new);
582 } else if (name) { 583 } else if (name) {
583 kmem_free(name, MQ_NAMELEN); 584 kmem_free(name, MQ_NAMELEN);
584 } 585 }
585 return error; 586 return error;
586} 587}
587 588
588int 589int
589sys_mq_close(struct lwp *l, const struct sys_mq_close_args *uap, 590sys_mq_close(struct lwp *l, const struct sys_mq_close_args *uap,
590 register_t *retval) 591 register_t *retval)
591{ 592{
592 593
593 return sys_close(l, (const void *)uap, retval); 594 return sys_close(l, (const void *)uap, retval);
594} 595}
595 596
596/* 597/*
597 * Primary mq_recv1() function. 598 * Primary mq_recv1() function.
598 */ 599 */
599int 600int
600mq_recv1(mqd_t mqdes, void *msg_ptr, size_t msg_len, u_int *msg_prio, 601mq_recv1(mqd_t mqdes, void *msg_ptr, size_t msg_len, u_int *msg_prio,
601 struct timespec *ts, ssize_t *mlen) 602 struct timespec *ts, ssize_t *mlen)
602{ 603{
603 struct mqueue *mq; 604 struct mqueue *mq;
604 struct mq_msg *msg = NULL; 605 struct mq_msg *msg = NULL;
605 struct mq_attr *mqattr; 606 struct mq_attr *mqattr;
606 u_int idx; 607 u_int idx;
607 int error; 608 int error;
608 609
609 error = mqueue_get(mqdes, FREAD, &mq); 610 error = mqueue_get(mqdes, FREAD, &mq);
610 if (error) { 611 if (error) {
611 return error; 612 return error;
612 } 613 }
613 getnanotime(&mq->mq_atime); 614 getnanotime(&mq->mq_atime);
614 mqattr = &mq->mq_attrib; 615 mqattr = &mq->mq_attrib;
615 616
616 /* Check the message size limits */ 617 /* Check the message size limits */
617 if (msg_len < mqattr->mq_msgsize) { 618 if (msg_len < mqattr->mq_msgsize) {
618 error = EMSGSIZE; 619 error = EMSGSIZE;
619 goto error; 620 goto error;
620 } 621 }
621 622
622 /* Check if queue is empty */ 623 /* Check if queue is empty */
623 while (mqattr->mq_curmsgs == 0) { 624 while (mqattr->mq_curmsgs == 0) {
624 int t; 625 int t;
625 626
626 if (mqattr->mq_flags & O_NONBLOCK) { 627 if (mqattr->mq_flags & O_NONBLOCK) {
627 error = EAGAIN; 628 error = EAGAIN;
628 goto error; 629 goto error;
629 } 630 }
630 if (ts) { 631 if (ts) {
631 error = abstimeout2timo(ts, &t); 632 error = abstimeout2timo(ts, &t);
632 if (error) 633 if (error)
633 goto error; 634 goto error;
634 } else 635 } else
635 t = 0; 636 t = 0;
636 /* 637 /*
637 * Block until someone sends the message. 638 * Block until someone sends the message.
638 * While doing this, notification should not be sent. 639 * While doing this, notification should not be sent.
639 */ 640 */
640 mqattr->mq_flags |= MQ_RECEIVE; 641 mqattr->mq_flags |= MQ_RECEIVE;
641 error = cv_timedwait_sig(&mq->mq_send_cv, &mq->mq_mtx, t); 642 error = cv_timedwait_sig(&mq->mq_send_cv, &mq->mq_mtx, t);
642 mqattr->mq_flags &= ~MQ_RECEIVE; 643 mqattr->mq_flags &= ~MQ_RECEIVE;
643 if (error || (mqattr->mq_flags & MQ_UNLINKED)) { 644 if (error || (mqattr->mq_flags & MQ_UNLINKED)) {
644 error = (error == EWOULDBLOCK) ? ETIMEDOUT : EINTR; 645 error = (error == EWOULDBLOCK) ? ETIMEDOUT : EINTR;
645 goto error; 646 goto error;
646 } 647 }
647 } 648 }
648 649
649 /* 650 /*
650 * Find the highest priority message, and remove it from the queue. 651 * Find the highest priority message, and remove it from the queue.
651 * At first, reserved queue is checked, bitmap is next. 652 * At first, reserved queue is checked, bitmap is next.
652 */ 653 */
653 msg = TAILQ_FIRST(&mq->mq_head[MQ_PQRESQ]); 654 msg = TAILQ_FIRST(&mq->mq_head[MQ_PQRESQ]);
654 if (__predict_true(msg == NULL)) { 655 if (__predict_true(msg == NULL)) {
655 idx = ffs(mq->mq_bitmap); 656 idx = ffs(mq->mq_bitmap);
656 msg = TAILQ_FIRST(&mq->mq_head[idx]); 657 msg = TAILQ_FIRST(&mq->mq_head[idx]);
657 KASSERT(msg != NULL); 658 KASSERT(msg != NULL);
658 } else { 659 } else {
659 idx = MQ_PQRESQ; 660 idx = MQ_PQRESQ;
660 } 661 }
661 TAILQ_REMOVE(&mq->mq_head[idx], msg, msg_queue); 662 TAILQ_REMOVE(&mq->mq_head[idx], msg, msg_queue);
662 663
663 /* Unmark the bit, if last message. */ 664 /* Unmark the bit, if last message. */
664 if (__predict_true(idx) && TAILQ_EMPTY(&mq->mq_head[idx])) { 665 if (__predict_true(idx) && TAILQ_EMPTY(&mq->mq_head[idx])) {
665 KASSERT((MQ_PQSIZE - idx) == msg->msg_prio); 666 KASSERT((MQ_PQSIZE - idx) == msg->msg_prio);
666 mq->mq_bitmap &= ~(1 << --idx); 667 mq->mq_bitmap &= ~(1 << --idx);
667 } 668 }
668 669
669 /* Decrement the counter and signal waiter, if any */ 670 /* Decrement the counter and signal waiter, if any */
670 mqattr->mq_curmsgs--; 671 mqattr->mq_curmsgs--;
671 cv_signal(&mq->mq_recv_cv); 672 cv_signal(&mq->mq_recv_cv);
672 673
673 /* Ready for sending now */ 674 /* Ready for sending now */
674 selnotify(&mq->mq_wsel, POLLOUT | POLLWRNORM, 0); 675 selnotify(&mq->mq_wsel, POLLOUT | POLLWRNORM, 0);
675error: 676error:
676 mutex_exit(&mq->mq_mtx); 677 mutex_exit(&mq->mq_mtx);
677 fd_putfile((int)mqdes); 678 fd_putfile((int)mqdes);
678 if (error) 679 if (error)
679 return error; 680 return error;
680 681
681 /* 682 /*
682 * Copy the data to the user-space. 683 * Copy the data to the user-space.
683 * Note: According to POSIX, no message should be removed from the 684 * Note: According to POSIX, no message should be removed from the
684 * queue in case of fail - this would be violated. 685 * queue in case of fail - this would be violated.
685 */ 686 */
686 *mlen = msg->msg_len; 687 *mlen = msg->msg_len;
687 error = copyout(msg->msg_ptr, msg_ptr, msg->msg_len); 688 error = copyout(msg->msg_ptr, msg_ptr, msg->msg_len);
688 if (error == 0 && msg_prio) 689 if (error == 0 && msg_prio)
689 error = copyout(&msg->msg_prio, msg_prio, sizeof(unsigned)); 690 error = copyout(&msg->msg_prio, msg_prio, sizeof(unsigned));
690 mqueue_freemsg(msg, sizeof(struct mq_msg) + msg->msg_len); 691 mqueue_freemsg(msg, sizeof(struct mq_msg) + msg->msg_len);
691 692
692 return error; 693 return error;
693} 694}
694 695
695int 696int
696sys_mq_receive(struct lwp *l, const struct sys_mq_receive_args *uap, 697sys_mq_receive(struct lwp *l, const struct sys_mq_receive_args *uap,
697 register_t *retval) 698 register_t *retval)
698{ 699{
699 /* { 700 /* {
700 syscallarg(mqd_t) mqdes; 701 syscallarg(mqd_t) mqdes;
701 syscallarg(char *) msg_ptr; 702 syscallarg(char *) msg_ptr;
702 syscallarg(size_t) msg_len; 703 syscallarg(size_t) msg_len;
703 syscallarg(unsigned *) msg_prio; 704 syscallarg(unsigned *) msg_prio;
704 } */ 705 } */
705 ssize_t mlen; 706 ssize_t mlen;
706 int error; 707 int error;
707 708
708 error = mq_recv1(SCARG(uap, mqdes), SCARG(uap, msg_ptr), 709 error = mq_recv1(SCARG(uap, mqdes), SCARG(uap, msg_ptr),
709 SCARG(uap, msg_len), SCARG(uap, msg_prio), NULL, &mlen); 710 SCARG(uap, msg_len), SCARG(uap, msg_prio), NULL, &mlen);
710 if (error == 0) 711 if (error == 0)
711 *retval = mlen; 712 *retval = mlen;
712 713
713 return error; 714 return error;
714} 715}
715 716
716int 717int
717sys___mq_timedreceive50(struct lwp *l, 718sys___mq_timedreceive50(struct lwp *l,
718 const struct sys___mq_timedreceive50_args *uap, register_t *retval) 719 const struct sys___mq_timedreceive50_args *uap, register_t *retval)
719{ 720{
720 /* { 721 /* {
721 syscallarg(mqd_t) mqdes; 722 syscallarg(mqd_t) mqdes;
722 syscallarg(char *) msg_ptr; 723 syscallarg(char *) msg_ptr;
723 syscallarg(size_t) msg_len; 724 syscallarg(size_t) msg_len;
724 syscallarg(unsigned *) msg_prio; 725 syscallarg(unsigned *) msg_prio;
725 syscallarg(const struct timespec *) abs_timeout; 726 syscallarg(const struct timespec *) abs_timeout;
726 } */ 727 } */
727 struct timespec ts, *tsp; 728 struct timespec ts, *tsp;
728 ssize_t mlen; 729 ssize_t mlen;
729 int error; 730 int error;
730 731
731 /* Get and convert time value */ 732 /* Get and convert time value */
732 if (SCARG(uap, abs_timeout)) { 733 if (SCARG(uap, abs_timeout)) {
733 error = copyin(SCARG(uap, abs_timeout), &ts, sizeof(ts)); 734 error = copyin(SCARG(uap, abs_timeout), &ts, sizeof(ts));
734 if (error) 735 if (error)
735 return error; 736 return error;
736 tsp = &ts; 737 tsp = &ts;
737 } else { 738 } else {
738 tsp = NULL; 739 tsp = NULL;
739 } 740 }
740 741
741 error = mq_recv1(SCARG(uap, mqdes), SCARG(uap, msg_ptr), 742 error = mq_recv1(SCARG(uap, mqdes), SCARG(uap, msg_ptr),
742 SCARG(uap, msg_len), SCARG(uap, msg_prio), tsp, &mlen); 743 SCARG(uap, msg_len), SCARG(uap, msg_prio), tsp, &mlen);
743 if (error == 0) 744 if (error == 0)
744 *retval = mlen; 745 *retval = mlen;
745 746
746 return error; 747 return error;
747} 748}
748 749
749/* 750/*
750 * Primary mq_send1() function. 751 * Primary mq_send1() function.
751 */ 752 */
752int 753int
753mq_send1(mqd_t mqdes, const char *msg_ptr, size_t msg_len, u_int msg_prio, 754mq_send1(mqd_t mqdes, const char *msg_ptr, size_t msg_len, u_int msg_prio,
754 struct timespec *ts) 755 struct timespec *ts)
755{ 756{
756 struct mqueue *mq; 757 struct mqueue *mq;
757 struct mq_msg *msg; 758 struct mq_msg *msg;
758 struct mq_attr *mqattr; 759 struct mq_attr *mqattr;
759 struct proc *notify = NULL; 760 struct proc *notify = NULL;
760 ksiginfo_t ksi; 761 ksiginfo_t ksi;
761 size_t size; 762 size_t size;
762 int error; 763 int error;
763 764
764 /* Check the priority range */ 765 /* Check the priority range */
765 if (msg_prio >= mq_prio_max) 766 if (msg_prio >= mq_prio_max)
766 return EINVAL; 767 return EINVAL;
767 768
768 /* Allocate a new message */ 769 /* Allocate a new message */
769 size = sizeof(struct mq_msg) + msg_len; 770 size = sizeof(struct mq_msg) + msg_len;
770 if (size > mq_max_msgsize) 771 if (size > mq_max_msgsize)
771 return EMSGSIZE; 772 return EMSGSIZE;
772 773
773 if (size > MQ_DEF_MSGSIZE) { 774 if (size > MQ_DEF_MSGSIZE) {
774 msg = kmem_alloc(size, KM_SLEEP); 775 msg = kmem_alloc(size, KM_SLEEP);
775 } else { 776 } else {
776 msg = pool_cache_get(mqmsg_cache, PR_WAITOK); 777 msg = pool_cache_get(mqmsg_cache, PR_WAITOK);
777 } 778 }
778 779
779 /* Get the data from user-space */ 780 /* Get the data from user-space */
780 error = copyin(msg_ptr, msg->msg_ptr, msg_len); 781 error = copyin(msg_ptr, msg->msg_ptr, msg_len);
781 if (error) { 782 if (error) {
782 mqueue_freemsg(msg, size); 783 mqueue_freemsg(msg, size);
783 return error; 784 return error;
784 } 785 }
785 msg->msg_len = msg_len; 786 msg->msg_len = msg_len;
786 msg->msg_prio = msg_prio; 787 msg->msg_prio = msg_prio;
787 788
788 error = mqueue_get(mqdes, FWRITE, &mq); 789 error = mqueue_get(mqdes, FWRITE, &mq);
789 if (error) { 790 if (error) {
790 mqueue_freemsg(msg, size); 791 mqueue_freemsg(msg, size);
791 return error; 792 return error;
792 } 793 }
793 getnanotime(&mq->mq_mtime); 794 getnanotime(&mq->mq_mtime);
794 mqattr = &mq->mq_attrib; 795 mqattr = &mq->mq_attrib;
795 796
796 /* Check the message size limit */ 797 /* Check the message size limit */
797 if (msg_len <= 0 || msg_len > mqattr->mq_msgsize) { 798 if (msg_len <= 0 || msg_len > mqattr->mq_msgsize) {
798 error = EMSGSIZE; 799 error = EMSGSIZE;
799 goto error; 800 goto error;
800 } 801 }
801 802
802 /* Check if queue is full */ 803 /* Check if queue is full */
803 while (mqattr->mq_curmsgs >= mqattr->mq_maxmsg) { 804 while (mqattr->mq_curmsgs >= mqattr->mq_maxmsg) {
804 int t; 805 int t;
805 806
806 if (mqattr->mq_flags & O_NONBLOCK) { 807 if (mqattr->mq_flags & O_NONBLOCK) {
807 error = EAGAIN; 808 error = EAGAIN;
808 goto error; 809 goto error;
809 } 810 }
810 if (ts) { 811 if (ts) {
811 error = abstimeout2timo(ts, &t); 812 error = abstimeout2timo(ts, &t);
812 if (error) 813 if (error)
813 goto error; 814 goto error;
814 } else 815 } else
815 t = 0; 816 t = 0;
816 /* Block until queue becomes available */ 817 /* Block until queue becomes available */
817 error = cv_timedwait_sig(&mq->mq_recv_cv, &mq->mq_mtx, t); 818 error = cv_timedwait_sig(&mq->mq_recv_cv, &mq->mq_mtx, t);
818 if (error || (mqattr->mq_flags & MQ_UNLINKED)) { 819 if (error || (mqattr->mq_flags & MQ_UNLINKED)) {
819 error = (error == EWOULDBLOCK) ? ETIMEDOUT : error; 820 error = (error == EWOULDBLOCK) ? ETIMEDOUT : error;
820 goto error; 821 goto error;
821 } 822 }
822 } 823 }
823 KASSERT(mqattr->mq_curmsgs < mqattr->mq_maxmsg); 824 KASSERT(mqattr->mq_curmsgs < mqattr->mq_maxmsg);
824 825
825 /* 826 /*
826 * Insert message into the queue, according to the priority. 827 * Insert message into the queue, according to the priority.
827 * Note the difference between index and priority. 828 * Note the difference between index and priority.
828 */ 829 */
829 if (__predict_true(msg_prio < MQ_PQSIZE)) { 830 if (__predict_true(msg_prio < MQ_PQSIZE)) {
830 u_int idx = MQ_PQSIZE - msg_prio; 831 u_int idx = MQ_PQSIZE - msg_prio;
831 832
832 KASSERT(idx != MQ_PQRESQ); 833 KASSERT(idx != MQ_PQRESQ);
833 TAILQ_INSERT_TAIL(&mq->mq_head[idx], msg, msg_queue); 834 TAILQ_INSERT_TAIL(&mq->mq_head[idx], msg, msg_queue);
834 mq->mq_bitmap |= (1 << --idx); 835 mq->mq_bitmap |= (1 << --idx);
835 } else { 836 } else {
836 mqueue_linear_insert(mq, msg); 837 mqueue_linear_insert(mq, msg);
837 } 838 }
838 839
839 /* Check for the notify */ 840 /* Check for the notify */
840 if (mqattr->mq_curmsgs == 0 && mq->mq_notify_proc && 841 if (mqattr->mq_curmsgs == 0 && mq->mq_notify_proc &&
841 (mqattr->mq_flags & MQ_RECEIVE) == 0 && 842 (mqattr->mq_flags & MQ_RECEIVE) == 0 &&
842 mq->mq_sig_notify.sigev_notify == SIGEV_SIGNAL) { 843 mq->mq_sig_notify.sigev_notify == SIGEV_SIGNAL) {
843 /* Initialize the signal */ 844 /* Initialize the signal */
844 KSI_INIT(&ksi); 845 KSI_INIT(&ksi);
845 ksi.ksi_signo = mq->mq_sig_notify.sigev_signo; 846 ksi.ksi_signo = mq->mq_sig_notify.sigev_signo;
846 ksi.ksi_code = SI_MESGQ; 847 ksi.ksi_code = SI_MESGQ;
847 ksi.ksi_value = mq->mq_sig_notify.sigev_value; 848 ksi.ksi_value = mq->mq_sig_notify.sigev_value;
848 /* Unregister the process */ 849 /* Unregister the process */
849 notify = mq->mq_notify_proc; 850 notify = mq->mq_notify_proc;
850 mq->mq_notify_proc = NULL; 851 mq->mq_notify_proc = NULL;
851 } 852 }
852 853
853 /* Increment the counter and signal waiter, if any */ 854 /* Increment the counter and signal waiter, if any */
854 mqattr->mq_curmsgs++; 855 mqattr->mq_curmsgs++;
855 cv_signal(&mq->mq_send_cv); 856 cv_signal(&mq->mq_send_cv);
856 857
857 /* Ready for receiving now */ 858 /* Ready for receiving now */
858 selnotify(&mq->mq_rsel, POLLIN | POLLRDNORM, 0); 859 selnotify(&mq->mq_rsel, POLLIN | POLLRDNORM, 0);
859error: 860error:
860 mutex_exit(&mq->mq_mtx); 861 mutex_exit(&mq->mq_mtx);
861 fd_putfile((int)mqdes); 862 fd_putfile((int)mqdes);
862 863
863 if (error) { 864 if (error) {
864 mqueue_freemsg(msg, size); 865 mqueue_freemsg(msg, size);
865 } else if (notify) { 866 } else if (notify) {
866 /* Send the notify, if needed */ 867 /* Send the notify, if needed */
867 mutex_enter(proc_lock); 868 mutex_enter(proc_lock);
868 kpsignal(notify, &ksi, NULL); 869 kpsignal(notify, &ksi, NULL);
869 mutex_exit(proc_lock); 870 mutex_exit(proc_lock);
870 } 871 }
871 return error; 872 return error;
872} 873}
873 874
874int 875int
875sys_mq_send(struct lwp *l, const struct sys_mq_send_args *uap, 876sys_mq_send(struct lwp *l, const struct sys_mq_send_args *uap,
876 register_t *retval) 877 register_t *retval)
877{ 878{
878 /* { 879 /* {
879 syscallarg(mqd_t) mqdes; 880 syscallarg(mqd_t) mqdes;
880 syscallarg(const char *) msg_ptr; 881 syscallarg(const char *) msg_ptr;
881 syscallarg(size_t) msg_len; 882 syscallarg(size_t) msg_len;
882 syscallarg(unsigned) msg_prio; 883 syscallarg(unsigned) msg_prio;
883 } */ 884 } */
884 885
885 return mq_send1(SCARG(uap, mqdes), SCARG(uap, msg_ptr), 886 return mq_send1(SCARG(uap, mqdes), SCARG(uap, msg_ptr),
886 SCARG(uap, msg_len), SCARG(uap, msg_prio), NULL); 887 SCARG(uap, msg_len), SCARG(uap, msg_prio), NULL);
887} 888}
888 889
889int 890int
890sys___mq_timedsend50(struct lwp *l, const struct sys___mq_timedsend50_args *uap, 891sys___mq_timedsend50(struct lwp *l, const struct sys___mq_timedsend50_args *uap,
891 register_t *retval) 892 register_t *retval)
892{ 893{
893 /* { 894 /* {
894 syscallarg(mqd_t) mqdes; 895 syscallarg(mqd_t) mqdes;
895 syscallarg(const char *) msg_ptr; 896 syscallarg(const char *) msg_ptr;
896 syscallarg(size_t) msg_len; 897 syscallarg(size_t) msg_len;
897 syscallarg(unsigned) msg_prio; 898 syscallarg(unsigned) msg_prio;
898 syscallarg(const struct timespec *) abs_timeout; 899 syscallarg(const struct timespec *) abs_timeout;
899 } */ 900 } */
900 struct timespec ts, *tsp; 901 struct timespec ts, *tsp;
901 int error; 902 int error;
902 903
903 /* Get and convert time value */ 904 /* Get and convert time value */
904 if (SCARG(uap, abs_timeout)) { 905 if (SCARG(uap, abs_timeout)) {
905 error = copyin(SCARG(uap, abs_timeout), &ts, sizeof(ts)); 906 error = copyin(SCARG(uap, abs_timeout), &ts, sizeof(ts));
906 if (error) 907 if (error)
907 return error; 908 return error;
908 tsp = &ts; 909 tsp = &ts;
909 } else { 910 } else {
910 tsp = NULL; 911 tsp = NULL;
911 } 912 }
912 913
913 return mq_send1(SCARG(uap, mqdes), SCARG(uap, msg_ptr), 914 return mq_send1(SCARG(uap, mqdes), SCARG(uap, msg_ptr),
914 SCARG(uap, msg_len), SCARG(uap, msg_prio), tsp); 915 SCARG(uap, msg_len), SCARG(uap, msg_prio), tsp);
915} 916}
916 917
917int 918int
918sys_mq_notify(struct lwp *l, const struct sys_mq_notify_args *uap, 919sys_mq_notify(struct lwp *l, const struct sys_mq_notify_args *uap,
919 register_t *retval) 920 register_t *retval)
920{ 921{
921 /* { 922 /* {
922 syscallarg(mqd_t) mqdes; 923 syscallarg(mqd_t) mqdes;
923 syscallarg(const struct sigevent *) notification; 924 syscallarg(const struct sigevent *) notification;
924 } */ 925 } */
925 struct mqueue *mq; 926 struct mqueue *mq;
926 struct sigevent sig; 927 struct sigevent sig;
927 int error; 928 int error;
928 929
929 if (SCARG(uap, notification)) { 930 if (SCARG(uap, notification)) {
930 /* Get the signal from user-space */ 931 /* Get the signal from user-space */
931 error = copyin(SCARG(uap, notification), &sig, 932 error = copyin(SCARG(uap, notification), &sig,
932 sizeof(struct sigevent)); 933 sizeof(struct sigevent));
933 if (error) 934 if (error)
934 return error; 935 return error;
935 if (sig.sigev_notify == SIGEV_SIGNAL && 936 if (sig.sigev_notify == SIGEV_SIGNAL &&
936 (sig.sigev_signo <=0 || sig.sigev_signo >= NSIG)) 937 (sig.sigev_signo <=0 || sig.sigev_signo >= NSIG))
937 return EINVAL; 938 return EINVAL;
938 } 939 }
939 940
940 error = mqueue_get(SCARG(uap, mqdes), 0, &mq); 941 error = mqueue_get(SCARG(uap, mqdes), 0, &mq);
941 if (error) { 942 if (error) {
942 return error; 943 return error;
943 } 944 }
944 if (SCARG(uap, notification)) { 945 if (SCARG(uap, notification)) {
945 /* Register notification: set the signal and target process */ 946 /* Register notification: set the signal and target process */
946 if (mq->mq_notify_proc == NULL) { 947 if (mq->mq_notify_proc == NULL) {
947 memcpy(&mq->mq_sig_notify, &sig, 948 memcpy(&mq->mq_sig_notify, &sig,
948 sizeof(struct sigevent)); 949 sizeof(struct sigevent));
949 mq->mq_notify_proc = l->l_proc; 950 mq->mq_notify_proc = l->l_proc;
950 } else { 951 } else {
951 /* Fail if someone else already registered */ 952 /* Fail if someone else already registered */
952 error = EBUSY; 953 error = EBUSY;
953 } 954 }
954 } else { 955 } else {
955 /* Unregister the notification */ 956 /* Unregister the notification */
956 mq->mq_notify_proc = NULL; 957 mq->mq_notify_proc = NULL;
957 } 958 }
958 mutex_exit(&mq->mq_mtx); 959 mutex_exit(&mq->mq_mtx);
959 fd_putfile((int)SCARG(uap, mqdes)); 960 fd_putfile((int)SCARG(uap, mqdes));
960 961
961 return error; 962 return error;
962} 963}
963 964
964int 965int
965sys_mq_getattr(struct lwp *l, const struct sys_mq_getattr_args *uap, 966sys_mq_getattr(struct lwp *l, const struct sys_mq_getattr_args *uap,
966 register_t *retval) 967 register_t *retval)
967{ 968{
968 /* { 969 /* {
969 syscallarg(mqd_t) mqdes; 970 syscallarg(mqd_t) mqdes;
970 syscallarg(struct mq_attr *) mqstat; 971 syscallarg(struct mq_attr *) mqstat;
971 } */ 972 } */
972 struct mqueue *mq; 973 struct mqueue *mq;
973 struct mq_attr attr; 974 struct mq_attr attr;
974 int error; 975 int error;
975 976
976 error = mqueue_get(SCARG(uap, mqdes), 0, &mq); 977 error = mqueue_get(SCARG(uap, mqdes), 0, &mq);
977 if (error) { 978 if (error) {
978 return error; 979 return error;
979 } 980 }
980 memcpy(&attr, &mq->mq_attrib, sizeof(struct mq_attr)); 981 memcpy(&attr, &mq->mq_attrib, sizeof(struct mq_attr));
981 mutex_exit(&mq->mq_mtx); 982 mutex_exit(&mq->mq_mtx);
982 fd_putfile((int)SCARG(uap, mqdes)); 983 fd_putfile((int)SCARG(uap, mqdes));
983 984
984 return copyout(&attr, SCARG(uap, mqstat), sizeof(struct mq_attr)); 985 return copyout(&attr, SCARG(uap, mqstat), sizeof(struct mq_attr));
985} 986}
986 987
987int 988int
988sys_mq_setattr(struct lwp *l, const struct sys_mq_setattr_args *uap, 989sys_mq_setattr(struct lwp *l, const struct sys_mq_setattr_args *uap,
989 register_t *retval) 990 register_t *retval)
990{ 991{
991 /* { 992 /* {
992 syscallarg(mqd_t) mqdes; 993 syscallarg(mqd_t) mqdes;
993 syscallarg(const struct mq_attr *) mqstat; 994 syscallarg(const struct mq_attr *) mqstat;
994 syscallarg(struct mq_attr *) omqstat; 995 syscallarg(struct mq_attr *) omqstat;
995 } */ 996 } */
996 struct mqueue *mq; 997 struct mqueue *mq;
997 struct mq_attr attr; 998 struct mq_attr attr;
998 int error, nonblock; 999 int error, nonblock;
999 1000
1000 error = copyin(SCARG(uap, mqstat), &attr, sizeof(struct mq_attr)); 1001 error = copyin(SCARG(uap, mqstat), &attr, sizeof(struct mq_attr));
1001 if (error) 1002 if (error)
1002 return error; 1003 return error;
1003 nonblock = (attr.mq_flags & O_NONBLOCK); 1004 nonblock = (attr.mq_flags & O_NONBLOCK);
1004 1005
1005 error = mqueue_get(SCARG(uap, mqdes), 0, &mq); 1006 error = mqueue_get(SCARG(uap, mqdes), 0, &mq);
1006 if (error) { 1007 if (error) {
1007 return error; 1008 return error;
1008 } 1009 }
1009 1010
1010 /* Copy the old attributes, if needed */ 1011 /* Copy the old attributes, if needed */
1011 if (SCARG(uap, omqstat)) { 1012 if (SCARG(uap, omqstat)) {
1012 memcpy(&attr, &mq->mq_attrib, sizeof(struct mq_attr)); 1013 memcpy(&attr, &mq->mq_attrib, sizeof(struct mq_attr));
1013 } 1014 }
1014 1015
1015 /* Ignore everything, except O_NONBLOCK */ 1016 /* Ignore everything, except O_NONBLOCK */
1016 if (nonblock) 1017 if (nonblock)
1017 mq->mq_attrib.mq_flags |= O_NONBLOCK; 1018 mq->mq_attrib.mq_flags |= O_NONBLOCK;
1018 else 1019 else
1019 mq->mq_attrib.mq_flags &= ~O_NONBLOCK; 1020 mq->mq_attrib.mq_flags &= ~O_NONBLOCK;
1020 1021
1021 mutex_exit(&mq->mq_mtx); 1022 mutex_exit(&mq->mq_mtx);
1022 fd_putfile((int)SCARG(uap, mqdes)); 1023 fd_putfile((int)SCARG(uap, mqdes));
1023 1024
1024 /* 1025 /*
1025 * Copy the data to the user-space. 1026 * Copy the data to the user-space.
1026 * Note: According to POSIX, the new attributes should not be set in 1027 * Note: According to POSIX, the new attributes should not be set in
1027 * case of fail - this would be violated. 1028 * case of fail - this would be violated.
1028 */ 1029 */
1029 if (SCARG(uap, omqstat)) 1030 if (SCARG(uap, omqstat))
1030 error = copyout(&attr, SCARG(uap, omqstat), 1031 error = copyout(&attr, SCARG(uap, omqstat),
1031 sizeof(struct mq_attr)); 1032 sizeof(struct mq_attr));
1032 1033
1033 return error; 1034 return error;
1034} 1035}
1035 1036
1036int 1037int
1037sys_mq_unlink(struct lwp *l, const struct sys_mq_unlink_args *uap, 1038sys_mq_unlink(struct lwp *l, const struct sys_mq_unlink_args *uap,
1038 register_t *retval) 1039 register_t *retval)
1039{ 1040{
1040 /* { 1041 /* {
1041 syscallarg(const char *) name; 1042 syscallarg(const char *) name;
1042 } */ 1043 } */
1043 mqueue_t *mq; 1044 mqueue_t *mq;
1044 char *name; 1045 char *name;
1045 int error, refcnt = 0; 1046 int error, refcnt = 0;
1046 1047
1047 /* Get the name from the user-space */ 1048 /* Get the name from the user-space */
1048 name = kmem_alloc(MQ_NAMELEN, KM_SLEEP); 1049 name = kmem_alloc(MQ_NAMELEN, KM_SLEEP);