msg.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Inter-Process Communication Message Facility.
*
*
* Resource controls
* -----------------
*
* Control: project.max-msg-ids (rc_project_msgmni)
* Description: Maximum number of message queue ids allowed a project.
*
* When msgget() is used to allocate a message queue, one id is
* allocated. If the id allocation doesn't succeed, msgget() fails
* and errno is set to ENOSPC. Upon successful msgctl(, IPC_RMID)
* the id is deallocated.
*
* Control: process.max-msg-qbytes (rc_process_msgmnb)
* Description: Maximum number of bytes of messages on a message queue.
*
* When msgget() successfully allocates a message queue, the minimum
* enforced value of this limit is used to initialize msg_qbytes.
*
* Control: process.max-msg-messages (rc_process_msgtql)
* Description: Maximum number of messages on a message queue.
*
* When msgget() successfully allocates a message queue, the minimum
* enforced value of this limit is used to initialize a per-queue
* limit on the number of messages.
*/
#include <sys/ipc_impl.h>
#include <sys/msg_impl.h>
#include <sys/sysmacros.h>
/*
* The following tunables are obsolete. Though for compatibility we
* still read and interpret msginfo_msgmnb, msginfo_msgmni, and
* msginfo_msgtql (see os/project.c and os/rctl_proc.c), the preferred
* mechanism for administrating the IPC Message facility is through the
* resource controls described at the top of this file.
*/
int msginfo_msgmap = 0; /* (obsolete) */
extern rctl_hndl_t rc_project_msgmni;
extern rctl_hndl_t rc_process_msgmnb;
extern rctl_hndl_t rc_process_msgtql;
static ipc_service_t *msq_svc;
static zone_key_t msg_zone_key;
static void msg_dtor(kipc_perm_t *);
static void msg_rmid(kipc_perm_t *);
static void msg_remove_zone(zoneid_t, void *);
/*
* Module linkage information for the kernel.
*/
static struct sysent ipcmsg_sysent = {
6,
#ifdef _LP64
#else
#endif
(int (*)())msgsys
};
#ifdef _SYSCALL32_IMPL
static struct sysent ipcmsg_sysent32 = {
6,
(int (*)())msgsys32
};
#endif /* _SYSCALL32_IMPL */
};
#ifdef _SYSCALL32_IMPL
};
#endif
static struct modlinkage modlinkage = {
&modlsys,
#ifdef _SYSCALL32_IMPL
#endif
};
int
_init(void)
{
int result;
return (0);
(void) zone_key_delete(msg_zone_key);
return (result);
}
int
_fini(void)
{
return (EBUSY);
}
int
{
}
static void
{
}
/*
* msg_rele - decrement the reference count on the message. When count
* reaches zero, free message header and contents.
*/
static void
{
}
}
/*
* msgunlink - Unlink msg from queue, decrement byte count and wake up anyone
* waiting for free bytes on queue.
*
* Called with queue locked.
*/
static void
{
/* Wake up waiting writers */
if (qp->msg_snd_cnt)
}
static void
{
if (qp->msg_rcv_cnt)
if (qp->msg_snd_cnt)
}
/*
* msgctl system call.
*
* gets q lock (via ipc_lookup), releases before return.
* may call users of msg_lock
*/
static int
{
int error;
struct msqid_ds64 ds64;
/*
* Perform pre- or non-lookup actions (e.g. copyins, RMID).
*/
switch (cmd) {
case IPC_SET:
break;
case IPC_SET64:
break;
case IPC_RMID:
return (0);
}
/*
* get msqid_ds for this msgid
*/
switch (cmd) {
case IPC_SET:
secpolicy_ipc_config(cr) != 0) {
}
}
break;
case IPC_STAT:
}
if (qp->msg_rcv_cnt)
if (qp->msg_snd_cnt)
break;
case IPC_SET64:
secpolicy_ipc_config(cr) != 0 &&
}
}
break;
case IPC_STAT64:
if (qp->msg_rcv_cnt)
if (qp->msg_snd_cnt)
break;
default:
}
/*
* Do copyout last (after releasing mutex).
*/
switch (cmd) {
case IPC_STAT:
break;
case IPC_STAT64:
break;
}
return (0);
}
/*
* Remove all message queues associated with a given zone. Called by
* zone_shutdown when the zone is halted.
*/
/*ARGSUSED1*/
static void
{
}
/*
* msgget system call.
*/
static int
{
top:
(kipc_perm_t *)qp)) {
goto top;
}
}
#ifdef C2_AUDIT
if (audit_active)
#endif
return (id);
}
/*
* msgrcv system call.
*/
static ssize_t
{
int cvres;
goto msgrcv_out;
if (msgtyp == 0) {
} else {
if (msgtyp > 0) {
continue;
break;
}
continue;
}
}
}
if (smp) {
/*
* Message found.
*/
/*
* No one else is copying this message. Copy it.
*/
if ((msgflg & MSG_NOERROR) == 0) {
goto msgrcv_out;
} else {
}
} else {
}
/*
* Mark message as being copied out. Release mutex
* while copying out.
*/
if (mdl == DATAMODEL_NATIVE) {
} else {
/*
* 32-bit callers need an imploded msg type.
*/
sizeof (msg_type32));
}
/*
* Reclaim mutex, make sure queue still exists,
* and remove message.
*/
goto msgrcv_out;
}
if (copyerror) {
goto msgrcv_out;
}
goto msgrcv_out;
}
} else {
/*
* No message found.
*/
if (msgflg & IPC_NOWAIT) {
goto msgrcv_out;
}
}
/* Wait for new message */
qp->msg_rcv_cnt++;
qp->msg_rcv_cnt--;
goto msgrcv_out;
}
if (cvres == 0) {
goto msgrcv_out;
}
goto findmsg;
if (error)
}
/*
* msgids system call.
*/
static int
{
int error;
return (0);
}
/*
* msgsnap system call.
*/
static int
{
int error, i;
}
/*
* First compute the required buffer size and
* the number of messages on the queue.
*/
if (msgtyp == 0 ||
nmsg++;
if (mdl == DATAMODEL_NATIVE)
else
}
}
nmsg = 0;
if (nmsg > 0) {
/*
* Mark the messages as being copied.
*/
i = 0;
if (msgtyp == 0 ||
i++;
}
}
}
/*
* Copy out the buffer header.
*/
/*
* Now copy out the messages one by one.
*/
for (i = 0; i < nmsg; i++) {
if (error == 0) {
if (error == 0 &&
if (mdl == DATAMODEL_NATIVE)
else
}
/* Check for msg q deleted or reallocated */
}
if (nmsg > 0)
if (error)
return (0);
}
/*
* msgsnd system call.
*/
static int
{
long type;
int error = 0;
if (mdl == DATAMODEL_NATIVE) {
} else {
}
if (type < 1)
goto msgsnd_out;
}
goto msgsnd_out;
top:
/*
* Allocate space on q, message header, & buffer space.
*/
int cvres;
if (msgflg & IPC_NOWAIT) {
goto msgsnd_out;
}
qp->msg_snd_cnt++;
qp->msg_snd_cnt--;
goto msgsnd_out;
}
if (cvres == 0) {
goto msgsnd_out;
}
}
int failure;
goto msgsnd_out;
}
if (failure) {
goto msgsnd_out;
}
goto top;
}
/*
* Everything is available, put msg on q.
*/
if (qp->msg_rcv_cnt)
if (error) {
if (mp)
}
return (0);
}
/*
* msgsys - System entry point for msgctl, msgget, msgrcv, and msgsnd
* system calls.
*/
static ssize_t
{
switch (opcode) {
case MSGGET:
break;
case MSGCTL:
break;
case MSGRCV:
break;
case MSGSND:
break;
case MSGIDS:
break;
case MSGSNAP:
break;
default:
break;
}
return (error);
}
#ifdef _SYSCALL32_IMPL
/*
* msgsys32 - System entry point for msgctl, msgget, msgrcv, and msgsnd
* system calls for 32-bit callers on LP64 kernel.
*/
static ssize32_t
{
switch (opcode) {
case MSGGET:
break;
case MSGCTL:
break;
case MSGRCV:
break;
case MSGSND:
break;
case MSGIDS:
break;
case MSGSNAP:
break;
default:
break;
}
return (error);
}
#endif /* SYSCALL32_IMPL */