xref: /titanic_51/usr/src/uts/common/os/msg.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate /*
34*7c478bd9Sstevel@tonic-gate  * Inter-Process Communication Message Facility.
35*7c478bd9Sstevel@tonic-gate  *
36*7c478bd9Sstevel@tonic-gate  * See os/ipc.c for a description of common IPC functionality.
37*7c478bd9Sstevel@tonic-gate  *
38*7c478bd9Sstevel@tonic-gate  * Resource controls
39*7c478bd9Sstevel@tonic-gate  * -----------------
40*7c478bd9Sstevel@tonic-gate  *
41*7c478bd9Sstevel@tonic-gate  * Control:      project.max-msg-ids (rc_project_msgmni)
42*7c478bd9Sstevel@tonic-gate  * Description:  Maximum number of message queue ids allowed a project.
43*7c478bd9Sstevel@tonic-gate  *
44*7c478bd9Sstevel@tonic-gate  *   When msgget() is used to allocate a message queue, one id is
45*7c478bd9Sstevel@tonic-gate  *   allocated.  If the id allocation doesn't succeed, msgget() fails
46*7c478bd9Sstevel@tonic-gate  *   and errno is set to ENOSPC.  Upon successful msgctl(, IPC_RMID)
47*7c478bd9Sstevel@tonic-gate  *   the id is deallocated.
48*7c478bd9Sstevel@tonic-gate  *
49*7c478bd9Sstevel@tonic-gate  * Control:      process.max-msg-qbytes (rc_process_msgmnb)
50*7c478bd9Sstevel@tonic-gate  * Description:  Maximum number of bytes of messages on a message queue.
51*7c478bd9Sstevel@tonic-gate  *
52*7c478bd9Sstevel@tonic-gate  *   When msgget() successfully allocates a message queue, the minimum
53*7c478bd9Sstevel@tonic-gate  *   enforced value of this limit is used to initialize msg_qbytes.
54*7c478bd9Sstevel@tonic-gate  *
55*7c478bd9Sstevel@tonic-gate  * Control:      process.max-msg-messages (rc_process_msgtql)
56*7c478bd9Sstevel@tonic-gate  * Description:  Maximum number of messages on a message queue.
57*7c478bd9Sstevel@tonic-gate  *
58*7c478bd9Sstevel@tonic-gate  *   When msgget() successfully allocates a message queue, the minimum
59*7c478bd9Sstevel@tonic-gate  *   enforced value of this limit is used to initialize a per-queue
60*7c478bd9Sstevel@tonic-gate  *   limit on the number of messages.
61*7c478bd9Sstevel@tonic-gate  */
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
64*7c478bd9Sstevel@tonic-gate #include <sys/t_lock.h>
65*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
66*7c478bd9Sstevel@tonic-gate #include <sys/cred.h>
67*7c478bd9Sstevel@tonic-gate #include <sys/user.h>
68*7c478bd9Sstevel@tonic-gate #include <sys/proc.h>
69*7c478bd9Sstevel@tonic-gate #include <sys/time.h>
70*7c478bd9Sstevel@tonic-gate #include <sys/ipc.h>
71*7c478bd9Sstevel@tonic-gate #include <sys/ipc_impl.h>
72*7c478bd9Sstevel@tonic-gate #include <sys/msg.h>
73*7c478bd9Sstevel@tonic-gate #include <sys/msg_impl.h>
74*7c478bd9Sstevel@tonic-gate #include <sys/list.h>
75*7c478bd9Sstevel@tonic-gate #include <sys/systm.h>
76*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
77*7c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h>
78*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
79*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
80*7c478bd9Sstevel@tonic-gate #include <sys/errno.h>
81*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
82*7c478bd9Sstevel@tonic-gate #include <sys/debug.h>
83*7c478bd9Sstevel@tonic-gate #include <sys/project.h>
84*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
85*7c478bd9Sstevel@tonic-gate #include <sys/syscall.h>
86*7c478bd9Sstevel@tonic-gate #include <sys/policy.h>
87*7c478bd9Sstevel@tonic-gate #include <sys/zone.h>
88*7c478bd9Sstevel@tonic-gate 
89*7c478bd9Sstevel@tonic-gate #include <c2/audit.h>
90*7c478bd9Sstevel@tonic-gate 
91*7c478bd9Sstevel@tonic-gate /*
92*7c478bd9Sstevel@tonic-gate  * The following tunables are obsolete.  Though for compatibility we
93*7c478bd9Sstevel@tonic-gate  * still read and interpret msginfo_msgmnb, msginfo_msgmni, and
94*7c478bd9Sstevel@tonic-gate  * msginfo_msgtql (see os/project.c and os/rctl_proc.c), the preferred
95*7c478bd9Sstevel@tonic-gate  * mechanism for administrating the IPC Message facility is through the
96*7c478bd9Sstevel@tonic-gate  * resource controls described at the top of this file.
97*7c478bd9Sstevel@tonic-gate  */
98*7c478bd9Sstevel@tonic-gate size_t	msginfo_msgmax = 2048;	/* (obsolete) */
99*7c478bd9Sstevel@tonic-gate size_t	msginfo_msgmnb = 4096;	/* (obsolete) */
100*7c478bd9Sstevel@tonic-gate int	msginfo_msgmni = 50;	/* (obsolete) */
101*7c478bd9Sstevel@tonic-gate int	msginfo_msgtql = 40;	/* (obsolete) */
102*7c478bd9Sstevel@tonic-gate int	msginfo_msgssz = 8;	/* (obsolete) */
103*7c478bd9Sstevel@tonic-gate int	msginfo_msgmap = 0;	/* (obsolete) */
104*7c478bd9Sstevel@tonic-gate ushort_t msginfo_msgseg = 1024;	/* (obsolete) */
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate extern rctl_hndl_t rc_project_msgmni;
107*7c478bd9Sstevel@tonic-gate extern rctl_hndl_t rc_process_msgmnb;
108*7c478bd9Sstevel@tonic-gate extern rctl_hndl_t rc_process_msgtql;
109*7c478bd9Sstevel@tonic-gate static ipc_service_t *msq_svc;
110*7c478bd9Sstevel@tonic-gate static zone_key_t msg_zone_key;
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate static void msg_dtor(kipc_perm_t *);
113*7c478bd9Sstevel@tonic-gate static void msg_rmid(kipc_perm_t *);
114*7c478bd9Sstevel@tonic-gate static void msg_remove_zone(zoneid_t, void *);
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate /*
117*7c478bd9Sstevel@tonic-gate  * Module linkage information for the kernel.
118*7c478bd9Sstevel@tonic-gate  */
119*7c478bd9Sstevel@tonic-gate static ssize_t msgsys(int opcode, uintptr_t a0, uintptr_t a1, uintptr_t a2,
120*7c478bd9Sstevel@tonic-gate 	uintptr_t a4, uintptr_t a5);
121*7c478bd9Sstevel@tonic-gate 
122*7c478bd9Sstevel@tonic-gate static struct sysent ipcmsg_sysent = {
123*7c478bd9Sstevel@tonic-gate 	6,
124*7c478bd9Sstevel@tonic-gate #ifdef	_LP64
125*7c478bd9Sstevel@tonic-gate 	SE_ARGC | SE_NOUNLOAD | SE_64RVAL,
126*7c478bd9Sstevel@tonic-gate #else
127*7c478bd9Sstevel@tonic-gate 	SE_ARGC | SE_NOUNLOAD | SE_32RVAL1,
128*7c478bd9Sstevel@tonic-gate #endif
129*7c478bd9Sstevel@tonic-gate 	(int (*)())msgsys
130*7c478bd9Sstevel@tonic-gate };
131*7c478bd9Sstevel@tonic-gate 
132*7c478bd9Sstevel@tonic-gate #ifdef	_SYSCALL32_IMPL
133*7c478bd9Sstevel@tonic-gate static ssize32_t msgsys32(int opcode, uint32_t a0, uint32_t a1, uint32_t a2,
134*7c478bd9Sstevel@tonic-gate 	uint32_t a4, uint32_t a5);
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate static struct sysent ipcmsg_sysent32 = {
137*7c478bd9Sstevel@tonic-gate 	6,
138*7c478bd9Sstevel@tonic-gate 	SE_ARGC | SE_NOUNLOAD | SE_32RVAL1,
139*7c478bd9Sstevel@tonic-gate 	(int (*)())msgsys32
140*7c478bd9Sstevel@tonic-gate };
141*7c478bd9Sstevel@tonic-gate #endif	/* _SYSCALL32_IMPL */
142*7c478bd9Sstevel@tonic-gate 
143*7c478bd9Sstevel@tonic-gate static struct modlsys modlsys = {
144*7c478bd9Sstevel@tonic-gate 	&mod_syscallops, "System V message facility", &ipcmsg_sysent
145*7c478bd9Sstevel@tonic-gate };
146*7c478bd9Sstevel@tonic-gate 
147*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
148*7c478bd9Sstevel@tonic-gate static struct modlsys modlsys32 = {
149*7c478bd9Sstevel@tonic-gate 	&mod_syscallops32, "32-bit System V message facility", &ipcmsg_sysent32
150*7c478bd9Sstevel@tonic-gate };
151*7c478bd9Sstevel@tonic-gate #endif
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
154*7c478bd9Sstevel@tonic-gate 	MODREV_1,
155*7c478bd9Sstevel@tonic-gate 	&modlsys,
156*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
157*7c478bd9Sstevel@tonic-gate 	&modlsys32,
158*7c478bd9Sstevel@tonic-gate #endif
159*7c478bd9Sstevel@tonic-gate 	NULL
160*7c478bd9Sstevel@tonic-gate };
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate int
164*7c478bd9Sstevel@tonic-gate _init(void)
165*7c478bd9Sstevel@tonic-gate {
166*7c478bd9Sstevel@tonic-gate 	int result;
167*7c478bd9Sstevel@tonic-gate 
168*7c478bd9Sstevel@tonic-gate 	msq_svc = ipcs_create("msqids", rc_project_msgmni, sizeof (kmsqid_t),
169*7c478bd9Sstevel@tonic-gate 	    msg_dtor, msg_rmid, AT_IPC_MSG,
170*7c478bd9Sstevel@tonic-gate 	    offsetof(kproject_data_t, kpd_msgmni));
171*7c478bd9Sstevel@tonic-gate 	zone_key_create(&msg_zone_key, NULL, msg_remove_zone, NULL);
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate 	if ((result = mod_install(&modlinkage)) == 0)
174*7c478bd9Sstevel@tonic-gate 		return (0);
175*7c478bd9Sstevel@tonic-gate 
176*7c478bd9Sstevel@tonic-gate 	(void) zone_key_delete(msg_zone_key);
177*7c478bd9Sstevel@tonic-gate 	ipcs_destroy(msq_svc);
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate 	return (result);
180*7c478bd9Sstevel@tonic-gate }
181*7c478bd9Sstevel@tonic-gate 
182*7c478bd9Sstevel@tonic-gate int
183*7c478bd9Sstevel@tonic-gate _fini(void)
184*7c478bd9Sstevel@tonic-gate {
185*7c478bd9Sstevel@tonic-gate 	return (EBUSY);
186*7c478bd9Sstevel@tonic-gate }
187*7c478bd9Sstevel@tonic-gate 
188*7c478bd9Sstevel@tonic-gate int
189*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
190*7c478bd9Sstevel@tonic-gate {
191*7c478bd9Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
192*7c478bd9Sstevel@tonic-gate }
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate static void
195*7c478bd9Sstevel@tonic-gate msg_dtor(kipc_perm_t *perm)
196*7c478bd9Sstevel@tonic-gate {
197*7c478bd9Sstevel@tonic-gate 	kmsqid_t *qp = (kmsqid_t *)perm;
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate 	ASSERT(qp->msg_rcv_cnt == 0);
200*7c478bd9Sstevel@tonic-gate 	ASSERT(qp->msg_snd_cnt == 0);
201*7c478bd9Sstevel@tonic-gate 	ASSERT(qp->msg_cbytes == 0);
202*7c478bd9Sstevel@tonic-gate 	list_destroy(&qp->msg_list);
203*7c478bd9Sstevel@tonic-gate }
204*7c478bd9Sstevel@tonic-gate 
205*7c478bd9Sstevel@tonic-gate 
206*7c478bd9Sstevel@tonic-gate #define	msg_hold(mp)	(mp)->msg_copycnt++
207*7c478bd9Sstevel@tonic-gate 
208*7c478bd9Sstevel@tonic-gate /*
209*7c478bd9Sstevel@tonic-gate  * msg_rele - decrement the reference count on the message.  When count
210*7c478bd9Sstevel@tonic-gate  * reaches zero, free message header and contents.
211*7c478bd9Sstevel@tonic-gate  */
212*7c478bd9Sstevel@tonic-gate static void
213*7c478bd9Sstevel@tonic-gate msg_rele(struct msg *mp)
214*7c478bd9Sstevel@tonic-gate {
215*7c478bd9Sstevel@tonic-gate 	ASSERT(mp->msg_copycnt > 0);
216*7c478bd9Sstevel@tonic-gate 	if (mp->msg_copycnt-- == 1) {
217*7c478bd9Sstevel@tonic-gate 		if (mp->msg_addr)
218*7c478bd9Sstevel@tonic-gate 			kmem_free(mp->msg_addr, mp->msg_size);
219*7c478bd9Sstevel@tonic-gate 		kmem_free(mp, sizeof (struct msg));
220*7c478bd9Sstevel@tonic-gate 	}
221*7c478bd9Sstevel@tonic-gate }
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate /*
224*7c478bd9Sstevel@tonic-gate  * msgunlink - Unlink msg from queue, decrement byte count and wake up anyone
225*7c478bd9Sstevel@tonic-gate  * waiting for free bytes on queue.
226*7c478bd9Sstevel@tonic-gate  *
227*7c478bd9Sstevel@tonic-gate  * Called with queue locked.
228*7c478bd9Sstevel@tonic-gate  */
229*7c478bd9Sstevel@tonic-gate static void
230*7c478bd9Sstevel@tonic-gate msgunlink(kmsqid_t *qp, struct msg *mp)
231*7c478bd9Sstevel@tonic-gate {
232*7c478bd9Sstevel@tonic-gate 	list_remove(&qp->msg_list, mp);
233*7c478bd9Sstevel@tonic-gate 	qp->msg_qnum--;
234*7c478bd9Sstevel@tonic-gate 	qp->msg_cbytes -= mp->msg_size;
235*7c478bd9Sstevel@tonic-gate 	msg_rele(mp);
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate 	/* Wake up waiting writers */
238*7c478bd9Sstevel@tonic-gate 	if (qp->msg_snd_cnt)
239*7c478bd9Sstevel@tonic-gate 		cv_broadcast(&qp->msg_snd_cv);
240*7c478bd9Sstevel@tonic-gate }
241*7c478bd9Sstevel@tonic-gate 
242*7c478bd9Sstevel@tonic-gate static void
243*7c478bd9Sstevel@tonic-gate msg_rmid(kipc_perm_t *perm)
244*7c478bd9Sstevel@tonic-gate {
245*7c478bd9Sstevel@tonic-gate 	kmsqid_t *qp = (kmsqid_t *)perm;
246*7c478bd9Sstevel@tonic-gate 	struct msg *mp;
247*7c478bd9Sstevel@tonic-gate 
248*7c478bd9Sstevel@tonic-gate 
249*7c478bd9Sstevel@tonic-gate 	while ((mp = list_head(&qp->msg_list)) != NULL)
250*7c478bd9Sstevel@tonic-gate 		msgunlink(qp, mp);
251*7c478bd9Sstevel@tonic-gate 	ASSERT(qp->msg_cbytes == 0);
252*7c478bd9Sstevel@tonic-gate 
253*7c478bd9Sstevel@tonic-gate 	if (qp->msg_rcv_cnt)
254*7c478bd9Sstevel@tonic-gate 		cv_broadcast(&qp->msg_rcv_cv);
255*7c478bd9Sstevel@tonic-gate 	if (qp->msg_snd_cnt)
256*7c478bd9Sstevel@tonic-gate 		cv_broadcast(&qp->msg_snd_cv);
257*7c478bd9Sstevel@tonic-gate }
258*7c478bd9Sstevel@tonic-gate 
259*7c478bd9Sstevel@tonic-gate /*
260*7c478bd9Sstevel@tonic-gate  * msgctl system call.
261*7c478bd9Sstevel@tonic-gate  *
262*7c478bd9Sstevel@tonic-gate  * gets q lock (via ipc_lookup), releases before return.
263*7c478bd9Sstevel@tonic-gate  * may call users of msg_lock
264*7c478bd9Sstevel@tonic-gate  */
265*7c478bd9Sstevel@tonic-gate static int
266*7c478bd9Sstevel@tonic-gate msgctl(int msgid, int cmd, void *arg)
267*7c478bd9Sstevel@tonic-gate {
268*7c478bd9Sstevel@tonic-gate 	STRUCT_DECL(msqid_ds, ds);		/* SVR4 queue work area */
269*7c478bd9Sstevel@tonic-gate 	kmsqid_t		*qp;		/* ptr to associated q */
270*7c478bd9Sstevel@tonic-gate 	int			error;
271*7c478bd9Sstevel@tonic-gate 	struct	cred		*cr;
272*7c478bd9Sstevel@tonic-gate 	model_t	mdl = get_udatamodel();
273*7c478bd9Sstevel@tonic-gate 	struct msqid_ds64	ds64;
274*7c478bd9Sstevel@tonic-gate 	kmutex_t		*lock;
275*7c478bd9Sstevel@tonic-gate 	proc_t			*pp = curproc;
276*7c478bd9Sstevel@tonic-gate 
277*7c478bd9Sstevel@tonic-gate 	STRUCT_INIT(ds, mdl);
278*7c478bd9Sstevel@tonic-gate 	cr = CRED();
279*7c478bd9Sstevel@tonic-gate 
280*7c478bd9Sstevel@tonic-gate 	/*
281*7c478bd9Sstevel@tonic-gate 	 * Perform pre- or non-lookup actions (e.g. copyins, RMID).
282*7c478bd9Sstevel@tonic-gate 	 */
283*7c478bd9Sstevel@tonic-gate 	switch (cmd) {
284*7c478bd9Sstevel@tonic-gate 	case IPC_SET:
285*7c478bd9Sstevel@tonic-gate 		if (copyin(arg, STRUCT_BUF(ds), STRUCT_SIZE(ds)))
286*7c478bd9Sstevel@tonic-gate 			return (set_errno(EFAULT));
287*7c478bd9Sstevel@tonic-gate 		break;
288*7c478bd9Sstevel@tonic-gate 
289*7c478bd9Sstevel@tonic-gate 	case IPC_SET64:
290*7c478bd9Sstevel@tonic-gate 		if (copyin(arg, &ds64, sizeof (struct msqid_ds64)))
291*7c478bd9Sstevel@tonic-gate 			return (set_errno(EFAULT));
292*7c478bd9Sstevel@tonic-gate 		break;
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 	case IPC_RMID:
295*7c478bd9Sstevel@tonic-gate 		if (error = ipc_rmid(msq_svc, msgid, cr))
296*7c478bd9Sstevel@tonic-gate 			return (set_errno(error));
297*7c478bd9Sstevel@tonic-gate 		return (0);
298*7c478bd9Sstevel@tonic-gate 	}
299*7c478bd9Sstevel@tonic-gate 
300*7c478bd9Sstevel@tonic-gate 	/*
301*7c478bd9Sstevel@tonic-gate 	 * get msqid_ds for this msgid
302*7c478bd9Sstevel@tonic-gate 	 */
303*7c478bd9Sstevel@tonic-gate 	if ((lock = ipc_lookup(msq_svc, msgid, (kipc_perm_t **)&qp)) == NULL)
304*7c478bd9Sstevel@tonic-gate 		return (set_errno(EINVAL));
305*7c478bd9Sstevel@tonic-gate 
306*7c478bd9Sstevel@tonic-gate 	switch (cmd) {
307*7c478bd9Sstevel@tonic-gate 	case IPC_SET:
308*7c478bd9Sstevel@tonic-gate 		if (STRUCT_FGET(ds, msg_qbytes) > qp->msg_qbytes &&
309*7c478bd9Sstevel@tonic-gate 		    secpolicy_ipc_config(cr) != 0) {
310*7c478bd9Sstevel@tonic-gate 			mutex_exit(lock);
311*7c478bd9Sstevel@tonic-gate 			return (set_errno(EPERM));
312*7c478bd9Sstevel@tonic-gate 		}
313*7c478bd9Sstevel@tonic-gate 		if (error = ipcperm_set(msq_svc, cr, &qp->msg_perm,
314*7c478bd9Sstevel@tonic-gate 		    &STRUCT_BUF(ds)->msg_perm, mdl)) {
315*7c478bd9Sstevel@tonic-gate 			mutex_exit(lock);
316*7c478bd9Sstevel@tonic-gate 			return (set_errno(error));
317*7c478bd9Sstevel@tonic-gate 		}
318*7c478bd9Sstevel@tonic-gate 		qp->msg_qbytes = STRUCT_FGET(ds, msg_qbytes);
319*7c478bd9Sstevel@tonic-gate 		qp->msg_ctime = gethrestime_sec();
320*7c478bd9Sstevel@tonic-gate 		break;
321*7c478bd9Sstevel@tonic-gate 
322*7c478bd9Sstevel@tonic-gate 	case IPC_STAT:
323*7c478bd9Sstevel@tonic-gate 		if (error = ipcperm_access(&qp->msg_perm, MSG_R, cr)) {
324*7c478bd9Sstevel@tonic-gate 			mutex_exit(lock);
325*7c478bd9Sstevel@tonic-gate 			return (set_errno(error));
326*7c478bd9Sstevel@tonic-gate 		}
327*7c478bd9Sstevel@tonic-gate 
328*7c478bd9Sstevel@tonic-gate 		if (qp->msg_rcv_cnt)
329*7c478bd9Sstevel@tonic-gate 			qp->msg_perm.ipc_mode |= MSG_RWAIT;
330*7c478bd9Sstevel@tonic-gate 		if (qp->msg_snd_cnt)
331*7c478bd9Sstevel@tonic-gate 			qp->msg_perm.ipc_mode |= MSG_WWAIT;
332*7c478bd9Sstevel@tonic-gate 		ipcperm_stat(&STRUCT_BUF(ds)->msg_perm, &qp->msg_perm, mdl);
333*7c478bd9Sstevel@tonic-gate 		qp->msg_perm.ipc_mode &= ~(MSG_RWAIT|MSG_WWAIT);
334*7c478bd9Sstevel@tonic-gate 		STRUCT_FSETP(ds, msg_first, NULL); 	/* kernel addr */
335*7c478bd9Sstevel@tonic-gate 		STRUCT_FSETP(ds, msg_last, NULL);
336*7c478bd9Sstevel@tonic-gate 		STRUCT_FSET(ds, msg_cbytes, qp->msg_cbytes);
337*7c478bd9Sstevel@tonic-gate 		STRUCT_FSET(ds, msg_qnum, qp->msg_qnum);
338*7c478bd9Sstevel@tonic-gate 		STRUCT_FSET(ds, msg_qbytes, qp->msg_qbytes);
339*7c478bd9Sstevel@tonic-gate 		STRUCT_FSET(ds, msg_lspid, qp->msg_lspid);
340*7c478bd9Sstevel@tonic-gate 		STRUCT_FSET(ds, msg_lrpid, qp->msg_lrpid);
341*7c478bd9Sstevel@tonic-gate 		STRUCT_FSET(ds, msg_stime, qp->msg_stime);
342*7c478bd9Sstevel@tonic-gate 		STRUCT_FSET(ds, msg_rtime, qp->msg_rtime);
343*7c478bd9Sstevel@tonic-gate 		STRUCT_FSET(ds, msg_ctime, qp->msg_ctime);
344*7c478bd9Sstevel@tonic-gate 		break;
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate 	case IPC_SET64:
347*7c478bd9Sstevel@tonic-gate 		mutex_enter(&pp->p_lock);
348*7c478bd9Sstevel@tonic-gate 		if ((ds64.msgx_qbytes > qp->msg_qbytes) &&
349*7c478bd9Sstevel@tonic-gate 		    secpolicy_ipc_config(cr) != 0 &&
350*7c478bd9Sstevel@tonic-gate 		    rctl_test(rc_process_msgmnb, pp->p_rctls, pp,
351*7c478bd9Sstevel@tonic-gate 		    ds64.msgx_qbytes, RCA_SAFE) & RCT_DENY) {
352*7c478bd9Sstevel@tonic-gate 			mutex_exit(&pp->p_lock);
353*7c478bd9Sstevel@tonic-gate 			mutex_exit(lock);
354*7c478bd9Sstevel@tonic-gate 			return (set_errno(EPERM));
355*7c478bd9Sstevel@tonic-gate 		}
356*7c478bd9Sstevel@tonic-gate 		mutex_exit(&pp->p_lock);
357*7c478bd9Sstevel@tonic-gate 		if (error = ipcperm_set64(msq_svc, cr, &qp->msg_perm,
358*7c478bd9Sstevel@tonic-gate 		    &ds64.msgx_perm)) {
359*7c478bd9Sstevel@tonic-gate 			mutex_exit(lock);
360*7c478bd9Sstevel@tonic-gate 			return (set_errno(error));
361*7c478bd9Sstevel@tonic-gate 		}
362*7c478bd9Sstevel@tonic-gate 		qp->msg_qbytes = ds64.msgx_qbytes;
363*7c478bd9Sstevel@tonic-gate 		qp->msg_ctime = gethrestime_sec();
364*7c478bd9Sstevel@tonic-gate 		break;
365*7c478bd9Sstevel@tonic-gate 
366*7c478bd9Sstevel@tonic-gate 	case IPC_STAT64:
367*7c478bd9Sstevel@tonic-gate 		if (qp->msg_rcv_cnt)
368*7c478bd9Sstevel@tonic-gate 			qp->msg_perm.ipc_mode |= MSG_RWAIT;
369*7c478bd9Sstevel@tonic-gate 		if (qp->msg_snd_cnt)
370*7c478bd9Sstevel@tonic-gate 			qp->msg_perm.ipc_mode |= MSG_WWAIT;
371*7c478bd9Sstevel@tonic-gate 		ipcperm_stat64(&ds64.msgx_perm, &qp->msg_perm);
372*7c478bd9Sstevel@tonic-gate 		qp->msg_perm.ipc_mode &= ~(MSG_RWAIT|MSG_WWAIT);
373*7c478bd9Sstevel@tonic-gate 		ds64.msgx_cbytes = qp->msg_cbytes;
374*7c478bd9Sstevel@tonic-gate 		ds64.msgx_qnum = qp->msg_qnum;
375*7c478bd9Sstevel@tonic-gate 		ds64.msgx_qbytes = qp->msg_qbytes;
376*7c478bd9Sstevel@tonic-gate 		ds64.msgx_lspid = qp->msg_lspid;
377*7c478bd9Sstevel@tonic-gate 		ds64.msgx_lrpid = qp->msg_lrpid;
378*7c478bd9Sstevel@tonic-gate 		ds64.msgx_stime = qp->msg_stime;
379*7c478bd9Sstevel@tonic-gate 		ds64.msgx_rtime = qp->msg_rtime;
380*7c478bd9Sstevel@tonic-gate 		ds64.msgx_ctime = qp->msg_ctime;
381*7c478bd9Sstevel@tonic-gate 		break;
382*7c478bd9Sstevel@tonic-gate 
383*7c478bd9Sstevel@tonic-gate 	default:
384*7c478bd9Sstevel@tonic-gate 		mutex_exit(lock);
385*7c478bd9Sstevel@tonic-gate 		return (set_errno(EINVAL));
386*7c478bd9Sstevel@tonic-gate 	}
387*7c478bd9Sstevel@tonic-gate 
388*7c478bd9Sstevel@tonic-gate 	mutex_exit(lock);
389*7c478bd9Sstevel@tonic-gate 
390*7c478bd9Sstevel@tonic-gate 	/*
391*7c478bd9Sstevel@tonic-gate 	 * Do copyout last (after releasing mutex).
392*7c478bd9Sstevel@tonic-gate 	 */
393*7c478bd9Sstevel@tonic-gate 	switch (cmd) {
394*7c478bd9Sstevel@tonic-gate 	case IPC_STAT:
395*7c478bd9Sstevel@tonic-gate 		if (copyout(STRUCT_BUF(ds), arg, STRUCT_SIZE(ds)))
396*7c478bd9Sstevel@tonic-gate 			return (set_errno(EFAULT));
397*7c478bd9Sstevel@tonic-gate 		break;
398*7c478bd9Sstevel@tonic-gate 
399*7c478bd9Sstevel@tonic-gate 	case IPC_STAT64:
400*7c478bd9Sstevel@tonic-gate 		if (copyout(&ds64, arg, sizeof (struct msqid_ds64)))
401*7c478bd9Sstevel@tonic-gate 			return (set_errno(EFAULT));
402*7c478bd9Sstevel@tonic-gate 		break;
403*7c478bd9Sstevel@tonic-gate 	}
404*7c478bd9Sstevel@tonic-gate 
405*7c478bd9Sstevel@tonic-gate 	return (0);
406*7c478bd9Sstevel@tonic-gate }
407*7c478bd9Sstevel@tonic-gate 
408*7c478bd9Sstevel@tonic-gate /*
409*7c478bd9Sstevel@tonic-gate  * Remove all message queues associated with a given zone.  Called by
410*7c478bd9Sstevel@tonic-gate  * zone_shutdown when the zone is halted.
411*7c478bd9Sstevel@tonic-gate  */
412*7c478bd9Sstevel@tonic-gate /*ARGSUSED1*/
413*7c478bd9Sstevel@tonic-gate static void
414*7c478bd9Sstevel@tonic-gate msg_remove_zone(zoneid_t zoneid, void *arg)
415*7c478bd9Sstevel@tonic-gate {
416*7c478bd9Sstevel@tonic-gate 	ipc_remove_zone(msq_svc, zoneid);
417*7c478bd9Sstevel@tonic-gate }
418*7c478bd9Sstevel@tonic-gate 
419*7c478bd9Sstevel@tonic-gate /*
420*7c478bd9Sstevel@tonic-gate  * msgget system call.
421*7c478bd9Sstevel@tonic-gate  */
422*7c478bd9Sstevel@tonic-gate static int
423*7c478bd9Sstevel@tonic-gate msgget(key_t key, int msgflg)
424*7c478bd9Sstevel@tonic-gate {
425*7c478bd9Sstevel@tonic-gate 	kmsqid_t	*qp;
426*7c478bd9Sstevel@tonic-gate 	kmutex_t	*lock;
427*7c478bd9Sstevel@tonic-gate 	int		id, error;
428*7c478bd9Sstevel@tonic-gate 	proc_t		*pp = curproc;
429*7c478bd9Sstevel@tonic-gate 
430*7c478bd9Sstevel@tonic-gate top:
431*7c478bd9Sstevel@tonic-gate 	if (error = ipc_get(msq_svc, key, msgflg, (kipc_perm_t **)&qp, &lock))
432*7c478bd9Sstevel@tonic-gate 		return (set_errno(error));
433*7c478bd9Sstevel@tonic-gate 
434*7c478bd9Sstevel@tonic-gate 	if (IPC_FREE(&qp->msg_perm)) {
435*7c478bd9Sstevel@tonic-gate 		mutex_exit(lock);
436*7c478bd9Sstevel@tonic-gate 		mutex_exit(&pp->p_lock);
437*7c478bd9Sstevel@tonic-gate 
438*7c478bd9Sstevel@tonic-gate 		list_create(&qp->msg_list, sizeof (struct msg),
439*7c478bd9Sstevel@tonic-gate 		    offsetof(struct msg, msg_node));
440*7c478bd9Sstevel@tonic-gate 		qp->msg_qnum = 0;
441*7c478bd9Sstevel@tonic-gate 		qp->msg_lspid = qp->msg_lrpid = 0;
442*7c478bd9Sstevel@tonic-gate 		qp->msg_stime = qp->msg_rtime = 0;
443*7c478bd9Sstevel@tonic-gate 		qp->msg_ctime = gethrestime_sec();
444*7c478bd9Sstevel@tonic-gate 		qp->msg_rcv_cnt = qp->msg_snd_cnt = 0;
445*7c478bd9Sstevel@tonic-gate 
446*7c478bd9Sstevel@tonic-gate 		if (error = ipc_commit_begin(msq_svc, key, msgflg,
447*7c478bd9Sstevel@tonic-gate 		    (kipc_perm_t *)qp)) {
448*7c478bd9Sstevel@tonic-gate 			if (error == EAGAIN)
449*7c478bd9Sstevel@tonic-gate 				goto top;
450*7c478bd9Sstevel@tonic-gate 			return (set_errno(error));
451*7c478bd9Sstevel@tonic-gate 		}
452*7c478bd9Sstevel@tonic-gate 		qp->msg_qbytes = rctl_enforced_value(rc_process_msgmnb,
453*7c478bd9Sstevel@tonic-gate 		    pp->p_rctls, pp);
454*7c478bd9Sstevel@tonic-gate 		qp->msg_qmax = rctl_enforced_value(rc_process_msgtql,
455*7c478bd9Sstevel@tonic-gate 		    pp->p_rctls, pp);
456*7c478bd9Sstevel@tonic-gate 		lock = ipc_commit_end(msq_svc, &qp->msg_perm);
457*7c478bd9Sstevel@tonic-gate 	}
458*7c478bd9Sstevel@tonic-gate #ifdef C2_AUDIT
459*7c478bd9Sstevel@tonic-gate 	if (audit_active)
460*7c478bd9Sstevel@tonic-gate 		audit_ipcget(AT_IPC_MSG, (void *)qp);
461*7c478bd9Sstevel@tonic-gate #endif
462*7c478bd9Sstevel@tonic-gate 	id = qp->msg_perm.ipc_id;
463*7c478bd9Sstevel@tonic-gate 	mutex_exit(lock);
464*7c478bd9Sstevel@tonic-gate 	return (id);
465*7c478bd9Sstevel@tonic-gate }
466*7c478bd9Sstevel@tonic-gate 
467*7c478bd9Sstevel@tonic-gate /*
468*7c478bd9Sstevel@tonic-gate  * msgrcv system call.
469*7c478bd9Sstevel@tonic-gate  */
470*7c478bd9Sstevel@tonic-gate static ssize_t
471*7c478bd9Sstevel@tonic-gate msgrcv(int msqid, struct ipcmsgbuf *msgp, size_t msgsz, long msgtyp, int msgflg)
472*7c478bd9Sstevel@tonic-gate {
473*7c478bd9Sstevel@tonic-gate 	struct msg	*mp;	/* ptr to msg on q */
474*7c478bd9Sstevel@tonic-gate 	struct msg	*smp;	/* ptr to best msg on q */
475*7c478bd9Sstevel@tonic-gate 	kmsqid_t	*qp;	/* ptr to associated q */
476*7c478bd9Sstevel@tonic-gate 	kmutex_t	*lock;
477*7c478bd9Sstevel@tonic-gate 	size_t		xtsz;	/* transfer byte count */
478*7c478bd9Sstevel@tonic-gate 	int		error = 0, copyerror = 0;
479*7c478bd9Sstevel@tonic-gate 	int		cvres;
480*7c478bd9Sstevel@tonic-gate 	STRUCT_HANDLE(ipcmsgbuf, umsgp);
481*7c478bd9Sstevel@tonic-gate 	model_t		mdl = get_udatamodel();
482*7c478bd9Sstevel@tonic-gate 
483*7c478bd9Sstevel@tonic-gate 	CPU_STATS_ADDQ(CPU, sys, msg, 1);	/* bump msg send/rcv count */
484*7c478bd9Sstevel@tonic-gate 	STRUCT_SET_HANDLE(umsgp, mdl, msgp);
485*7c478bd9Sstevel@tonic-gate 
486*7c478bd9Sstevel@tonic-gate 	if ((lock = ipc_lookup(msq_svc, msqid, (kipc_perm_t **)&qp)) == NULL)
487*7c478bd9Sstevel@tonic-gate 		return ((ssize_t)set_errno(EINVAL));
488*7c478bd9Sstevel@tonic-gate 	ipc_hold(msq_svc, (kipc_perm_t *)qp);
489*7c478bd9Sstevel@tonic-gate 
490*7c478bd9Sstevel@tonic-gate 	if (error = ipcperm_access(&qp->msg_perm, MSG_R, CRED()))
491*7c478bd9Sstevel@tonic-gate 		goto msgrcv_out;
492*7c478bd9Sstevel@tonic-gate 
493*7c478bd9Sstevel@tonic-gate findmsg:
494*7c478bd9Sstevel@tonic-gate 	smp = NULL;
495*7c478bd9Sstevel@tonic-gate 	mp = list_head(&qp->msg_list);
496*7c478bd9Sstevel@tonic-gate 	if (msgtyp == 0) {
497*7c478bd9Sstevel@tonic-gate 		smp = mp;
498*7c478bd9Sstevel@tonic-gate 	} else {
499*7c478bd9Sstevel@tonic-gate 		for (; mp; mp = list_next(&qp->msg_list, mp)) {
500*7c478bd9Sstevel@tonic-gate 			if (msgtyp > 0) {
501*7c478bd9Sstevel@tonic-gate 				if (msgtyp != mp->msg_type)
502*7c478bd9Sstevel@tonic-gate 					continue;
503*7c478bd9Sstevel@tonic-gate 				smp = mp;
504*7c478bd9Sstevel@tonic-gate 				break;
505*7c478bd9Sstevel@tonic-gate 			}
506*7c478bd9Sstevel@tonic-gate 			if (mp->msg_type <= -msgtyp) {
507*7c478bd9Sstevel@tonic-gate 				if (smp && smp->msg_type <= mp->msg_type)
508*7c478bd9Sstevel@tonic-gate 					continue;
509*7c478bd9Sstevel@tonic-gate 				smp = mp;
510*7c478bd9Sstevel@tonic-gate 			}
511*7c478bd9Sstevel@tonic-gate 		}
512*7c478bd9Sstevel@tonic-gate 	}
513*7c478bd9Sstevel@tonic-gate 
514*7c478bd9Sstevel@tonic-gate 	if (smp) {
515*7c478bd9Sstevel@tonic-gate 		/*
516*7c478bd9Sstevel@tonic-gate 		 * Message found.
517*7c478bd9Sstevel@tonic-gate 		 */
518*7c478bd9Sstevel@tonic-gate 		if ((smp->msg_flags & MSG_RCVCOPY) == 0) {
519*7c478bd9Sstevel@tonic-gate 			/*
520*7c478bd9Sstevel@tonic-gate 			 * No one else is copying this message. Copy it.
521*7c478bd9Sstevel@tonic-gate 			 */
522*7c478bd9Sstevel@tonic-gate 			if (msgsz < smp->msg_size) {
523*7c478bd9Sstevel@tonic-gate 				if ((msgflg & MSG_NOERROR) == 0) {
524*7c478bd9Sstevel@tonic-gate 					error = E2BIG;
525*7c478bd9Sstevel@tonic-gate 					goto msgrcv_out;
526*7c478bd9Sstevel@tonic-gate 				} else {
527*7c478bd9Sstevel@tonic-gate 					xtsz = msgsz;
528*7c478bd9Sstevel@tonic-gate 				}
529*7c478bd9Sstevel@tonic-gate 			} else {
530*7c478bd9Sstevel@tonic-gate 				xtsz = smp->msg_size;
531*7c478bd9Sstevel@tonic-gate 			}
532*7c478bd9Sstevel@tonic-gate 
533*7c478bd9Sstevel@tonic-gate 			/*
534*7c478bd9Sstevel@tonic-gate 			 * Mark message as being copied out. Release mutex
535*7c478bd9Sstevel@tonic-gate 			 * while copying out.
536*7c478bd9Sstevel@tonic-gate 			 */
537*7c478bd9Sstevel@tonic-gate 			ASSERT((smp->msg_flags & MSG_RCVCOPY) == 0);
538*7c478bd9Sstevel@tonic-gate 			smp->msg_flags |= MSG_RCVCOPY;
539*7c478bd9Sstevel@tonic-gate 			msg_hold(smp);
540*7c478bd9Sstevel@tonic-gate 			mutex_exit(lock);
541*7c478bd9Sstevel@tonic-gate 
542*7c478bd9Sstevel@tonic-gate 			if (mdl == DATAMODEL_NATIVE) {
543*7c478bd9Sstevel@tonic-gate 				copyerror = copyout(&smp->msg_type, msgp,
544*7c478bd9Sstevel@tonic-gate 				    sizeof (smp->msg_type));
545*7c478bd9Sstevel@tonic-gate 			} else {
546*7c478bd9Sstevel@tonic-gate 				/*
547*7c478bd9Sstevel@tonic-gate 				 * 32-bit callers need an imploded msg type.
548*7c478bd9Sstevel@tonic-gate 				 */
549*7c478bd9Sstevel@tonic-gate 				int32_t	msg_type32 = smp->msg_type;
550*7c478bd9Sstevel@tonic-gate 
551*7c478bd9Sstevel@tonic-gate 				copyerror = copyout(&msg_type32, msgp,
552*7c478bd9Sstevel@tonic-gate 				    sizeof (msg_type32));
553*7c478bd9Sstevel@tonic-gate 			}
554*7c478bd9Sstevel@tonic-gate 
555*7c478bd9Sstevel@tonic-gate 			if (copyerror == 0 && xtsz)
556*7c478bd9Sstevel@tonic-gate 				copyerror = copyout(smp->msg_addr,
557*7c478bd9Sstevel@tonic-gate 				    STRUCT_FADDR(umsgp, mtext), xtsz);
558*7c478bd9Sstevel@tonic-gate 
559*7c478bd9Sstevel@tonic-gate 			/*
560*7c478bd9Sstevel@tonic-gate 			 * Reclaim mutex, make sure queue still exists,
561*7c478bd9Sstevel@tonic-gate 			 * and remove message.
562*7c478bd9Sstevel@tonic-gate 			 */
563*7c478bd9Sstevel@tonic-gate 			lock = ipc_lock(msq_svc, qp->msg_perm.ipc_id);
564*7c478bd9Sstevel@tonic-gate 			ASSERT(smp->msg_flags & MSG_RCVCOPY);
565*7c478bd9Sstevel@tonic-gate 			smp->msg_flags &= ~MSG_RCVCOPY;
566*7c478bd9Sstevel@tonic-gate 			msg_rele(smp);
567*7c478bd9Sstevel@tonic-gate 
568*7c478bd9Sstevel@tonic-gate 			if (IPC_FREE(&qp->msg_perm)) {
569*7c478bd9Sstevel@tonic-gate 				error = EIDRM;
570*7c478bd9Sstevel@tonic-gate 				goto msgrcv_out;
571*7c478bd9Sstevel@tonic-gate 			}
572*7c478bd9Sstevel@tonic-gate 			cv_broadcast(&qp->msg_rcv_cv);
573*7c478bd9Sstevel@tonic-gate 
574*7c478bd9Sstevel@tonic-gate 			if (copyerror) {
575*7c478bd9Sstevel@tonic-gate 				error = EFAULT;
576*7c478bd9Sstevel@tonic-gate 				goto msgrcv_out;
577*7c478bd9Sstevel@tonic-gate 			}
578*7c478bd9Sstevel@tonic-gate 			qp->msg_lrpid = ttoproc(curthread)->p_pid;
579*7c478bd9Sstevel@tonic-gate 			qp->msg_rtime = gethrestime_sec();
580*7c478bd9Sstevel@tonic-gate 			msgunlink(qp, smp);
581*7c478bd9Sstevel@tonic-gate 			goto msgrcv_out;
582*7c478bd9Sstevel@tonic-gate 		}
583*7c478bd9Sstevel@tonic-gate 
584*7c478bd9Sstevel@tonic-gate 	} else {
585*7c478bd9Sstevel@tonic-gate 		/*
586*7c478bd9Sstevel@tonic-gate 		 * No message found.
587*7c478bd9Sstevel@tonic-gate 		 */
588*7c478bd9Sstevel@tonic-gate 		if (msgflg & IPC_NOWAIT) {
589*7c478bd9Sstevel@tonic-gate 			error = ENOMSG;
590*7c478bd9Sstevel@tonic-gate 			goto msgrcv_out;
591*7c478bd9Sstevel@tonic-gate 		}
592*7c478bd9Sstevel@tonic-gate 	}
593*7c478bd9Sstevel@tonic-gate 
594*7c478bd9Sstevel@tonic-gate 	/* Wait for new message */
595*7c478bd9Sstevel@tonic-gate 	qp->msg_rcv_cnt++;
596*7c478bd9Sstevel@tonic-gate 	cvres = cv_wait_sig(&qp->msg_rcv_cv, lock);
597*7c478bd9Sstevel@tonic-gate 	lock = ipc_relock(msq_svc, qp->msg_perm.ipc_id, lock);
598*7c478bd9Sstevel@tonic-gate 	qp->msg_rcv_cnt--;
599*7c478bd9Sstevel@tonic-gate 
600*7c478bd9Sstevel@tonic-gate 	if (IPC_FREE(&qp->msg_perm)) {
601*7c478bd9Sstevel@tonic-gate 		error = EIDRM;
602*7c478bd9Sstevel@tonic-gate 		goto msgrcv_out;
603*7c478bd9Sstevel@tonic-gate 	}
604*7c478bd9Sstevel@tonic-gate 	if (cvres == 0) {
605*7c478bd9Sstevel@tonic-gate 		error = EINTR;
606*7c478bd9Sstevel@tonic-gate 		goto msgrcv_out;
607*7c478bd9Sstevel@tonic-gate 	}
608*7c478bd9Sstevel@tonic-gate 
609*7c478bd9Sstevel@tonic-gate 	goto findmsg;
610*7c478bd9Sstevel@tonic-gate 
611*7c478bd9Sstevel@tonic-gate msgrcv_out:
612*7c478bd9Sstevel@tonic-gate 	ipc_rele(msq_svc, (kipc_perm_t *)qp);
613*7c478bd9Sstevel@tonic-gate 	if (error)
614*7c478bd9Sstevel@tonic-gate 		return ((ssize_t)set_errno(error));
615*7c478bd9Sstevel@tonic-gate 	return ((ssize_t)xtsz);
616*7c478bd9Sstevel@tonic-gate }
617*7c478bd9Sstevel@tonic-gate 
618*7c478bd9Sstevel@tonic-gate /*
619*7c478bd9Sstevel@tonic-gate  * msgids system call.
620*7c478bd9Sstevel@tonic-gate  */
621*7c478bd9Sstevel@tonic-gate static int
622*7c478bd9Sstevel@tonic-gate msgids(int *buf, uint_t nids, uint_t *pnids)
623*7c478bd9Sstevel@tonic-gate {
624*7c478bd9Sstevel@tonic-gate 	int error;
625*7c478bd9Sstevel@tonic-gate 
626*7c478bd9Sstevel@tonic-gate 	if (error = ipc_ids(msq_svc, buf, nids, pnids))
627*7c478bd9Sstevel@tonic-gate 		return (set_errno(error));
628*7c478bd9Sstevel@tonic-gate 
629*7c478bd9Sstevel@tonic-gate 	return (0);
630*7c478bd9Sstevel@tonic-gate }
631*7c478bd9Sstevel@tonic-gate 
632*7c478bd9Sstevel@tonic-gate #define	RND(x)		roundup((x), sizeof (size_t))
633*7c478bd9Sstevel@tonic-gate #define	RND32(x)	roundup((x), sizeof (size32_t))
634*7c478bd9Sstevel@tonic-gate 
635*7c478bd9Sstevel@tonic-gate /*
636*7c478bd9Sstevel@tonic-gate  * msgsnap system call.
637*7c478bd9Sstevel@tonic-gate  */
638*7c478bd9Sstevel@tonic-gate static int
639*7c478bd9Sstevel@tonic-gate msgsnap(int msqid, caddr_t buf, size_t bufsz, long msgtyp)
640*7c478bd9Sstevel@tonic-gate {
641*7c478bd9Sstevel@tonic-gate 	struct msg	*mp;	/* ptr to msg on q */
642*7c478bd9Sstevel@tonic-gate 	kmsqid_t	*qp;	/* ptr to associated q */
643*7c478bd9Sstevel@tonic-gate 	kmutex_t	*lock;
644*7c478bd9Sstevel@tonic-gate 	size_t		size;
645*7c478bd9Sstevel@tonic-gate 	size_t		nmsg;
646*7c478bd9Sstevel@tonic-gate 	struct msg	**snaplist;
647*7c478bd9Sstevel@tonic-gate 	int		error, i;
648*7c478bd9Sstevel@tonic-gate 	model_t		mdl = get_udatamodel();
649*7c478bd9Sstevel@tonic-gate 	STRUCT_DECL(msgsnap_head, head);
650*7c478bd9Sstevel@tonic-gate 	STRUCT_DECL(msgsnap_mhead, mhead);
651*7c478bd9Sstevel@tonic-gate 
652*7c478bd9Sstevel@tonic-gate 	STRUCT_INIT(head, mdl);
653*7c478bd9Sstevel@tonic-gate 	STRUCT_INIT(mhead, mdl);
654*7c478bd9Sstevel@tonic-gate 
655*7c478bd9Sstevel@tonic-gate 	if (bufsz < STRUCT_SIZE(head))
656*7c478bd9Sstevel@tonic-gate 		return (set_errno(EINVAL));
657*7c478bd9Sstevel@tonic-gate 
658*7c478bd9Sstevel@tonic-gate 	if ((lock = ipc_lookup(msq_svc, msqid, (kipc_perm_t **)&qp)) == NULL)
659*7c478bd9Sstevel@tonic-gate 		return (set_errno(EINVAL));
660*7c478bd9Sstevel@tonic-gate 
661*7c478bd9Sstevel@tonic-gate 	if (error = ipcperm_access(&qp->msg_perm, MSG_R, CRED())) {
662*7c478bd9Sstevel@tonic-gate 		mutex_exit(lock);
663*7c478bd9Sstevel@tonic-gate 		return (set_errno(error));
664*7c478bd9Sstevel@tonic-gate 	}
665*7c478bd9Sstevel@tonic-gate 	ipc_hold(msq_svc, (kipc_perm_t *)qp);
666*7c478bd9Sstevel@tonic-gate 
667*7c478bd9Sstevel@tonic-gate 	/*
668*7c478bd9Sstevel@tonic-gate 	 * First compute the required buffer size and
669*7c478bd9Sstevel@tonic-gate 	 * the number of messages on the queue.
670*7c478bd9Sstevel@tonic-gate 	 */
671*7c478bd9Sstevel@tonic-gate 	size = nmsg = 0;
672*7c478bd9Sstevel@tonic-gate 	for (mp = list_head(&qp->msg_list); mp;
673*7c478bd9Sstevel@tonic-gate 	    mp = list_next(&qp->msg_list, mp)) {
674*7c478bd9Sstevel@tonic-gate 		if (msgtyp == 0 ||
675*7c478bd9Sstevel@tonic-gate 		    (msgtyp > 0 && msgtyp == mp->msg_type) ||
676*7c478bd9Sstevel@tonic-gate 		    (msgtyp < 0 && mp->msg_type <= -msgtyp)) {
677*7c478bd9Sstevel@tonic-gate 			nmsg++;
678*7c478bd9Sstevel@tonic-gate 			if (mdl == DATAMODEL_NATIVE)
679*7c478bd9Sstevel@tonic-gate 				size += RND(mp->msg_size);
680*7c478bd9Sstevel@tonic-gate 			else
681*7c478bd9Sstevel@tonic-gate 				size += RND32(mp->msg_size);
682*7c478bd9Sstevel@tonic-gate 		}
683*7c478bd9Sstevel@tonic-gate 	}
684*7c478bd9Sstevel@tonic-gate 
685*7c478bd9Sstevel@tonic-gate 	size += STRUCT_SIZE(head) + nmsg * STRUCT_SIZE(mhead);
686*7c478bd9Sstevel@tonic-gate 	if (size > bufsz)
687*7c478bd9Sstevel@tonic-gate 		nmsg = 0;
688*7c478bd9Sstevel@tonic-gate 
689*7c478bd9Sstevel@tonic-gate 	if (nmsg > 0) {
690*7c478bd9Sstevel@tonic-gate 		/*
691*7c478bd9Sstevel@tonic-gate 		 * Mark the messages as being copied.
692*7c478bd9Sstevel@tonic-gate 		 */
693*7c478bd9Sstevel@tonic-gate 		snaplist = (struct msg **)kmem_alloc(nmsg *
694*7c478bd9Sstevel@tonic-gate 		    sizeof (struct msg *), KM_SLEEP);
695*7c478bd9Sstevel@tonic-gate 		i = 0;
696*7c478bd9Sstevel@tonic-gate 		for (mp = list_head(&qp->msg_list); mp;
697*7c478bd9Sstevel@tonic-gate 		    mp = list_next(&qp->msg_list, mp)) {
698*7c478bd9Sstevel@tonic-gate 			if (msgtyp == 0 ||
699*7c478bd9Sstevel@tonic-gate 			    (msgtyp > 0 && msgtyp == mp->msg_type) ||
700*7c478bd9Sstevel@tonic-gate 			    (msgtyp < 0 && mp->msg_type <= -msgtyp)) {
701*7c478bd9Sstevel@tonic-gate 				msg_hold(mp);
702*7c478bd9Sstevel@tonic-gate 				snaplist[i] = mp;
703*7c478bd9Sstevel@tonic-gate 				i++;
704*7c478bd9Sstevel@tonic-gate 			}
705*7c478bd9Sstevel@tonic-gate 		}
706*7c478bd9Sstevel@tonic-gate 	}
707*7c478bd9Sstevel@tonic-gate 	mutex_exit(lock);
708*7c478bd9Sstevel@tonic-gate 
709*7c478bd9Sstevel@tonic-gate 	/*
710*7c478bd9Sstevel@tonic-gate 	 * Copy out the buffer header.
711*7c478bd9Sstevel@tonic-gate 	 */
712*7c478bd9Sstevel@tonic-gate 	STRUCT_FSET(head, msgsnap_size, size);
713*7c478bd9Sstevel@tonic-gate 	STRUCT_FSET(head, msgsnap_nmsg, nmsg);
714*7c478bd9Sstevel@tonic-gate 	if (copyout(STRUCT_BUF(head), buf, STRUCT_SIZE(head)))
715*7c478bd9Sstevel@tonic-gate 		error = EFAULT;
716*7c478bd9Sstevel@tonic-gate 
717*7c478bd9Sstevel@tonic-gate 	buf += STRUCT_SIZE(head);
718*7c478bd9Sstevel@tonic-gate 
719*7c478bd9Sstevel@tonic-gate 	/*
720*7c478bd9Sstevel@tonic-gate 	 * Now copy out the messages one by one.
721*7c478bd9Sstevel@tonic-gate 	 */
722*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < nmsg; i++) {
723*7c478bd9Sstevel@tonic-gate 		mp = snaplist[i];
724*7c478bd9Sstevel@tonic-gate 		if (error == 0) {
725*7c478bd9Sstevel@tonic-gate 			STRUCT_FSET(mhead, msgsnap_mlen, mp->msg_size);
726*7c478bd9Sstevel@tonic-gate 			STRUCT_FSET(mhead, msgsnap_mtype, mp->msg_type);
727*7c478bd9Sstevel@tonic-gate 			if (copyout(STRUCT_BUF(mhead), buf, STRUCT_SIZE(mhead)))
728*7c478bd9Sstevel@tonic-gate 				error = EFAULT;
729*7c478bd9Sstevel@tonic-gate 			buf += STRUCT_SIZE(mhead);
730*7c478bd9Sstevel@tonic-gate 
731*7c478bd9Sstevel@tonic-gate 			if (error == 0 &&
732*7c478bd9Sstevel@tonic-gate 			    mp->msg_size != 0 &&
733*7c478bd9Sstevel@tonic-gate 			    copyout(mp->msg_addr, buf, mp->msg_size))
734*7c478bd9Sstevel@tonic-gate 				error = EFAULT;
735*7c478bd9Sstevel@tonic-gate 			if (mdl == DATAMODEL_NATIVE)
736*7c478bd9Sstevel@tonic-gate 				buf += RND(mp->msg_size);
737*7c478bd9Sstevel@tonic-gate 			else
738*7c478bd9Sstevel@tonic-gate 				buf += RND32(mp->msg_size);
739*7c478bd9Sstevel@tonic-gate 		}
740*7c478bd9Sstevel@tonic-gate 		lock = ipc_lock(msq_svc, qp->msg_perm.ipc_id);
741*7c478bd9Sstevel@tonic-gate 		msg_rele(mp);
742*7c478bd9Sstevel@tonic-gate 		/* Check for msg q deleted or reallocated */
743*7c478bd9Sstevel@tonic-gate 		if (IPC_FREE(&qp->msg_perm))
744*7c478bd9Sstevel@tonic-gate 			error = EIDRM;
745*7c478bd9Sstevel@tonic-gate 		mutex_exit(lock);
746*7c478bd9Sstevel@tonic-gate 	}
747*7c478bd9Sstevel@tonic-gate 
748*7c478bd9Sstevel@tonic-gate 	(void) ipc_lock(msq_svc, qp->msg_perm.ipc_id);
749*7c478bd9Sstevel@tonic-gate 	ipc_rele(msq_svc, (kipc_perm_t *)qp);
750*7c478bd9Sstevel@tonic-gate 
751*7c478bd9Sstevel@tonic-gate 	if (nmsg > 0)
752*7c478bd9Sstevel@tonic-gate 		kmem_free(snaplist, nmsg * sizeof (struct msg *));
753*7c478bd9Sstevel@tonic-gate 
754*7c478bd9Sstevel@tonic-gate 	if (error)
755*7c478bd9Sstevel@tonic-gate 		return (set_errno(error));
756*7c478bd9Sstevel@tonic-gate 	return (0);
757*7c478bd9Sstevel@tonic-gate }
758*7c478bd9Sstevel@tonic-gate 
759*7c478bd9Sstevel@tonic-gate /*
760*7c478bd9Sstevel@tonic-gate  * msgsnd system call.
761*7c478bd9Sstevel@tonic-gate  */
762*7c478bd9Sstevel@tonic-gate static int
763*7c478bd9Sstevel@tonic-gate msgsnd(int msqid, struct ipcmsgbuf *msgp, size_t msgsz, int msgflg)
764*7c478bd9Sstevel@tonic-gate {
765*7c478bd9Sstevel@tonic-gate 	kmsqid_t	*qp;
766*7c478bd9Sstevel@tonic-gate 	kmutex_t	*lock;
767*7c478bd9Sstevel@tonic-gate 	struct msg	*mp = NULL;
768*7c478bd9Sstevel@tonic-gate 	long		type;
769*7c478bd9Sstevel@tonic-gate 	int		error = 0;
770*7c478bd9Sstevel@tonic-gate 	model_t		mdl = get_udatamodel();
771*7c478bd9Sstevel@tonic-gate 	STRUCT_HANDLE(ipcmsgbuf, umsgp);
772*7c478bd9Sstevel@tonic-gate 
773*7c478bd9Sstevel@tonic-gate 	CPU_STATS_ADDQ(CPU, sys, msg, 1);	/* bump msg send/rcv count */
774*7c478bd9Sstevel@tonic-gate 	STRUCT_SET_HANDLE(umsgp, mdl, msgp);
775*7c478bd9Sstevel@tonic-gate 
776*7c478bd9Sstevel@tonic-gate 	if (mdl == DATAMODEL_NATIVE) {
777*7c478bd9Sstevel@tonic-gate 		if (copyin(msgp, &type, sizeof (type)))
778*7c478bd9Sstevel@tonic-gate 			return (set_errno(EFAULT));
779*7c478bd9Sstevel@tonic-gate 	} else {
780*7c478bd9Sstevel@tonic-gate 		int32_t	type32;
781*7c478bd9Sstevel@tonic-gate 		if (copyin(msgp, &type32, sizeof (type32)))
782*7c478bd9Sstevel@tonic-gate 			return (set_errno(EFAULT));
783*7c478bd9Sstevel@tonic-gate 		type = type32;
784*7c478bd9Sstevel@tonic-gate 	}
785*7c478bd9Sstevel@tonic-gate 
786*7c478bd9Sstevel@tonic-gate 	if (type < 1)
787*7c478bd9Sstevel@tonic-gate 		return (set_errno(EINVAL));
788*7c478bd9Sstevel@tonic-gate 
789*7c478bd9Sstevel@tonic-gate 	if ((lock = ipc_lookup(msq_svc, msqid, (kipc_perm_t **)&qp)) == NULL)
790*7c478bd9Sstevel@tonic-gate 		return (set_errno(EINVAL));
791*7c478bd9Sstevel@tonic-gate 	ipc_hold(msq_svc, (kipc_perm_t *)qp);
792*7c478bd9Sstevel@tonic-gate 
793*7c478bd9Sstevel@tonic-gate 	if (msgsz > qp->msg_qbytes) {
794*7c478bd9Sstevel@tonic-gate 		error = EINVAL;
795*7c478bd9Sstevel@tonic-gate 		goto msgsnd_out;
796*7c478bd9Sstevel@tonic-gate 	}
797*7c478bd9Sstevel@tonic-gate 
798*7c478bd9Sstevel@tonic-gate 	if (error = ipcperm_access(&qp->msg_perm, MSG_W, CRED()))
799*7c478bd9Sstevel@tonic-gate 		goto msgsnd_out;
800*7c478bd9Sstevel@tonic-gate 
801*7c478bd9Sstevel@tonic-gate top:
802*7c478bd9Sstevel@tonic-gate 	/*
803*7c478bd9Sstevel@tonic-gate 	 * Allocate space on q, message header, & buffer space.
804*7c478bd9Sstevel@tonic-gate 	 */
805*7c478bd9Sstevel@tonic-gate 	ASSERT(qp->msg_qnum <= qp->msg_qmax);
806*7c478bd9Sstevel@tonic-gate 	while ((msgsz > qp->msg_qbytes - qp->msg_cbytes) ||
807*7c478bd9Sstevel@tonic-gate 	    (qp->msg_qnum == qp->msg_qmax)) {
808*7c478bd9Sstevel@tonic-gate 		int cvres;
809*7c478bd9Sstevel@tonic-gate 
810*7c478bd9Sstevel@tonic-gate 		if (msgflg & IPC_NOWAIT) {
811*7c478bd9Sstevel@tonic-gate 			error = EAGAIN;
812*7c478bd9Sstevel@tonic-gate 			goto msgsnd_out;
813*7c478bd9Sstevel@tonic-gate 		}
814*7c478bd9Sstevel@tonic-gate 
815*7c478bd9Sstevel@tonic-gate 		qp->msg_snd_cnt++;
816*7c478bd9Sstevel@tonic-gate 		cvres = cv_wait_sig(&qp->msg_snd_cv, lock);
817*7c478bd9Sstevel@tonic-gate 		lock = ipc_relock(msq_svc, qp->msg_perm.ipc_id, lock);
818*7c478bd9Sstevel@tonic-gate 		qp->msg_snd_cnt--;
819*7c478bd9Sstevel@tonic-gate 
820*7c478bd9Sstevel@tonic-gate 		if (IPC_FREE(&qp->msg_perm)) {
821*7c478bd9Sstevel@tonic-gate 			error = EIDRM;
822*7c478bd9Sstevel@tonic-gate 			goto msgsnd_out;
823*7c478bd9Sstevel@tonic-gate 		}
824*7c478bd9Sstevel@tonic-gate 
825*7c478bd9Sstevel@tonic-gate 		if (cvres == 0) {
826*7c478bd9Sstevel@tonic-gate 			error = EINTR;
827*7c478bd9Sstevel@tonic-gate 			goto msgsnd_out;
828*7c478bd9Sstevel@tonic-gate 		}
829*7c478bd9Sstevel@tonic-gate 	}
830*7c478bd9Sstevel@tonic-gate 
831*7c478bd9Sstevel@tonic-gate 	if (mp == NULL) {
832*7c478bd9Sstevel@tonic-gate 		int failure;
833*7c478bd9Sstevel@tonic-gate 
834*7c478bd9Sstevel@tonic-gate 		mutex_exit(lock);
835*7c478bd9Sstevel@tonic-gate 		mp = kmem_zalloc(sizeof (struct msg), KM_SLEEP);
836*7c478bd9Sstevel@tonic-gate 		mp->msg_addr = kmem_zalloc(msgsz, KM_SLEEP);
837*7c478bd9Sstevel@tonic-gate 		mp->msg_size = msgsz;
838*7c478bd9Sstevel@tonic-gate 		mp->msg_copycnt = 1;
839*7c478bd9Sstevel@tonic-gate 
840*7c478bd9Sstevel@tonic-gate 		failure = msgsz && (copyin(STRUCT_FADDR(umsgp, mtext),
841*7c478bd9Sstevel@tonic-gate 		    mp->msg_addr, msgsz) == -1);
842*7c478bd9Sstevel@tonic-gate 		lock = ipc_lock(msq_svc, qp->msg_perm.ipc_id);
843*7c478bd9Sstevel@tonic-gate 		if (IPC_FREE(&qp->msg_perm)) {
844*7c478bd9Sstevel@tonic-gate 			error = EIDRM;
845*7c478bd9Sstevel@tonic-gate 			goto msgsnd_out;
846*7c478bd9Sstevel@tonic-gate 		}
847*7c478bd9Sstevel@tonic-gate 		if (failure) {
848*7c478bd9Sstevel@tonic-gate 			error = EFAULT;
849*7c478bd9Sstevel@tonic-gate 			goto msgsnd_out;
850*7c478bd9Sstevel@tonic-gate 		}
851*7c478bd9Sstevel@tonic-gate 		goto top;
852*7c478bd9Sstevel@tonic-gate 	}
853*7c478bd9Sstevel@tonic-gate 
854*7c478bd9Sstevel@tonic-gate 	/*
855*7c478bd9Sstevel@tonic-gate 	 * Everything is available, put msg on q.
856*7c478bd9Sstevel@tonic-gate 	 */
857*7c478bd9Sstevel@tonic-gate 	qp->msg_qnum++;
858*7c478bd9Sstevel@tonic-gate 	qp->msg_cbytes += msgsz;
859*7c478bd9Sstevel@tonic-gate 	qp->msg_lspid = curproc->p_pid;
860*7c478bd9Sstevel@tonic-gate 	qp->msg_stime = gethrestime_sec();
861*7c478bd9Sstevel@tonic-gate 	mp->msg_type = type;
862*7c478bd9Sstevel@tonic-gate 	mp->msg_flags = 0;
863*7c478bd9Sstevel@tonic-gate 	list_insert_tail(&qp->msg_list, mp);
864*7c478bd9Sstevel@tonic-gate 	if (qp->msg_rcv_cnt)
865*7c478bd9Sstevel@tonic-gate 		cv_broadcast(&qp->msg_rcv_cv);
866*7c478bd9Sstevel@tonic-gate 
867*7c478bd9Sstevel@tonic-gate msgsnd_out:
868*7c478bd9Sstevel@tonic-gate 	ipc_rele(msq_svc, (kipc_perm_t *)qp);	/* drops lock */
869*7c478bd9Sstevel@tonic-gate 
870*7c478bd9Sstevel@tonic-gate 	if (error) {
871*7c478bd9Sstevel@tonic-gate 		if (mp)
872*7c478bd9Sstevel@tonic-gate 			msg_rele(mp);
873*7c478bd9Sstevel@tonic-gate 		return (set_errno(error));
874*7c478bd9Sstevel@tonic-gate 	}
875*7c478bd9Sstevel@tonic-gate 
876*7c478bd9Sstevel@tonic-gate 	return (0);
877*7c478bd9Sstevel@tonic-gate }
878*7c478bd9Sstevel@tonic-gate 
879*7c478bd9Sstevel@tonic-gate /*
880*7c478bd9Sstevel@tonic-gate  * msgsys - System entry point for msgctl, msgget, msgrcv, and msgsnd
881*7c478bd9Sstevel@tonic-gate  * system calls.
882*7c478bd9Sstevel@tonic-gate  */
883*7c478bd9Sstevel@tonic-gate static ssize_t
884*7c478bd9Sstevel@tonic-gate msgsys(int opcode, uintptr_t a1, uintptr_t a2, uintptr_t a3,
885*7c478bd9Sstevel@tonic-gate 	uintptr_t a4, uintptr_t a5)
886*7c478bd9Sstevel@tonic-gate {
887*7c478bd9Sstevel@tonic-gate 	ssize_t error;
888*7c478bd9Sstevel@tonic-gate 
889*7c478bd9Sstevel@tonic-gate 	switch (opcode) {
890*7c478bd9Sstevel@tonic-gate 	case MSGGET:
891*7c478bd9Sstevel@tonic-gate 		error = msgget((key_t)a1, (int)a2);
892*7c478bd9Sstevel@tonic-gate 		break;
893*7c478bd9Sstevel@tonic-gate 	case MSGCTL:
894*7c478bd9Sstevel@tonic-gate 		error = msgctl((int)a1, (int)a2, (void *)a3);
895*7c478bd9Sstevel@tonic-gate 		break;
896*7c478bd9Sstevel@tonic-gate 	case MSGRCV:
897*7c478bd9Sstevel@tonic-gate 		error = msgrcv((int)a1, (struct ipcmsgbuf *)a2,
898*7c478bd9Sstevel@tonic-gate 		    (size_t)a3, (long)a4, (int)a5);
899*7c478bd9Sstevel@tonic-gate 		break;
900*7c478bd9Sstevel@tonic-gate 	case MSGSND:
901*7c478bd9Sstevel@tonic-gate 		error = msgsnd((int)a1, (struct ipcmsgbuf *)a2,
902*7c478bd9Sstevel@tonic-gate 		    (size_t)a3, (int)a4);
903*7c478bd9Sstevel@tonic-gate 		break;
904*7c478bd9Sstevel@tonic-gate 	case MSGIDS:
905*7c478bd9Sstevel@tonic-gate 		error = msgids((int *)a1, (uint_t)a2, (uint_t *)a3);
906*7c478bd9Sstevel@tonic-gate 		break;
907*7c478bd9Sstevel@tonic-gate 	case MSGSNAP:
908*7c478bd9Sstevel@tonic-gate 		error = msgsnap((int)a1, (caddr_t)a2, (size_t)a3, (long)a4);
909*7c478bd9Sstevel@tonic-gate 		break;
910*7c478bd9Sstevel@tonic-gate 	default:
911*7c478bd9Sstevel@tonic-gate 		error = set_errno(EINVAL);
912*7c478bd9Sstevel@tonic-gate 		break;
913*7c478bd9Sstevel@tonic-gate 	}
914*7c478bd9Sstevel@tonic-gate 
915*7c478bd9Sstevel@tonic-gate 	return (error);
916*7c478bd9Sstevel@tonic-gate }
917*7c478bd9Sstevel@tonic-gate 
918*7c478bd9Sstevel@tonic-gate #ifdef	_SYSCALL32_IMPL
919*7c478bd9Sstevel@tonic-gate /*
920*7c478bd9Sstevel@tonic-gate  * msgsys32 - System entry point for msgctl, msgget, msgrcv, and msgsnd
921*7c478bd9Sstevel@tonic-gate  * system calls for 32-bit callers on LP64 kernel.
922*7c478bd9Sstevel@tonic-gate  */
923*7c478bd9Sstevel@tonic-gate static ssize32_t
924*7c478bd9Sstevel@tonic-gate msgsys32(int opcode, uint32_t a1, uint32_t a2, uint32_t a3,
925*7c478bd9Sstevel@tonic-gate 	uint32_t a4, uint32_t a5)
926*7c478bd9Sstevel@tonic-gate {
927*7c478bd9Sstevel@tonic-gate 	ssize_t error;
928*7c478bd9Sstevel@tonic-gate 
929*7c478bd9Sstevel@tonic-gate 	switch (opcode) {
930*7c478bd9Sstevel@tonic-gate 	case MSGGET:
931*7c478bd9Sstevel@tonic-gate 		error = msgget((key_t)a1, (int)a2);
932*7c478bd9Sstevel@tonic-gate 		break;
933*7c478bd9Sstevel@tonic-gate 	case MSGCTL:
934*7c478bd9Sstevel@tonic-gate 		error = msgctl((int)a1, (int)a2, (void *)(uintptr_t)a3);
935*7c478bd9Sstevel@tonic-gate 		break;
936*7c478bd9Sstevel@tonic-gate 	case MSGRCV:
937*7c478bd9Sstevel@tonic-gate 		error = msgrcv((int)a1, (struct ipcmsgbuf *)(uintptr_t)a2,
938*7c478bd9Sstevel@tonic-gate 		    (size_t)a3, (long)(int32_t)a4, (int)a5);
939*7c478bd9Sstevel@tonic-gate 		break;
940*7c478bd9Sstevel@tonic-gate 	case MSGSND:
941*7c478bd9Sstevel@tonic-gate 		error = msgsnd((int)a1, (struct ipcmsgbuf *)(uintptr_t)a2,
942*7c478bd9Sstevel@tonic-gate 		    (size_t)(int32_t)a3, (int)a4);
943*7c478bd9Sstevel@tonic-gate 		break;
944*7c478bd9Sstevel@tonic-gate 	case MSGIDS:
945*7c478bd9Sstevel@tonic-gate 		error = msgids((int *)(uintptr_t)a1, (uint_t)a2,
946*7c478bd9Sstevel@tonic-gate 		    (uint_t *)(uintptr_t)a3);
947*7c478bd9Sstevel@tonic-gate 		break;
948*7c478bd9Sstevel@tonic-gate 	case MSGSNAP:
949*7c478bd9Sstevel@tonic-gate 		error = msgsnap((int)a1, (caddr_t)(uintptr_t)a2, (size_t)a3,
950*7c478bd9Sstevel@tonic-gate 		    (long)(int32_t)a4);
951*7c478bd9Sstevel@tonic-gate 		break;
952*7c478bd9Sstevel@tonic-gate 	default:
953*7c478bd9Sstevel@tonic-gate 		error = set_errno(EINVAL);
954*7c478bd9Sstevel@tonic-gate 		break;
955*7c478bd9Sstevel@tonic-gate 	}
956*7c478bd9Sstevel@tonic-gate 
957*7c478bd9Sstevel@tonic-gate 	return (error);
958*7c478bd9Sstevel@tonic-gate }
959*7c478bd9Sstevel@tonic-gate #endif	/* SYSCALL32_IMPL */
960