1*cc17ee2eSpgoyette /*	$NetBSD: netbsd32_mqueue.c,v 1.7 2019/01/27 02:08:40 pgoyette Exp $	*/
29cec043eSmartin 
39cec043eSmartin /*-
49cec043eSmartin  * Copyright (c) 2008 The NetBSD Foundation, Inc.
59cec043eSmartin  * All rights reserved.
69cec043eSmartin  *
79cec043eSmartin  * This code is derived from software developed for The NetBSD Foundation.
89cec043eSmartin  *
99cec043eSmartin  * Redistribution and use in source and binary forms, with or without
109cec043eSmartin  * modification, are permitted provided that the following conditions
119cec043eSmartin  * are met:
129cec043eSmartin  * 1. Redistributions of source code must retain the above copyright
139cec043eSmartin  *    notice, this list of conditions and the following disclaimer.
149cec043eSmartin  * 2. Redistributions in binary form must reproduce the above copyright
159cec043eSmartin  *    notice, this list of conditions and the following disclaimer in the
169cec043eSmartin  *    documentation and/or other materials provided with the distribution.
179cec043eSmartin  *
189cec043eSmartin  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
199cec043eSmartin  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
209cec043eSmartin  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
219cec043eSmartin  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
229cec043eSmartin  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
239cec043eSmartin  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
249cec043eSmartin  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
259cec043eSmartin  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
269cec043eSmartin  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
279cec043eSmartin  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
289cec043eSmartin  * POSSIBILITY OF SUCH DAMAGE.
299cec043eSmartin  */
309cec043eSmartin 
319cec043eSmartin #include <sys/cdefs.h>
32*cc17ee2eSpgoyette __KERNEL_RCSID(0, "$NetBSD: netbsd32_mqueue.c,v 1.7 2019/01/27 02:08:40 pgoyette Exp $");
339cec043eSmartin 
349cec043eSmartin #if defined(_KERNEL_OPT)
359cec043eSmartin #include "opt_compat_netbsd.h"
369cec043eSmartin #endif
379cec043eSmartin 
389cec043eSmartin #include <sys/param.h>
399cec043eSmartin #include <sys/dirent.h>
409cec043eSmartin #include <sys/filedesc.h>
419cec043eSmartin #include <sys/fcntl.h>
429cec043eSmartin #include <sys/module.h>
43fb93a1daSpgoyette #include <sys/syscallvar.h>
449cec043eSmartin 
459cec043eSmartin #include <compat/netbsd32/netbsd32.h>
469cec043eSmartin #include <compat/netbsd32/netbsd32_syscall.h>
479cec043eSmartin #include <compat/netbsd32/netbsd32_syscallargs.h>
489cec043eSmartin #include <compat/netbsd32/netbsd32_conv.h>
499cec043eSmartin 
509cec043eSmartin int
netbsd32_mq_open(struct lwp * l,const struct netbsd32_mq_open_args * uap,register_t * retval)519cec043eSmartin netbsd32_mq_open(struct lwp *l, const struct netbsd32_mq_open_args *uap,
529cec043eSmartin     register_t *retval)
539cec043eSmartin {
549cec043eSmartin 	/* {
559cec043eSmartin 		syscallarg(const netbsd32_charp) name;
569cec043eSmartin 		syscallarg(int) oflag;
579cec043eSmartin 		syscallarg(mode_t) mode;
589cec043eSmartin 		syscallarg(struct netbsd32_mq_attrp_t) attr;
599cec043eSmartin 	} */
609cec043eSmartin 	struct netbsd32_mq_attr attr32;
619cec043eSmartin 	struct mq_attr *attr = NULL, a;
629cec043eSmartin 	int error;
639cec043eSmartin 
6459bac05fSchristos 	if ((SCARG(uap, oflag) & O_CREAT) && SCARG_P32(uap, attr) != NULL) {
65d02810a4Smartin 		error = copyin(SCARG_P32(uap, attr), &attr32, sizeof(attr32));
669cec043eSmartin 		if (error)
679cec043eSmartin 			return error;
689cec043eSmartin 		netbsd32_to_mq_attr(&attr32, &a);
699cec043eSmartin 		attr = &a;
709cec043eSmartin 	}
719cec043eSmartin 
729cec043eSmartin 	return mq_handle_open(l, SCARG_P32(uap, name), SCARG(uap, oflag),
739cec043eSmartin 	    SCARG(uap, mode), attr, retval);
749cec043eSmartin }
759cec043eSmartin 
769cec043eSmartin int
netbsd32_mq_close(struct lwp * l,const struct netbsd32_mq_close_args * uap,register_t * retval)779cec043eSmartin netbsd32_mq_close(struct lwp *l, const struct netbsd32_mq_close_args *uap,
789cec043eSmartin     register_t *retval)
799cec043eSmartin {
809cec043eSmartin 	/* {
819cec043eSmartin 		syscallarg(mqd_t) mqdes;
829cec043eSmartin 	} */
839cec043eSmartin 
849cec043eSmartin 	return netbsd32_close(l, (const void*)uap, retval);
859cec043eSmartin }
869cec043eSmartin 
879cec043eSmartin int
netbsd32_mq_unlink(struct lwp * l,const struct netbsd32_mq_unlink_args * uap,register_t * retval)889cec043eSmartin netbsd32_mq_unlink(struct lwp *l, const struct netbsd32_mq_unlink_args *uap,
899cec043eSmartin     register_t *retval)
909cec043eSmartin {
919cec043eSmartin 	/* {
929cec043eSmartin 		syscallarg(const netbsd32_charp) name;
939cec043eSmartin 	} */
949cec043eSmartin 	struct sys_mq_unlink_args ua;
959cec043eSmartin 
969cec043eSmartin 	NETBSD32TOP_UAP(name, const char);
979cec043eSmartin 	return sys_mq_unlink(l, &ua, retval);
989cec043eSmartin }
999cec043eSmartin 
1009cec043eSmartin int
netbsd32_mq_getattr(struct lwp * l,const struct netbsd32_mq_getattr_args * uap,register_t * retval)1019cec043eSmartin netbsd32_mq_getattr(struct lwp *l, const struct netbsd32_mq_getattr_args *uap,
1029cec043eSmartin     register_t *retval)
1039cec043eSmartin {
1049cec043eSmartin 	/* {
1059cec043eSmartin 		syscallarg(mqd_t) mqdes;
1069cec043eSmartin 		syscallarg(netbsd32_mq_attrp_t) mqstat;
1079cec043eSmartin 	} */
1089cec043eSmartin 	struct mqueue *mq;
1099cec043eSmartin 	struct mq_attr attr;
1109cec043eSmartin 	struct netbsd32_mq_attr a32;
1119cec043eSmartin 	int error;
1129cec043eSmartin 
1139cec043eSmartin 	error = mqueue_get(SCARG(uap, mqdes), 0, &mq);
1149cec043eSmartin 	if (error)
1159cec043eSmartin 		return error;
1169cec043eSmartin 
1179cec043eSmartin 	memcpy(&attr, &mq->mq_attrib, sizeof(struct mq_attr));
1189cec043eSmartin 	mutex_exit(&mq->mq_mtx);
1199cec043eSmartin 	fd_putfile((int)SCARG(uap, mqdes));
1209cec043eSmartin 	netbsd32_from_mq_attr(&attr, &a32);
1219cec043eSmartin 	return copyout(&a32, SCARG_P32(uap,mqstat), sizeof(a32));
1229cec043eSmartin }
1239cec043eSmartin 
1249cec043eSmartin int
netbsd32_mq_setattr(struct lwp * l,const struct netbsd32_mq_setattr_args * uap,register_t * retval)1259cec043eSmartin netbsd32_mq_setattr(struct lwp *l, const struct netbsd32_mq_setattr_args *uap,
1269cec043eSmartin     register_t *retval)
1279cec043eSmartin {
1289cec043eSmartin 	/* {
1299cec043eSmartin 		syscallarg(mqd_t) mqdes;
1309cec043eSmartin 		syscallarg(const netbsd32_mq_attrp_t) mqstat;
1319cec043eSmartin 		syscallarg(netbsd32_mq_attrp_t) omqstat;
1329cec043eSmartin 	} */
1339cec043eSmartin 	struct mqueue *mq;
1349cec043eSmartin 	struct netbsd32_mq_attr attr32;
1359cec043eSmartin 	struct mq_attr attr;
1369cec043eSmartin 	int error, nonblock;
1379cec043eSmartin 
1389cec043eSmartin 	error = copyin(SCARG_P32(uap, mqstat), &attr32, sizeof(attr32));
1399cec043eSmartin 	if (error)
1409cec043eSmartin 		return error;
1419cec043eSmartin 	netbsd32_to_mq_attr(&attr32, &attr);
1429cec043eSmartin 	nonblock = (attr.mq_flags & O_NONBLOCK);
1439cec043eSmartin 
1449cec043eSmartin 	error = mqueue_get(SCARG(uap, mqdes), 0, &mq);
1459cec043eSmartin 	if (error)
1469cec043eSmartin 		return error;
1479cec043eSmartin 
1489cec043eSmartin 	/* Copy the old attributes, if needed */
1499cec043eSmartin 	if (SCARG_P32(uap, omqstat))
1509cec043eSmartin 		memcpy(&attr, &mq->mq_attrib, sizeof(struct mq_attr));
1519cec043eSmartin 
1529cec043eSmartin 	/* Ignore everything, except O_NONBLOCK */
1539cec043eSmartin 	if (nonblock)
1549cec043eSmartin 		mq->mq_attrib.mq_flags |= O_NONBLOCK;
1559cec043eSmartin 	else
1569cec043eSmartin 		mq->mq_attrib.mq_flags &= ~O_NONBLOCK;
1579cec043eSmartin 
1589cec043eSmartin 	mutex_exit(&mq->mq_mtx);
1599cec043eSmartin 	fd_putfile((int)SCARG(uap, mqdes));
1609cec043eSmartin 
1619cec043eSmartin 	/*
1629cec043eSmartin 	 * Copy the data to the user-space.
1639cec043eSmartin 	 * Note: According to POSIX, the new attributes should not be set in
1649cec043eSmartin 	 * case of fail - this would be violated.
1659cec043eSmartin 	 */
1669cec043eSmartin 	if (SCARG_P32(uap, omqstat)) {
1679cec043eSmartin 		netbsd32_from_mq_attr(&attr, &attr32);
1689cec043eSmartin 		error = copyout(&attr32, SCARG_P32(uap, omqstat),
1699cec043eSmartin 		    sizeof(attr32));
1709cec043eSmartin 	}
1719cec043eSmartin 
1729cec043eSmartin 	return error;
1739cec043eSmartin }
1749cec043eSmartin 
1759cec043eSmartin int
netbsd32_mq_notify(struct lwp * l,const struct netbsd32_mq_notify_args * uap,register_t * result)1769cec043eSmartin netbsd32_mq_notify(struct lwp *l, const struct netbsd32_mq_notify_args *uap,
1779cec043eSmartin     register_t *result)
1789cec043eSmartin {
1799cec043eSmartin 	/* {
1809cec043eSmartin 		syscallarg(mqd_t) mqdes;
1819cec043eSmartin 		syscallarg(const netbsd32_sigeventp_t) notification;
1829cec043eSmartin 	} */
1839cec043eSmartin 	struct mqueue *mq;
1849cec043eSmartin 	struct netbsd32_sigevent sig32;
1859cec043eSmartin 	int error;
1869cec043eSmartin 
1879cec043eSmartin 	if (SCARG_P32(uap, notification)) {
1889cec043eSmartin 		/* Get the signal from user-space */
1899cec043eSmartin 		error = copyin(SCARG_P32(uap, notification), &sig32,
1909cec043eSmartin 		    sizeof(sig32));
1919cec043eSmartin 		if (error)
1929cec043eSmartin 			return error;
1939cec043eSmartin 		if (sig32.sigev_notify == SIGEV_SIGNAL &&
1949cec043eSmartin 		    (sig32.sigev_signo <=0 || sig32.sigev_signo >= NSIG))
1959cec043eSmartin 			return EINVAL;
1969cec043eSmartin 	}
1979cec043eSmartin 
1989cec043eSmartin 	error = mqueue_get(SCARG(uap, mqdes), 0, &mq);
1999cec043eSmartin 	if (error) {
2009cec043eSmartin 		return error;
2019cec043eSmartin 	}
2029cec043eSmartin 	if (SCARG_P32(uap, notification)) {
2039cec043eSmartin 		/* Register notification: set the signal and target process */
2049cec043eSmartin 		if (mq->mq_notify_proc == NULL) {
2059cec043eSmartin 			netbsd32_to_sigevent(&sig32, &mq->mq_sig_notify);
2069cec043eSmartin 			mq->mq_notify_proc = l->l_proc;
2079cec043eSmartin 		} else {
2089cec043eSmartin 			/* Fail if someone else already registered */
2099cec043eSmartin 			error = EBUSY;
2109cec043eSmartin 		}
2119cec043eSmartin 	} else {
2129cec043eSmartin 		/* Unregister the notification */
2139cec043eSmartin 		mq->mq_notify_proc = NULL;
2149cec043eSmartin 	}
2159cec043eSmartin 	mutex_exit(&mq->mq_mtx);
2169cec043eSmartin 	fd_putfile((int)SCARG(uap, mqdes));
2179cec043eSmartin 
2189cec043eSmartin 	return error;
2199cec043eSmartin }
2209cec043eSmartin 
2219cec043eSmartin int
netbsd32_mq_send(struct lwp * l,const struct netbsd32_mq_send_args * uap,register_t * result)2229cec043eSmartin netbsd32_mq_send(struct lwp *l, const struct netbsd32_mq_send_args *uap,
2239cec043eSmartin     register_t *result)
2249cec043eSmartin {
2259cec043eSmartin 	/* {
2269cec043eSmartin 		syscallarg(mqd_t) mqdes;
2279cec043eSmartin 		syscallarg(const netbsd32_charp) msg_ptr;
2289cec043eSmartin 		syscallarg(netbsd32_size_t) msg_len;
2299cec043eSmartin 		syscallarg(unsigned) msg_prio;
2309cec043eSmartin 	} */
2319cec043eSmartin 
2329cec043eSmartin 
2339cec043eSmartin 	return mq_send1(SCARG(uap, mqdes), SCARG_P32(uap, msg_ptr),
2349cec043eSmartin 	    SCARG(uap, msg_len), SCARG(uap, msg_prio), NULL);
2359cec043eSmartin }
2369cec043eSmartin 
2379cec043eSmartin int
netbsd32_mq_receive(struct lwp * l,const struct netbsd32_mq_receive_args * uap,register_t * retval)2389cec043eSmartin netbsd32_mq_receive(struct lwp *l, const struct netbsd32_mq_receive_args *uap,
2399cec043eSmartin     register_t *retval)
2409cec043eSmartin {
2419cec043eSmartin 	/* {
2429cec043eSmartin 		syscallarg(mqd_t) mqdes;
2439cec043eSmartin 		syscallarg(netbsd32_charp) msg_ptr;
2449cec043eSmartin 		syscallarg(netbsd32_size_t) msg_len;
2459cec043eSmartin 		syscallarg(netbsd32_uintp) msg_prio;
2469cec043eSmartin 	} */
2479cec043eSmartin 	ssize_t mlen;
2489cec043eSmartin 	int error;
2499cec043eSmartin 
2509cec043eSmartin 	error = mq_recv1(SCARG(uap, mqdes), SCARG_P32(uap, msg_ptr),
2519cec043eSmartin 	    SCARG(uap, msg_len), SCARG_P32(uap, msg_prio), NULL, &mlen);
2529cec043eSmartin 	if (error == 0)
2539cec043eSmartin 		*retval = mlen;
2549cec043eSmartin 
2559cec043eSmartin 	return error;
2569cec043eSmartin }
2579cec043eSmartin 
2589cec043eSmartin int
netbsd32___mq_timedsend50(struct lwp * l,const struct netbsd32___mq_timedsend50_args * uap,register_t * retval)2598e9c942dSmartin netbsd32___mq_timedsend50(struct lwp *l,
2608e9c942dSmartin      const struct netbsd32___mq_timedsend50_args *uap, register_t *retval)
2619cec043eSmartin {
2629cec043eSmartin 	/* {
2639cec043eSmartin 		syscallarg(mqd_t) mqdes;
2649cec043eSmartin 		syscallarg(const netbsd32_charp) msg_ptr;
2659cec043eSmartin 		syscallarg(netbsd32_size_t) msg_len;
2669cec043eSmartin 		syscallarg(unsigned) msg_prio;
2678e9c942dSmartin 		syscallarg(const netbsd32_timespecp_t) abs_timeout;
2689cec043eSmartin 	} */
2699cec043eSmartin 	struct timespec ts, *tsp;
2709cec043eSmartin 	struct netbsd32_timespec ts32;
2719cec043eSmartin 	int error;
2729cec043eSmartin 
2739cec043eSmartin 	/* Get and convert time value */
2749cec043eSmartin 	if (SCARG_P32(uap, abs_timeout)) {
2759cec043eSmartin 		error = copyin(SCARG_P32(uap, abs_timeout), &ts32,
2769cec043eSmartin 		     sizeof(ts32));
2779cec043eSmartin 		if (error)
2789cec043eSmartin 			return error;
2799cec043eSmartin 		netbsd32_to_timespec(&ts32, &ts);
2809cec043eSmartin 		tsp = &ts;
2819cec043eSmartin 	} else {
2829cec043eSmartin 		tsp = NULL;
2839cec043eSmartin 	}
2849cec043eSmartin 
2859cec043eSmartin 	return mq_send1(SCARG(uap, mqdes), SCARG_P32(uap, msg_ptr),
2869cec043eSmartin 	    SCARG(uap, msg_len), SCARG(uap, msg_prio), tsp);
2879cec043eSmartin }
2889cec043eSmartin 
2899cec043eSmartin int
netbsd32___mq_timedreceive50(struct lwp * l,const struct netbsd32___mq_timedreceive50_args * uap,register_t * retval)2908e9c942dSmartin netbsd32___mq_timedreceive50(struct lwp *l,
2918e9c942dSmartin     const struct netbsd32___mq_timedreceive50_args *uap, register_t *retval)
2929cec043eSmartin {
2939cec043eSmartin 	/* {
2949cec043eSmartin 		syscallarg(mqd_t) mqdes;
2959cec043eSmartin 		syscallarg(netbsd32_charp) msg_ptr;
2969cec043eSmartin 		syscallarg(netbsd32_size_t) msg_len;
2979cec043eSmartin 		syscallarg(netbsd32_uintp) msg_prio;
2988e9c942dSmartin 		syscallarg(const netbsd32_timespecp_t) abs_timeout;
2999cec043eSmartin 	} */
3009cec043eSmartin 	struct timespec ts, *tsp;
3019cec043eSmartin 	struct netbsd32_timespec ts32;
3029cec043eSmartin 	ssize_t mlen;
3039cec043eSmartin 	int error;
3049cec043eSmartin 
3059cec043eSmartin 	/* Get and convert time value */
3069cec043eSmartin 	if (SCARG_P32(uap, abs_timeout)) {
3079cec043eSmartin 		error = copyin(SCARG_P32(uap, abs_timeout), &ts32,
3089cec043eSmartin 		    sizeof(ts32));
3099cec043eSmartin 		if (error)
3109cec043eSmartin 			return error;
3119cec043eSmartin 		netbsd32_to_timespec(&ts32, &ts);
3129cec043eSmartin 		tsp = &ts;
3139cec043eSmartin 	} else {
3149cec043eSmartin 		tsp = NULL;
3159cec043eSmartin 	}
3169cec043eSmartin 
3179cec043eSmartin 	error = mq_recv1(SCARG(uap, mqdes), SCARG_P32(uap, msg_ptr),
3189cec043eSmartin 	    SCARG(uap, msg_len), SCARG_P32(uap, msg_prio), tsp, &mlen);
3199cec043eSmartin 	if (error == 0)
3209cec043eSmartin 		*retval = mlen;
3219cec043eSmartin 
3229cec043eSmartin 	return error;
3239cec043eSmartin }
3248e9c942dSmartin 
325fb93a1daSpgoyette #ifdef COMPAT_50
326fb93a1daSpgoyette 
327fb93a1daSpgoyette int
compat_50_netbsd32_mq_timedsend(struct lwp * l,const struct compat_50_netbsd32_mq_timedsend_args * uap,register_t * retval)328fb93a1daSpgoyette compat_50_netbsd32_mq_timedsend(struct lwp *l,
329fb93a1daSpgoyette     const struct compat_50_netbsd32_mq_timedsend_args *uap,
330fb93a1daSpgoyette     register_t *retval)
331fb93a1daSpgoyette {
332fb93a1daSpgoyette 	/* {
333fb93a1daSpgoyette 		syscallarg(mqd_t) mqdes;
334fb93a1daSpgoyette 		syscallarg(const netbsd32_charp) msg_ptr;
335fb93a1daSpgoyette 		syscallarg(netbsd32_size_t) msg_len;
336fb93a1daSpgoyette 		syscallarg(unsigned) msg_prio;
337fb93a1daSpgoyette 		syscallarg(const netbsd32_timespec50p_t) abs_timeout;
338fb93a1daSpgoyette 	} */
339fb93a1daSpgoyette 	struct timespec ts, *tsp;
340fb93a1daSpgoyette 	struct netbsd32_timespec50 ts32;
341fb93a1daSpgoyette 	int error;
342fb93a1daSpgoyette 
343fb93a1daSpgoyette 	/* Get and convert time value */
344fb93a1daSpgoyette 	if (SCARG_P32(uap, abs_timeout)) {
345fb93a1daSpgoyette 		error = copyin(SCARG_P32(uap, abs_timeout), &ts32,
346fb93a1daSpgoyette 		     sizeof(ts32));
347fb93a1daSpgoyette 		if (error)
348fb93a1daSpgoyette 			return error;
349fb93a1daSpgoyette 		netbsd32_to_timespec50(&ts32, &ts);
350fb93a1daSpgoyette 		tsp = &ts;
351fb93a1daSpgoyette 	} else {
352fb93a1daSpgoyette 		tsp = NULL;
353fb93a1daSpgoyette 	}
354fb93a1daSpgoyette 
355fb93a1daSpgoyette 	return mq_send1(SCARG(uap, mqdes), SCARG_P32(uap, msg_ptr),
356fb93a1daSpgoyette 	    SCARG(uap, msg_len), SCARG(uap, msg_prio), tsp);
357fb93a1daSpgoyette }
358fb93a1daSpgoyette 
359fb93a1daSpgoyette int
compat_50_netbsd32_mq_timedreceive(struct lwp * l,const struct compat_50_netbsd32_mq_timedreceive_args * uap,register_t * retval)360fb93a1daSpgoyette compat_50_netbsd32_mq_timedreceive(struct lwp *l,
361fb93a1daSpgoyette     const struct compat_50_netbsd32_mq_timedreceive_args *uap,
362fb93a1daSpgoyette     register_t *retval)
363fb93a1daSpgoyette {
364fb93a1daSpgoyette 	/* {
365fb93a1daSpgoyette 		syscallarg(mqd_t) mqdes;
366fb93a1daSpgoyette 		syscallarg(netbsd32_charp) msg_ptr;
367fb93a1daSpgoyette 		syscallarg(netbsd32_size_t) msg_len;
368fb93a1daSpgoyette 		syscallarg(netbsd32_uintp) msg_prio;
369fb93a1daSpgoyette 		syscallarg(const netbsd32_timespec50p_t) abs_timeout;
370fb93a1daSpgoyette 	} */
371fb93a1daSpgoyette 	struct timespec ts, *tsp;
372fb93a1daSpgoyette 	struct netbsd32_timespec50 ts32;
373fb93a1daSpgoyette 	ssize_t mlen;
374fb93a1daSpgoyette 	int error;
375fb93a1daSpgoyette 
376fb93a1daSpgoyette 	/* Get and convert time value */
377fb93a1daSpgoyette 	if (SCARG_P32(uap, abs_timeout)) {
378fb93a1daSpgoyette 		error = copyin(SCARG_P32(uap, abs_timeout), &ts32,
379fb93a1daSpgoyette 		    sizeof(ts32));
380fb93a1daSpgoyette 		if (error)
381fb93a1daSpgoyette 			return error;
382fb93a1daSpgoyette 		netbsd32_to_timespec50(&ts32, &ts);
383fb93a1daSpgoyette 		tsp = &ts;
384fb93a1daSpgoyette 	} else {
385fb93a1daSpgoyette 		tsp = NULL;
386fb93a1daSpgoyette 	}
387fb93a1daSpgoyette 
388fb93a1daSpgoyette 	error = mq_recv1(SCARG(uap, mqdes), SCARG_P32(uap, msg_ptr),
389fb93a1daSpgoyette 	    SCARG(uap, msg_len), SCARG_P32(uap, msg_prio), tsp, &mlen);
390fb93a1daSpgoyette 	if (error == 0)
391fb93a1daSpgoyette 		*retval = mlen;
392fb93a1daSpgoyette 
393fb93a1daSpgoyette 	return error;
394fb93a1daSpgoyette }
395fb93a1daSpgoyette 
396fb93a1daSpgoyette #endif /* COMPAT_50 */
397fb93a1daSpgoyette 
398fb93a1daSpgoyette #define _PKG_ENTRY(name)	\
399fb93a1daSpgoyette 	{ NETBSD32_SYS_ ## name, 0, (sy_call_t *)name }
400fb93a1daSpgoyette 
401fb93a1daSpgoyette static const struct syscall_package compat_mqueue_syscalls[] = {
402fb93a1daSpgoyette 	_PKG_ENTRY(netbsd32_mq_open),
403fb93a1daSpgoyette 	_PKG_ENTRY(netbsd32_mq_close),
404fb93a1daSpgoyette 	_PKG_ENTRY(netbsd32_mq_unlink),
405fb93a1daSpgoyette 	_PKG_ENTRY(netbsd32_mq_getattr),
406fb93a1daSpgoyette 	_PKG_ENTRY(netbsd32_mq_setattr),
407fb93a1daSpgoyette 	_PKG_ENTRY(netbsd32_mq_notify),
408fb93a1daSpgoyette 	_PKG_ENTRY(netbsd32_mq_send),
409fb93a1daSpgoyette 	_PKG_ENTRY(netbsd32_mq_receive),
410fb93a1daSpgoyette 	_PKG_ENTRY(netbsd32___mq_timedsend50),
411fb93a1daSpgoyette 	_PKG_ENTRY(netbsd32___mq_timedreceive50),
412fb93a1daSpgoyette #ifdef COMPAT_50
413fb93a1daSpgoyette 	_PKG_ENTRY(compat_50_netbsd32_mq_timedsend),
414fb93a1daSpgoyette 	_PKG_ENTRY(compat_50_netbsd32_mq_timedreceive),
415fb93a1daSpgoyette #endif
416fb93a1daSpgoyette 	{0, 0, NULL}
417fb93a1daSpgoyette };
418fb93a1daSpgoyette 
419fb93a1daSpgoyette MODULE(MODULE_CLASS_EXEC, compat_netbsd32_mqueue, "mqueue,compat_netbsd32");
420fb93a1daSpgoyette 
421fb93a1daSpgoyette static int
compat_netbsd32_mqueue_modcmd(modcmd_t cmd,void * arg)422fb93a1daSpgoyette compat_netbsd32_mqueue_modcmd(modcmd_t cmd, void *arg)
423fb93a1daSpgoyette {
424fb93a1daSpgoyette 	int error;
425fb93a1daSpgoyette 
426fb93a1daSpgoyette 	switch (cmd) {
427fb93a1daSpgoyette 	case MODULE_CMD_INIT:
428fb93a1daSpgoyette 		error = syscall_establish(&emul_netbsd32,
429fb93a1daSpgoyette 		    compat_mqueue_syscalls);
430fb93a1daSpgoyette 		break;
431fb93a1daSpgoyette 	case MODULE_CMD_FINI:
432fb93a1daSpgoyette 		error = syscall_disestablish(&emul_netbsd32,
433fb93a1daSpgoyette 		    compat_mqueue_syscalls);
434fb93a1daSpgoyette 		break;
435fb93a1daSpgoyette 	default:
436fb93a1daSpgoyette 		error = ENOTTY;
437fb93a1daSpgoyette 		break;
438fb93a1daSpgoyette 	}
439fb93a1daSpgoyette 	return error;
440fb93a1daSpgoyette }
441