Second of several commits to allow kernel System V IPC data structures

to be modified and extended without breaking the user space ABI:

Use _kernel variants on _ds structures for System V sempahores, message
queues, and shared memory.  When interfacing with userspace, export
only the _ds subsets of the _kernel data structures.  A lot of search
and replace.

Define the message structure in the _KERNEL portion of msg.h so that it
can be used by other kernel consumers, but not exposed to user space.

Submitted by:	Dandekar Hrishikesh <rishi_dandekar at sbcglobal dot net>
Obtained from:	TrustedBSD Project
Sponsored by:	DARPA, SPAWAR, McAfee Research
This commit is contained in:
Robert Watson 2004-11-12 13:23:47 +00:00
parent 0931d0a9f8
commit 921d05b90d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=137613
4 changed files with 353 additions and 349 deletions

View File

@ -57,16 +57,6 @@ static sy_call_t *msgcalls[] = {
(sy_call_t *)msgsnd, (sy_call_t *)msgrcv
};
struct msg {
struct msg *msg_next; /* next msg in the chain */
long msg_type; /* type of this message */
/* >0 -> type of this message */
/* 0 -> free header */
u_short msg_ts; /* size of this message */
short msg_spot; /* location of start of msg in buffer */
};
#ifndef MSGSSZ
#define MSGSSZ 8 /* Each segment must be 2^N long */
#endif
@ -130,7 +120,7 @@ static struct msg *free_msghdrs;/* list of free msg headers */
static char *msgpool; /* MSGMAX byte long msg buffer pool */
static struct msgmap *msgmaps; /* MSGSEG msgmap structures */
static struct msg *msghdrs; /* MSGTQL msg headers */
static struct msqid_ds *msqids; /* MSGMNI msqid_ds struct's */
static struct msqid_kernel *msqids; /* MSGMNI msqid_kernel struct's */
static struct mtx msq_mtx; /* global mutex for message queues. */
static void
@ -152,7 +142,8 @@ msginit()
msghdrs = malloc(sizeof(struct msg) * msginfo.msgtql, M_MSG, M_WAITOK);
if (msghdrs == NULL)
panic("msghdrs is NULL");
msqids = malloc(sizeof(struct msqid_ds) * msginfo.msgmni, M_MSG, M_WAITOK);
msqids = malloc(sizeof(struct msqid_kernel) * msginfo.msgmni, M_MSG,
M_WAITOK);
if (msqids == NULL)
panic("msqids is NULL");
@ -202,9 +193,9 @@ msginit()
panic("msqids is NULL");
for (i = 0; i < msginfo.msgmni; i++) {
msqids[i].msg_qbytes = 0; /* implies entry is available */
msqids[i].msg_perm.seq = 0; /* reset to a known value */
msqids[i].msg_perm.mode = 0;
msqids[i].u.msg_qbytes = 0; /* implies entry is available */
msqids[i].u.msg_perm.seq = 0; /* reset to a known value */
msqids[i].u.msg_perm.mode = 0;
}
mtx_init(&msq_mtx, "msq", NULL, MTX_DEF);
}
@ -212,7 +203,7 @@ msginit()
static int
msgunload()
{
struct msqid_ds *msqptr;
struct msqid_kernel *msqkptr;
int msqid;
for (msqid = 0; msqid < msginfo.msgmni; msqid++) {
@ -222,9 +213,9 @@ msgunload()
* they are copying the message in/out. We can't
* re-use the entry until they release it.
*/
msqptr = &msqids[msqid];
if (msqptr->msg_qbytes != 0 ||
(msqptr->msg_perm.mode & MSG_LOCKED) != 0)
msqkptr = &msqids[msqid];
if (msqkptr->u.msg_qbytes != 0 ||
(msqkptr->u.msg_perm.mode & MSG_LOCKED) != 0)
break;
}
if (msqid != msginfo.msgmni)
@ -350,7 +341,7 @@ msgctl(td, uap)
struct msqid_ds *user_msqptr = uap->buf;
int rval, error;
struct msqid_ds msqbuf;
register struct msqid_ds *msqptr;
register struct msqid_kernel *msqkptr;
DPRINTF(("call to msgctl(%d, %d, 0x%x)\n", msqid, cmd, user_msqptr));
if (!jail_sysvipc_allowed && jailed(td->td_ucred))
@ -367,15 +358,15 @@ msgctl(td, uap)
(error = copyin(user_msqptr, &msqbuf, sizeof(msqbuf))) != 0)
return (error);
msqptr = &msqids[msqid];
msqkptr = &msqids[msqid];
mtx_lock(&msq_mtx);
if (msqptr->msg_qbytes == 0) {
if (msqkptr->u.msg_qbytes == 0) {
DPRINTF(("no such msqid\n"));
error = EINVAL;
goto done2;
}
if (msqptr->msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) {
if (msqkptr->u.msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) {
DPRINTF(("wrong sequence number\n"));
error = EINVAL;
goto done2;
@ -389,37 +380,38 @@ msgctl(td, uap)
case IPC_RMID:
{
struct msg *msghdr;
if ((error = ipcperm(td, &msqptr->msg_perm, IPC_M)))
if ((error = ipcperm(td, &msqkptr->u.msg_perm, IPC_M)))
goto done2;
/* Free the message headers */
msghdr = msqptr->msg_first;
msghdr = msqkptr->u.msg_first;
while (msghdr != NULL) {
struct msg *msghdr_tmp;
/* Free the segments of each message */
msqptr->msg_cbytes -= msghdr->msg_ts;
msqptr->msg_qnum--;
msqkptr->u.msg_cbytes -= msghdr->msg_ts;
msqkptr->u.msg_qnum--;
msghdr_tmp = msghdr;
msghdr = msghdr->msg_next;
msg_freehdr(msghdr_tmp);
}
if (msqptr->msg_cbytes != 0)
if (msqkptr->u.msg_cbytes != 0)
panic("msg_cbytes is screwed up");
if (msqptr->msg_qnum != 0)
if (msqkptr->u.msg_qnum != 0)
panic("msg_qnum is screwed up");
msqptr->msg_qbytes = 0; /* Mark it as free */
msqkptr->u.msg_qbytes = 0; /* Mark it as free */
wakeup(msqptr);
wakeup(msqkptr);
}
break;
case IPC_SET:
if ((error = ipcperm(td, &msqptr->msg_perm, IPC_M)))
if ((error = ipcperm(td, &msqkptr->u.msg_perm, IPC_M)))
goto done2;
if (msqbuf.msg_qbytes > msqptr->msg_qbytes) {
if (msqbuf.msg_qbytes > msqkptr->u.msg_qbytes) {
error = suser(td);
if (error)
goto done2;
@ -434,16 +426,16 @@ msgctl(td, uap)
error = EINVAL; /* non-standard errno! */
goto done2;
}
msqptr->msg_perm.uid = msqbuf.msg_perm.uid; /* change the owner */
msqptr->msg_perm.gid = msqbuf.msg_perm.gid; /* change the owner */
msqptr->msg_perm.mode = (msqptr->msg_perm.mode & ~0777) |
msqkptr->u.msg_perm.uid = msqbuf.msg_perm.uid; /* change the owner */
msqkptr->u.msg_perm.gid = msqbuf.msg_perm.gid; /* change the owner */
msqkptr->u.msg_perm.mode = (msqkptr->u.msg_perm.mode & ~0777) |
(msqbuf.msg_perm.mode & 0777);
msqptr->msg_qbytes = msqbuf.msg_qbytes;
msqptr->msg_ctime = time_second;
msqkptr->u.msg_qbytes = msqbuf.msg_qbytes;
msqkptr->u.msg_ctime = time_second;
break;
case IPC_STAT:
if ((error = ipcperm(td, &msqptr->msg_perm, IPC_R))) {
if ((error = ipcperm(td, &msqkptr->u.msg_perm, IPC_R))) {
DPRINTF(("requester doesn't have read access\n"));
goto done2;
}
@ -460,7 +452,7 @@ msgctl(td, uap)
done2:
mtx_unlock(&msq_mtx);
if (cmd == IPC_STAT && error == 0)
error = copyout(msqptr, user_msqptr, sizeof(struct msqid_ds));
error = copyout(&(msqkptr->u), user_msqptr, sizeof(struct msqid_ds));
return(error);
}
@ -483,7 +475,7 @@ msgget(td, uap)
int key = uap->key;
int msgflg = uap->msgflg;
struct ucred *cred = td->td_ucred;
register struct msqid_ds *msqptr = NULL;
register struct msqid_kernel *msqkptr = NULL;
DPRINTF(("msgget(0x%x, 0%o)\n", key, msgflg));
@ -493,9 +485,9 @@ msgget(td, uap)
mtx_lock(&msq_mtx);
if (key != IPC_PRIVATE) {
for (msqid = 0; msqid < msginfo.msgmni; msqid++) {
msqptr = &msqids[msqid];
if (msqptr->msg_qbytes != 0 &&
msqptr->msg_perm.key == key)
msqkptr = &msqids[msqid];
if (msqkptr->u.msg_qbytes != 0 &&
msqkptr->u.msg_perm.key == key)
break;
}
if (msqid < msginfo.msgmni) {
@ -505,7 +497,8 @@ msgget(td, uap)
error = EEXIST;
goto done2;
}
if ((error = ipcperm(td, &msqptr->msg_perm, msgflg & 0700))) {
if ((error = ipcperm(td, &msqkptr->u.msg_perm,
msgflg & 0700))) {
DPRINTF(("requester doesn't have 0%o access\n",
msgflg & 0700));
goto done2;
@ -523,9 +516,9 @@ msgget(td, uap)
* they are copying the message in/out. We can't
* re-use the entry until they release it.
*/
msqptr = &msqids[msqid];
if (msqptr->msg_qbytes == 0 &&
(msqptr->msg_perm.mode & MSG_LOCKED) == 0)
msqkptr = &msqids[msqid];
if (msqkptr->u.msg_qbytes == 0 &&
(msqkptr->u.msg_perm.mode & MSG_LOCKED) == 0)
break;
}
if (msqid == msginfo.msgmni) {
@ -534,24 +527,24 @@ msgget(td, uap)
goto done2;
}
DPRINTF(("msqid %d is available\n", msqid));
msqptr->msg_perm.key = key;
msqptr->msg_perm.cuid = cred->cr_uid;
msqptr->msg_perm.uid = cred->cr_uid;
msqptr->msg_perm.cgid = cred->cr_gid;
msqptr->msg_perm.gid = cred->cr_gid;
msqptr->msg_perm.mode = (msgflg & 0777);
msqkptr->u.msg_perm.key = key;
msqkptr->u.msg_perm.cuid = cred->cr_uid;
msqkptr->u.msg_perm.uid = cred->cr_uid;
msqkptr->u.msg_perm.cgid = cred->cr_gid;
msqkptr->u.msg_perm.gid = cred->cr_gid;
msqkptr->u.msg_perm.mode = (msgflg & 0777);
/* Make sure that the returned msqid is unique */
msqptr->msg_perm.seq = (msqptr->msg_perm.seq + 1) & 0x7fff;
msqptr->msg_first = NULL;
msqptr->msg_last = NULL;
msqptr->msg_cbytes = 0;
msqptr->msg_qnum = 0;
msqptr->msg_qbytes = msginfo.msgmnb;
msqptr->msg_lspid = 0;
msqptr->msg_lrpid = 0;
msqptr->msg_stime = 0;
msqptr->msg_rtime = 0;
msqptr->msg_ctime = time_second;
msqkptr->u.msg_perm.seq = (msqkptr->u.msg_perm.seq + 1) & 0x7fff;
msqkptr->u.msg_first = NULL;
msqkptr->u.msg_last = NULL;
msqkptr->u.msg_cbytes = 0;
msqkptr->u.msg_qnum = 0;
msqkptr->u.msg_qbytes = msginfo.msgmnb;
msqkptr->u.msg_lspid = 0;
msqkptr->u.msg_lrpid = 0;
msqkptr->u.msg_stime = 0;
msqkptr->u.msg_rtime = 0;
msqkptr->u.msg_ctime = time_second;
} else {
DPRINTF(("didn't find it and wasn't asked to create it\n"));
error = ENOENT;
@ -560,7 +553,7 @@ msgget(td, uap)
found:
/* Construct the unique msqid */
td->td_retval[0] = IXSEQ_TO_IPCID(msqid, msqptr->msg_perm);
td->td_retval[0] = IXSEQ_TO_IPCID(msqid, msqkptr->u.msg_perm);
done2:
mtx_unlock(&msq_mtx);
return (error);
@ -588,7 +581,7 @@ msgsnd(td, uap)
size_t msgsz = uap->msgsz;
int msgflg = uap->msgflg;
int segs_needed, error = 0;
register struct msqid_ds *msqptr;
register struct msqid_kernel *msqkptr;
register struct msg *msghdr;
short next;
@ -607,19 +600,19 @@ msgsnd(td, uap)
goto done2;
}
msqptr = &msqids[msqid];
if (msqptr->msg_qbytes == 0) {
msqkptr = &msqids[msqid];
if (msqkptr->u.msg_qbytes == 0) {
DPRINTF(("no such message queue id\n"));
error = EINVAL;
goto done2;
}
if (msqptr->msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) {
if (msqkptr->u.msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) {
DPRINTF(("wrong sequence number\n"));
error = EINVAL;
goto done2;
}
if ((error = ipcperm(td, &msqptr->msg_perm, IPC_W))) {
if ((error = ipcperm(td, &msqkptr->u.msg_perm, IPC_W))) {
DPRINTF(("requester doesn't have write access\n"));
goto done2;
}
@ -635,17 +628,17 @@ msgsnd(td, uap)
* (inside this loop in case msg_qbytes changes while we sleep)
*/
if (msgsz > msqptr->msg_qbytes) {
DPRINTF(("msgsz > msqptr->msg_qbytes\n"));
if (msgsz > msqkptr->u.msg_qbytes) {
DPRINTF(("msgsz > msqkptr->u.msg_qbytes\n"));
error = EINVAL;
goto done2;
}
if (msqptr->msg_perm.mode & MSG_LOCKED) {
if (msqkptr->u.msg_perm.mode & MSG_LOCKED) {
DPRINTF(("msqid is locked\n"));
need_more_resources = 1;
}
if (msgsz + msqptr->msg_cbytes > msqptr->msg_qbytes) {
if (msgsz + msqkptr->u.msg_cbytes > msqkptr->u.msg_qbytes) {
DPRINTF(("msgsz + msg_cbytes > msg_qbytes\n"));
need_more_resources = 1;
}
@ -668,22 +661,22 @@ msgsnd(td, uap)
goto done2;
}
if ((msqptr->msg_perm.mode & MSG_LOCKED) != 0) {
if ((msqkptr->u.msg_perm.mode & MSG_LOCKED) != 0) {
DPRINTF(("we don't own the msqid_ds\n"));
we_own_it = 0;
} else {
/* Force later arrivals to wait for our
request */
DPRINTF(("we own the msqid_ds\n"));
msqptr->msg_perm.mode |= MSG_LOCKED;
msqkptr->u.msg_perm.mode |= MSG_LOCKED;
we_own_it = 1;
}
DPRINTF(("goodnight\n"));
error = msleep(msqptr, &msq_mtx, (PZERO - 4) | PCATCH,
error = msleep(msqkptr, &msq_mtx, (PZERO - 4) | PCATCH,
"msgwait", 0);
DPRINTF(("good morning, error=%d\n", error));
if (we_own_it)
msqptr->msg_perm.mode &= ~MSG_LOCKED;
msqkptr->u.msg_perm.mode &= ~MSG_LOCKED;
if (error != 0) {
DPRINTF(("msgsnd: interrupted system call\n"));
error = EINTR;
@ -694,7 +687,7 @@ msgsnd(td, uap)
* Make sure that the msq queue still exists
*/
if (msqptr->msg_qbytes == 0) {
if (msqkptr->u.msg_qbytes == 0) {
DPRINTF(("msqid deleted\n"));
error = EIDRM;
goto done2;
@ -711,11 +704,11 @@ msgsnd(td, uap)
* Make sure!
*/
if (msqptr->msg_perm.mode & MSG_LOCKED)
if (msqkptr->u.msg_perm.mode & MSG_LOCKED)
panic("msg_perm.mode & MSG_LOCKED");
if (segs_needed > nfree_msgmaps)
panic("segs_needed > nfree_msgmaps");
if (msgsz + msqptr->msg_cbytes > msqptr->msg_qbytes)
if (msgsz + msqkptr->u.msg_cbytes > msqkptr->u.msg_qbytes)
panic("msgsz + msg_cbytes > msg_qbytes");
if (free_msghdrs == NULL)
panic("no more msghdrs");
@ -725,9 +718,9 @@ msgsnd(td, uap)
* message
*/
if ((msqptr->msg_perm.mode & MSG_LOCKED) != 0)
if ((msqkptr->u.msg_perm.mode & MSG_LOCKED) != 0)
panic("msqid_ds is already locked");
msqptr->msg_perm.mode |= MSG_LOCKED;
msqkptr->u.msg_perm.mode |= MSG_LOCKED;
/*
* Allocate a message header
@ -770,8 +763,8 @@ msgsnd(td, uap)
mtx_lock(&msq_mtx);
DPRINTF(("error %d copying the message type\n", error));
msg_freehdr(msghdr);
msqptr->msg_perm.mode &= ~MSG_LOCKED;
wakeup(msqptr);
msqkptr->u.msg_perm.mode &= ~MSG_LOCKED;
wakeup(msqkptr);
goto done2;
}
mtx_lock(&msq_mtx);
@ -783,8 +776,8 @@ msgsnd(td, uap)
if (msghdr->msg_type < 1) {
msg_freehdr(msghdr);
msqptr->msg_perm.mode &= ~MSG_LOCKED;
wakeup(msqptr);
msqkptr->u.msg_perm.mode &= ~MSG_LOCKED;
wakeup(msqkptr);
DPRINTF(("mtype (%d) < 1\n", msghdr->msg_type));
error = EINVAL;
goto done2;
@ -812,8 +805,8 @@ msgsnd(td, uap)
DPRINTF(("error %d copying in message segment\n",
error));
msg_freehdr(msghdr);
msqptr->msg_perm.mode &= ~MSG_LOCKED;
wakeup(msqptr);
msqkptr->u.msg_perm.mode &= ~MSG_LOCKED;
wakeup(msqkptr);
goto done2;
}
mtx_lock(&msq_mtx);
@ -828,15 +821,15 @@ msgsnd(td, uap)
* We've got the message. Unlock the msqid_ds.
*/
msqptr->msg_perm.mode &= ~MSG_LOCKED;
msqkptr->u.msg_perm.mode &= ~MSG_LOCKED;
/*
* Make sure that the msqid_ds is still allocated.
*/
if (msqptr->msg_qbytes == 0) {
if (msqkptr->u.msg_qbytes == 0) {
msg_freehdr(msghdr);
wakeup(msqptr);
wakeup(msqkptr);
error = EIDRM;
goto done2;
}
@ -844,22 +837,21 @@ msgsnd(td, uap)
/*
* Put the message into the queue
*/
if (msqptr->msg_first == NULL) {
msqptr->msg_first = msghdr;
msqptr->msg_last = msghdr;
if (msqkptr->u.msg_first == NULL) {
msqkptr->u.msg_first = msghdr;
msqkptr->u.msg_last = msghdr;
} else {
msqptr->msg_last->msg_next = msghdr;
msqptr->msg_last = msghdr;
msqkptr->u.msg_last->msg_next = msghdr;
msqkptr->u.msg_last = msghdr;
}
msqptr->msg_last->msg_next = NULL;
msqkptr->u.msg_last->msg_next = NULL;
msqptr->msg_cbytes += msghdr->msg_ts;
msqptr->msg_qnum++;
msqptr->msg_lspid = td->td_proc->p_pid;
msqptr->msg_stime = time_second;
msqkptr->u.msg_cbytes += msghdr->msg_ts;
msqkptr->u.msg_qnum++;
msqkptr->u.msg_lspid = td->td_proc->p_pid;
msqkptr->u.msg_stime = time_second;
wakeup(msqptr);
wakeup(msqkptr);
td->td_retval[0] = 0;
done2:
mtx_unlock(&msq_mtx);
@ -890,7 +882,7 @@ msgrcv(td, uap)
long msgtyp = uap->msgtyp;
int msgflg = uap->msgflg;
size_t len;
register struct msqid_ds *msqptr;
register struct msqid_kernel *msqkptr;
register struct msg *msghdr;
int error = 0;
short next;
@ -909,20 +901,20 @@ msgrcv(td, uap)
return (EINVAL);
}
msqptr = &msqids[msqid];
msqkptr = &msqids[msqid];
mtx_lock(&msq_mtx);
if (msqptr->msg_qbytes == 0) {
if (msqkptr->u.msg_qbytes == 0) {
DPRINTF(("no such message queue id\n"));
error = EINVAL;
goto done2;
}
if (msqptr->msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) {
if (msqkptr->u.msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) {
DPRINTF(("wrong sequence number\n"));
error = EINVAL;
goto done2;
}
if ((error = ipcperm(td, &msqptr->msg_perm, IPC_R))) {
if ((error = ipcperm(td, &msqkptr->u.msg_perm, IPC_R))) {
DPRINTF(("requester doesn't have read access\n"));
goto done2;
}
@ -930,7 +922,7 @@ msgrcv(td, uap)
msghdr = NULL;
while (msghdr == NULL) {
if (msgtyp == 0) {
msghdr = msqptr->msg_first;
msghdr = msqkptr->u.msg_first;
if (msghdr != NULL) {
if (msgsz < msghdr->msg_ts &&
(msgflg & MSG_NOERROR) == 0) {
@ -940,12 +932,12 @@ msgrcv(td, uap)
error = E2BIG;
goto done2;
}
if (msqptr->msg_first == msqptr->msg_last) {
msqptr->msg_first = NULL;
msqptr->msg_last = NULL;
if (msqkptr->u.msg_first == msqkptr->u.msg_last) {
msqkptr->u.msg_first = NULL;
msqkptr->u.msg_last = NULL;
} else {
msqptr->msg_first = msghdr->msg_next;
if (msqptr->msg_first == NULL)
msqkptr->u.msg_first = msghdr->msg_next;
if (msqkptr->u.msg_first == NULL)
panic("msg_first/last screwed up #1");
}
}
@ -954,7 +946,7 @@ msgrcv(td, uap)
struct msg **prev;
previous = NULL;
prev = &(msqptr->msg_first);
prev = &(msqkptr->u.msg_first);
while ((msghdr = *prev) != NULL) {
/*
* Is this message's type an exact match or is
@ -980,20 +972,20 @@ msgrcv(td, uap)
goto done2;
}
*prev = msghdr->msg_next;
if (msghdr == msqptr->msg_last) {
if (msghdr == msqkptr->u.msg_last) {
if (previous == NULL) {
if (prev !=
&msqptr->msg_first)
&msqkptr->u.msg_first)
panic("msg_first/last screwed up #2");
msqptr->msg_first =
msqkptr->u.msg_first =
NULL;
msqptr->msg_last =
msqkptr->u.msg_last =
NULL;
} else {
if (prev ==
&msqptr->msg_first)
&msqkptr->u.msg_first)
panic("msg_first/last screwed up #3");
msqptr->msg_last =
msqkptr->u.msg_last =
previous;
}
}
@ -1030,7 +1022,7 @@ msgrcv(td, uap)
*/
DPRINTF(("msgrcv: goodnight\n"));
error = msleep(msqptr, &msq_mtx, (PZERO - 4) | PCATCH,
error = msleep(msqkptr, &msq_mtx, (PZERO - 4) | PCATCH,
"msgwait", 0);
DPRINTF(("msgrcv: good morning (error=%d)\n", error));
@ -1044,8 +1036,8 @@ msgrcv(td, uap)
* Make sure that the msq queue still exists
*/
if (msqptr->msg_qbytes == 0 ||
msqptr->msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) {
if (msqkptr->u.msg_qbytes == 0 ||
msqkptr->u.msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) {
DPRINTF(("msqid deleted\n"));
error = EIDRM;
goto done2;
@ -1058,10 +1050,10 @@ msgrcv(td, uap)
* First, do the bookkeeping (before we risk being interrupted).
*/
msqptr->msg_cbytes -= msghdr->msg_ts;
msqptr->msg_qnum--;
msqptr->msg_lrpid = td->td_proc->p_pid;
msqptr->msg_rtime = time_second;
msqkptr->u.msg_cbytes -= msghdr->msg_ts;
msqkptr->u.msg_qnum--;
msqkptr->u.msg_lrpid = td->td_proc->p_pid;
msqkptr->u.msg_rtime = time_second;
/*
* Make msgsz the actual amount that we'll be returning.
@ -1085,7 +1077,7 @@ msgrcv(td, uap)
if (error != 0) {
DPRINTF(("error (%d) copying out message type\n", error));
msg_freehdr(msghdr);
wakeup(msqptr);
wakeup(msqkptr);
goto done2;
}
user_msgp = (char *)user_msgp + sizeof(msghdr->msg_type);
@ -1114,7 +1106,7 @@ msgrcv(td, uap)
DPRINTF(("error (%d) copying out message segment\n",
error));
msg_freehdr(msghdr);
wakeup(msqptr);
wakeup(msqkptr);
goto done2;
}
user_msgp = (char *)user_msgp + tlen;
@ -1126,7 +1118,7 @@ msgrcv(td, uap)
*/
msg_freehdr(msghdr);
wakeup(msqptr);
wakeup(msqkptr);
td->td_retval[0] = msgsz;
done2:
mtx_unlock(&msq_mtx);
@ -1138,7 +1130,7 @@ sysctl_msqids(SYSCTL_HANDLER_ARGS)
{
return (SYSCTL_OUT(req, msqids,
sizeof(struct msqid_ds) * msginfo.msgmni));
sizeof(struct msqid_kernel) * msginfo.msgmni));
}
SYSCTL_DECL(_kern_ipc);

View File

@ -40,7 +40,7 @@ static int sysvsem_modload(struct module *, int, void *);
static int semunload(void);
static void semexit_myhook(void *arg, struct proc *p);
static int sysctl_sema(SYSCTL_HANDLER_ARGS);
static int semvalid(int semid, struct semid_ds *semaptr);
static int semvalid(int semid, struct semid_kernel *semakptr);
#ifndef _SYS_SYSPROTO_H_
struct __semctl_args;
@ -64,7 +64,7 @@ static sy_call_t *semcalls[] = {
static struct mtx sem_mtx; /* semaphore global lock */
static int semtot = 0;
static struct semid_ds *sema; /* semaphore id pool */
static struct semid_kernel *sema; /* semaphore id pool */
static struct mtx *sema_mtx; /* semaphore id pool mutexes*/
static struct sem *sem; /* semaphore pool */
SLIST_HEAD(, sem_undo) semu_list; /* list of active undo structures */
@ -190,16 +190,16 @@ seminit(void)
TUNABLE_INT_FETCH("kern.ipc.semaem", &seminfo.semaem);
sem = malloc(sizeof(struct sem) * seminfo.semmns, M_SEM, M_WAITOK);
sema = malloc(sizeof(struct semid_ds) * seminfo.semmni, M_SEM,
sema = malloc(sizeof(struct semid_kernel) * seminfo.semmni, M_SEM,
M_WAITOK);
sema_mtx = malloc(sizeof(struct mtx) * seminfo.semmni, M_SEM,
M_WAITOK | M_ZERO);
semu = malloc(seminfo.semmnu * seminfo.semusz, M_SEM, M_WAITOK);
for (i = 0; i < seminfo.semmni; i++) {
sema[i].sem_base = 0;
sema[i].sem_perm.mode = 0;
sema[i].sem_perm.seq = 0;
sema[i].u.sem_base = 0;
sema[i].u.sem_perm.mode = 0;
sema[i].u.sem_perm.seq = 0;
}
for (i = 0; i < seminfo.semmni; i++)
mtx_init(&sema_mtx[i], "semid", NULL, MTX_DEF);
@ -472,13 +472,13 @@ semundo_clear(semid, semnum)
}
static int
semvalid(semid, semaptr)
semvalid(semid, semakptr)
int semid;
struct semid_ds *semaptr;
struct semid_kernel *semakptr;
{
return ((semaptr->sem_perm.mode & SEM_ALLOC) == 0 ||
semaptr->sem_perm.seq != IPCID_TO_SEQ(semid) ? EINVAL : 0);
return ((semakptr->u.sem_perm.mode & SEM_ALLOC) == 0 ||
semakptr->u.sem_perm.seq != IPCID_TO_SEQ(semid) ? EINVAL : 0);
}
/*
@ -510,7 +510,7 @@ __semctl(td, uap)
struct ucred *cred = td->td_ucred;
int i, rval, error;
struct semid_ds sbuf;
struct semid_ds *semaptr;
struct semid_kernel *semakptr;
struct mtx *sema_mtxp;
u_short usval, count;
@ -527,18 +527,19 @@ __semctl(td, uap)
return (EINVAL);
if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
return (error);
semaptr = &sema[semid];
semakptr = &sema[semid];
sema_mtxp = &sema_mtx[semid];
mtx_lock(sema_mtxp);
if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0) {
if ((semakptr->u.sem_perm.mode & SEM_ALLOC) == 0) {
error = EINVAL;
goto done2;
}
if ((error = ipcperm(td, &semaptr->sem_perm, IPC_R)))
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
goto done2;
mtx_unlock(sema_mtxp);
error = copyout(semaptr, real_arg.buf, sizeof(struct semid_ds));
rval = IXSEQ_TO_IPCID(semid,semaptr->sem_perm);
error = copyout(&semakptr->u, real_arg.buf,
sizeof(struct semid_ds));
rval = IXSEQ_TO_IPCID(semid, semakptr->u.sem_perm);
if (error == 0)
td->td_retval[0] = rval;
return (error);
@ -548,7 +549,7 @@ __semctl(td, uap)
if (semid < 0 || semid >= seminfo.semmni)
return (EINVAL);
semaptr = &sema[semid];
semakptr = &sema[semid];
sema_mtxp = &sema_mtx[semid];
error = 0;
@ -557,25 +558,25 @@ __semctl(td, uap)
switch (cmd) {
case IPC_RMID:
mtx_lock(sema_mtxp);
if ((error = semvalid(uap->semid, semaptr)) != 0)
if ((error = semvalid(uap->semid, semakptr)) != 0)
goto done2;
if ((error = ipcperm(td, &semaptr->sem_perm, IPC_M)))
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_M)))
goto done2;
semaptr->sem_perm.cuid = cred->cr_uid;
semaptr->sem_perm.uid = cred->cr_uid;
semtot -= semaptr->sem_nsems;
for (i = semaptr->sem_base - sem; i < semtot; i++)
sem[i] = sem[i + semaptr->sem_nsems];
semakptr->u.sem_perm.cuid = cred->cr_uid;
semakptr->u.sem_perm.uid = cred->cr_uid;
semtot -= semakptr->u.sem_nsems;
for (i = semakptr->u.sem_base - sem; i < semtot; i++)
sem[i] = sem[i + semakptr->u.sem_nsems];
for (i = 0; i < seminfo.semmni; i++) {
if ((sema[i].sem_perm.mode & SEM_ALLOC) &&
sema[i].sem_base > semaptr->sem_base)
sema[i].sem_base -= semaptr->sem_nsems;
if ((sema[i].u.sem_perm.mode & SEM_ALLOC) &&
sema[i].u.sem_base > semakptr->u.sem_base)
sema[i].u.sem_base -= semakptr->u.sem_nsems;
}
semaptr->sem_perm.mode = 0;
semakptr->u.sem_perm.mode = 0;
SEMUNDO_LOCK();
semundo_clear(semid, -1);
SEMUNDO_UNLOCK();
wakeup(semaptr);
wakeup(semakptr);
break;
case IPC_SET:
@ -584,82 +585,82 @@ __semctl(td, uap)
if ((error = copyin(real_arg.buf, &sbuf, sizeof(sbuf))) != 0)
goto done2;
mtx_lock(sema_mtxp);
if ((error = semvalid(uap->semid, semaptr)) != 0)
if ((error = semvalid(uap->semid, semakptr)) != 0)
goto done2;
if ((error = ipcperm(td, &semaptr->sem_perm, IPC_M)))
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_M)))
goto done2;
semaptr->sem_perm.uid = sbuf.sem_perm.uid;
semaptr->sem_perm.gid = sbuf.sem_perm.gid;
semaptr->sem_perm.mode = (semaptr->sem_perm.mode & ~0777) |
(sbuf.sem_perm.mode & 0777);
semaptr->sem_ctime = time_second;
semakptr->u.sem_perm.uid = sbuf.sem_perm.uid;
semakptr->u.sem_perm.gid = sbuf.sem_perm.gid;
semakptr->u.sem_perm.mode = (semakptr->u.sem_perm.mode &
~0777) | (sbuf.sem_perm.mode & 0777);
semakptr->u.sem_ctime = time_second;
break;
case IPC_STAT:
if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
goto done2;
mtx_lock(sema_mtxp);
if ((error = semvalid(uap->semid, semaptr)) != 0)
if ((error = semvalid(uap->semid, semakptr)) != 0)
goto done2;
if ((error = ipcperm(td, &semaptr->sem_perm, IPC_R)))
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
goto done2;
sbuf = *semaptr;
sbuf = semakptr->u;
mtx_unlock(sema_mtxp);
error = copyout(semaptr, real_arg.buf,
error = copyout(&semakptr->u, real_arg.buf,
sizeof(struct semid_ds));
break;
case GETNCNT:
mtx_lock(sema_mtxp);
if ((error = semvalid(uap->semid, semaptr)) != 0)
if ((error = semvalid(uap->semid, semakptr)) != 0)
goto done2;
if ((error = ipcperm(td, &semaptr->sem_perm, IPC_R)))
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
goto done2;
if (semnum < 0 || semnum >= semaptr->sem_nsems) {
if (semnum < 0 || semnum >= semakptr->u.sem_nsems) {
error = EINVAL;
goto done2;
}
rval = semaptr->sem_base[semnum].semncnt;
rval = semakptr->u.sem_base[semnum].semncnt;
break;
case GETPID:
mtx_lock(sema_mtxp);
if ((error = semvalid(uap->semid, semaptr)) != 0)
if ((error = semvalid(uap->semid, semakptr)) != 0)
goto done2;
if ((error = ipcperm(td, &semaptr->sem_perm, IPC_R)))
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
goto done2;
if (semnum < 0 || semnum >= semaptr->sem_nsems) {
if (semnum < 0 || semnum >= semakptr->u.sem_nsems) {
error = EINVAL;
goto done2;
}
rval = semaptr->sem_base[semnum].sempid;
rval = semakptr->u.sem_base[semnum].sempid;
break;
case GETVAL:
mtx_lock(sema_mtxp);
if ((error = semvalid(uap->semid, semaptr)) != 0)
if ((error = semvalid(uap->semid, semakptr)) != 0)
goto done2;
if ((error = ipcperm(td, &semaptr->sem_perm, IPC_R)))
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
goto done2;
if (semnum < 0 || semnum >= semaptr->sem_nsems) {
if (semnum < 0 || semnum >= semakptr->u.sem_nsems) {
error = EINVAL;
goto done2;
}
rval = semaptr->sem_base[semnum].semval;
rval = semakptr->u.sem_base[semnum].semval;
break;
case GETALL:
if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
goto done2;
array = malloc(sizeof(*array) * semaptr->sem_nsems, M_TEMP,
array = malloc(sizeof(*array) * semakptr->u.sem_nsems, M_TEMP,
M_WAITOK);
mtx_lock(sema_mtxp);
if ((error = semvalid(uap->semid, semaptr)) != 0)
if ((error = semvalid(uap->semid, semakptr)) != 0)
goto done2;
if ((error = ipcperm(td, &semaptr->sem_perm, IPC_R)))
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
goto done2;
for (i = 0; i < semaptr->sem_nsems; i++)
array[i] = semaptr->sem_base[i].semval;
for (i = 0; i < semakptr->u.sem_nsems; i++)
array[i] = semakptr->u.sem_base[i].semval;
mtx_unlock(sema_mtxp);
error = copyout(array, real_arg.array,
i * sizeof(real_arg.array[0]));
@ -667,26 +668,26 @@ __semctl(td, uap)
case GETZCNT:
mtx_lock(sema_mtxp);
if ((error = semvalid(uap->semid, semaptr)) != 0)
if ((error = semvalid(uap->semid, semakptr)) != 0)
goto done2;
if ((error = ipcperm(td, &semaptr->sem_perm, IPC_R)))
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
goto done2;
if (semnum < 0 || semnum >= semaptr->sem_nsems) {
if (semnum < 0 || semnum >= semakptr->u.sem_nsems) {
error = EINVAL;
goto done2;
}
rval = semaptr->sem_base[semnum].semzcnt;
rval = semakptr->u.sem_base[semnum].semzcnt;
break;
case SETVAL:
if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
goto done2;
mtx_lock(sema_mtxp);
if ((error = semvalid(uap->semid, semaptr)) != 0)
if ((error = semvalid(uap->semid, semakptr)) != 0)
goto done2;
if ((error = ipcperm(td, &semaptr->sem_perm, IPC_W)))
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_W)))
goto done2;
if (semnum < 0 || semnum >= semaptr->sem_nsems) {
if (semnum < 0 || semnum >= semakptr->u.sem_nsems) {
error = EINVAL;
goto done2;
}
@ -694,19 +695,19 @@ __semctl(td, uap)
error = ERANGE;
goto done2;
}
semaptr->sem_base[semnum].semval = real_arg.val;
semakptr->u.sem_base[semnum].semval = real_arg.val;
SEMUNDO_LOCK();
semundo_clear(semid, semnum);
SEMUNDO_UNLOCK();
wakeup(semaptr);
wakeup(semakptr);
break;
case SETALL:
mtx_lock(sema_mtxp);
raced:
if ((error = semvalid(uap->semid, semaptr)) != 0)
if ((error = semvalid(uap->semid, semakptr)) != 0)
goto done2;
count = semaptr->sem_nsems;
count = semakptr->u.sem_nsems;
mtx_unlock(sema_mtxp);
if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
goto done2;
@ -715,28 +716,28 @@ __semctl(td, uap)
if (error)
break;
mtx_lock(sema_mtxp);
if ((error = semvalid(uap->semid, semaptr)) != 0)
if ((error = semvalid(uap->semid, semakptr)) != 0)
goto done2;
/* we could have raced? */
if (count != semaptr->sem_nsems) {
if (count != semakptr->u.sem_nsems) {
free(array, M_TEMP);
array = NULL;
goto raced;
}
if ((error = ipcperm(td, &semaptr->sem_perm, IPC_W)))
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_W)))
goto done2;
for (i = 0; i < semaptr->sem_nsems; i++) {
for (i = 0; i < semakptr->u.sem_nsems; i++) {
usval = array[i];
if (usval > seminfo.semvmx) {
error = ERANGE;
break;
}
semaptr->sem_base[i].semval = usval;
semakptr->u.sem_base[i].semval = usval;
}
SEMUNDO_LOCK();
semundo_clear(semid, -1);
SEMUNDO_UNLOCK();
wakeup(semaptr);
wakeup(semakptr);
break;
default:
@ -783,17 +784,17 @@ semget(td, uap)
mtx_lock(&Giant);
if (key != IPC_PRIVATE) {
for (semid = 0; semid < seminfo.semmni; semid++) {
if ((sema[semid].sem_perm.mode & SEM_ALLOC) &&
sema[semid].sem_perm.key == key)
if ((sema[semid].u.sem_perm.mode & SEM_ALLOC) &&
sema[semid].u.sem_perm.key == key)
break;
}
if (semid < seminfo.semmni) {
DPRINTF(("found public key\n"));
if ((error = ipcperm(td, &sema[semid].sem_perm,
if ((error = ipcperm(td, &sema[semid].u.sem_perm,
semflg & 0700))) {
goto done2;
}
if (nsems > 0 && sema[semid].sem_nsems < nsems) {
if (nsems > 0 && sema[semid].u.sem_nsems < nsems) {
DPRINTF(("too small\n"));
error = EINVAL;
goto done2;
@ -807,7 +808,7 @@ semget(td, uap)
}
}
DPRINTF(("need to allocate the semid_ds\n"));
DPRINTF(("need to allocate the semid_kernel\n"));
if (key == IPC_PRIVATE || (semflg & IPC_CREAT)) {
if (nsems <= 0 || nsems > seminfo.semmsl) {
DPRINTF(("nsems out of range (0<%d<=%d)\n", nsems,
@ -823,32 +824,32 @@ semget(td, uap)
goto done2;
}
for (semid = 0; semid < seminfo.semmni; semid++) {
if ((sema[semid].sem_perm.mode & SEM_ALLOC) == 0)
if ((sema[semid].u.sem_perm.mode & SEM_ALLOC) == 0)
break;
}
if (semid == seminfo.semmni) {
DPRINTF(("no more semid_ds's available\n"));
DPRINTF(("no more semid_kernel's available\n"));
error = ENOSPC;
goto done2;
}
DPRINTF(("semid %d is available\n", semid));
sema[semid].sem_perm.key = key;
sema[semid].sem_perm.cuid = cred->cr_uid;
sema[semid].sem_perm.uid = cred->cr_uid;
sema[semid].sem_perm.cgid = cred->cr_gid;
sema[semid].sem_perm.gid = cred->cr_gid;
sema[semid].sem_perm.mode = (semflg & 0777) | SEM_ALLOC;
sema[semid].sem_perm.seq =
(sema[semid].sem_perm.seq + 1) & 0x7fff;
sema[semid].sem_nsems = nsems;
sema[semid].sem_otime = 0;
sema[semid].sem_ctime = time_second;
sema[semid].sem_base = &sem[semtot];
sema[semid].u.sem_perm.key = key;
sema[semid].u.sem_perm.cuid = cred->cr_uid;
sema[semid].u.sem_perm.uid = cred->cr_uid;
sema[semid].u.sem_perm.cgid = cred->cr_gid;
sema[semid].u.sem_perm.gid = cred->cr_gid;
sema[semid].u.sem_perm.mode = (semflg & 0777) | SEM_ALLOC;
sema[semid].u.sem_perm.seq =
(sema[semid].u.sem_perm.seq + 1) & 0x7fff;
sema[semid].u.sem_nsems = nsems;
sema[semid].u.sem_otime = 0;
sema[semid].u.sem_ctime = time_second;
sema[semid].u.sem_base = &sem[semtot];
semtot += nsems;
bzero(sema[semid].sem_base,
sizeof(sema[semid].sem_base[0])*nsems);
DPRINTF(("sembase = 0x%x, next = 0x%x\n", sema[semid].sem_base,
&sem[semtot]));
bzero(sema[semid].u.sem_base,
sizeof(sema[semid].u.sem_base[0])*nsems);
DPRINTF(("sembase = 0x%x, next = 0x%x\n",
sema[semid].u.sem_base, &sem[semtot]));
} else {
DPRINTF(("didn't find it and wasn't asked to create it\n"));
error = ENOENT;
@ -856,7 +857,7 @@ semget(td, uap)
}
found:
td->td_retval[0] = IXSEQ_TO_IPCID(semid, sema[semid].sem_perm);
td->td_retval[0] = IXSEQ_TO_IPCID(semid, sema[semid].u.sem_perm);
done2:
mtx_unlock(&Giant);
return (error);
@ -883,7 +884,7 @@ semop(td, uap)
int semid = uap->semid;
size_t nsops = uap->nsops;
struct sembuf *sops;
struct semid_ds *semaptr;
struct semid_kernel *semakptr;
struct sembuf *sopptr = 0;
struct sem *semptr = 0;
struct sem_undo *suptr;
@ -900,7 +901,7 @@ semop(td, uap)
semid = IPCID_TO_IX(semid); /* Convert back to zero origin */
if (semid < 0 || semid >= seminfo.semmni)
return (EINVAL);
error = EINVAL;
/* Allocate memory for sem_ops */
if (nsops <= SMALL_SOPS)
@ -920,14 +921,14 @@ semop(td, uap)
return (error);
}
semaptr = &sema[semid];
semakptr = &sema[semid];
sema_mtxp = &sema_mtx[semid];
mtx_lock(sema_mtxp);
if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0) {
if ((semakptr->u.sem_perm.mode & SEM_ALLOC) == 0) {
error = EINVAL;
goto done2;
}
if (semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid)) {
if (semakptr->u.sem_perm.seq != IPCID_TO_SEQ(uap->semid)) {
error = EINVAL;
goto done2;
}
@ -940,7 +941,7 @@ semop(td, uap)
do_undos = 0;
for (i = 0; i < nsops; i++) {
sopptr = &sops[i];
if (sopptr->sem_num >= semaptr->sem_nsems) {
if (sopptr->sem_num >= semakptr->u.sem_nsems) {
error = EFBIG;
goto done2;
}
@ -949,7 +950,7 @@ semop(td, uap)
j |= (sopptr->sem_op == 0) ? SEM_R : SEM_A;
}
if ((error = ipcperm(td, &semaptr->sem_perm, j))) {
if ((error = ipcperm(td, &semakptr->u.sem_perm, j))) {
DPRINTF(("error = %d from ipaccess\n", error));
goto done2;
}
@ -969,12 +970,12 @@ semop(td, uap)
for (i = 0; i < nsops; i++) {
sopptr = &sops[i];
semptr = &semaptr->sem_base[sopptr->sem_num];
semptr = &semakptr->u.sem_base[sopptr->sem_num];
DPRINTF((
"semop: semaptr=%x, sem_base=%x, "
"semop: semakptr=%x, sem_base=%x, "
"semptr=%x, sem[%d]=%d : op=%d, flag=%s\n",
semaptr, semaptr->sem_base, semptr,
semakptr, semakptr->u.sem_base, semptr,
sopptr->sem_num, semptr->semval, sopptr->sem_op,
(sopptr->sem_flg & IPC_NOWAIT) ?
"nowait" : "wait"));
@ -1016,7 +1017,7 @@ semop(td, uap)
*/
DPRINTF(("semop: rollback 0 through %d\n", i-1));
for (j = 0; j < i; j++)
semaptr->sem_base[sops[j].sem_num].semval -=
semakptr->u.sem_base[sops[j].sem_num].semval -=
sops[j].sem_op;
/* If we detected an error, return it */
@ -1038,7 +1039,7 @@ semop(td, uap)
semptr->semncnt++;
DPRINTF(("semop: good night!\n"));
error = msleep(semaptr, sema_mtxp, (PZERO - 4) | PCATCH,
error = msleep(semakptr, sema_mtxp, (PZERO - 4) | PCATCH,
"semwait", 0);
DPRINTF(("semop: good morning (error=%d)!\n", error));
/* return code is checked below, after sem[nz]cnt-- */
@ -1046,8 +1047,8 @@ semop(td, uap)
/*
* Make sure that the semaphore still exists
*/
if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0 ||
semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid)) {
if ((semakptr->u.sem_perm.mode & SEM_ALLOC) == 0 ||
semakptr->u.sem_perm.seq != IPCID_TO_SEQ(uap->semid)) {
error = EIDRM;
goto done2;
}
@ -1119,7 +1120,7 @@ semop(td, uap)
}
for (j = 0; j < nsops; j++)
semaptr->sem_base[sops[j].sem_num].semval -=
semakptr->u.sem_base[sops[j].sem_num].semval -=
sops[j].sem_op;
DPRINTF(("error = %d from semundo_adjust\n", error));
@ -1132,10 +1133,10 @@ semop(td, uap)
/* We're definitely done - set the sempid's and time */
for (i = 0; i < nsops; i++) {
sopptr = &sops[i];
semptr = &semaptr->sem_base[sopptr->sem_num];
semptr = &semakptr->u.sem_base[sopptr->sem_num];
semptr->sempid = td->td_proc->p_pid;
}
semaptr->sem_otime = time_second;
semakptr->u.sem_otime = time_second;
/*
* Do a wakeup if any semaphore was up'd whilst something was
@ -1143,7 +1144,7 @@ semop(td, uap)
*/
if (do_wakeup) {
DPRINTF(("semop: doing wakeup\n"));
wakeup(semaptr);
wakeup(semakptr);
DPRINTF(("semop: back from wakeup\n"));
}
DPRINTF(("semop: done\n"));
@ -1152,6 +1153,7 @@ semop(td, uap)
mtx_unlock(sema_mtxp);
if (sops != small_sops)
free(sops, M_SEM);
free(sops, M_SEM);
return (error);
}
@ -1194,16 +1196,16 @@ semexit_myhook(arg, p)
int semid = suptr->un_ent[ix].un_id;
int semnum = suptr->un_ent[ix].un_num;
int adjval = suptr->un_ent[ix].un_adjval;
struct semid_ds *semaptr;
struct semid_kernel *semakptr;
struct mtx *sema_mtxp;
semaptr = &sema[semid];
semakptr = &sema[semid];
sema_mtxp = &sema_mtx[semid];
mtx_lock(sema_mtxp);
SEMUNDO_LOCK();
if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0)
if ((semakptr->u.sem_perm.mode & SEM_ALLOC) == 0)
panic("semexit - semid not allocated");
if (semnum >= semaptr->sem_nsems)
if (semnum >= semakptr->u.sem_nsems)
panic("semexit - semnum out of range");
DPRINTF((
@ -1211,18 +1213,19 @@ semexit_myhook(arg, p)
suptr->un_proc, suptr->un_ent[ix].un_id,
suptr->un_ent[ix].un_num,
suptr->un_ent[ix].un_adjval,
semaptr->sem_base[semnum].semval));
semakptr->u.sem_base[semnum].semval));
if (adjval < 0) {
if (semaptr->sem_base[semnum].semval < -adjval)
semaptr->sem_base[semnum].semval = 0;
if (semakptr->u.sem_base[semnum].semval <
-adjval)
semakptr->u.sem_base[semnum].semval = 0;
else
semaptr->sem_base[semnum].semval +=
semakptr->u.sem_base[semnum].semval +=
adjval;
} else
semaptr->sem_base[semnum].semval += adjval;
semakptr->u.sem_base[semnum].semval += adjval;
wakeup(semaptr);
wakeup(semakptr);
DPRINTF(("semexit: back from wakeup\n"));
mtx_unlock(sema_mtxp);
SEMUNDO_UNLOCK();
@ -1242,5 +1245,5 @@ sysctl_sema(SYSCTL_HANDLER_ARGS)
{
return (SYSCTL_OUT(req, sema,
sizeof(struct semid_ds) * seminfo.semmni));
sizeof(struct semid_kernel) * seminfo.semmni));
}

View File

@ -85,17 +85,17 @@ static sy_call_t *shmcalls[] = {
#define SHMSEG_WANTED 0x1000
static int shm_last_free, shm_nused, shm_committed, shmalloced;
static struct shmid_ds *shmsegs;
static struct shmid_kernel *shmsegs;
struct shmmap_state {
vm_offset_t va;
int shmid;
};
static void shm_deallocate_segment(struct shmid_ds *);
static void shm_deallocate_segment(struct shmid_kernel *);
static int shm_find_segment_by_key(key_t);
static struct shmid_ds *shm_find_segment_by_shmid(int);
static struct shmid_ds *shm_find_segment_by_shmidx(int);
static struct shmid_kernel *shm_find_segment_by_shmid(int);
static struct shmid_kernel *shm_find_segment_by_shmidx(int);
static int shm_delete_mapping(struct vmspace *vm, struct shmmap_state *);
static void shmrealloc(void);
static void shminit(void);
@ -158,65 +158,65 @@ shm_find_segment_by_key(key)
int i;
for (i = 0; i < shmalloced; i++)
if ((shmsegs[i].shm_perm.mode & SHMSEG_ALLOCATED) &&
shmsegs[i].shm_perm.key == key)
if ((shmsegs[i].u.shm_perm.mode & SHMSEG_ALLOCATED) &&
shmsegs[i].u.shm_perm.key == key)
return (i);
return (-1);
}
static struct shmid_ds *
static struct shmid_kernel *
shm_find_segment_by_shmid(int shmid)
{
int segnum;
struct shmid_ds *shmseg;
struct shmid_kernel *shmseg;
segnum = IPCID_TO_IX(shmid);
if (segnum < 0 || segnum >= shmalloced)
return (NULL);
shmseg = &shmsegs[segnum];
if ((shmseg->shm_perm.mode & SHMSEG_ALLOCATED) == 0 ||
if ((shmseg->u.shm_perm.mode & SHMSEG_ALLOCATED) == 0 ||
(!shm_allow_removed &&
(shmseg->shm_perm.mode & SHMSEG_REMOVED) != 0) ||
shmseg->shm_perm.seq != IPCID_TO_SEQ(shmid))
(shmseg->u.shm_perm.mode & SHMSEG_REMOVED) != 0) ||
shmseg->u.shm_perm.seq != IPCID_TO_SEQ(shmid))
return (NULL);
return (shmseg);
}
static struct shmid_ds *
static struct shmid_kernel *
shm_find_segment_by_shmidx(int segnum)
{
struct shmid_ds *shmseg;
struct shmid_kernel *shmseg;
if (segnum < 0 || segnum >= shmalloced)
return (NULL);
shmseg = &shmsegs[segnum];
if ((shmseg->shm_perm.mode & SHMSEG_ALLOCATED) == 0 ||
if ((shmseg->u.shm_perm.mode & SHMSEG_ALLOCATED) == 0 ||
(!shm_allow_removed &&
(shmseg->shm_perm.mode & SHMSEG_REMOVED) != 0))
(shmseg->u.shm_perm.mode & SHMSEG_REMOVED) != 0))
return (NULL);
return (shmseg);
}
static void
shm_deallocate_segment(shmseg)
struct shmid_ds *shmseg;
struct shmid_kernel *shmseg;
{
size_t size;
GIANT_REQUIRED;
vm_object_deallocate(shmseg->shm_internal);
shmseg->shm_internal = NULL;
size = round_page(shmseg->shm_segsz);
vm_object_deallocate(shmseg->u.shm_internal);
shmseg->u.shm_internal = NULL;
size = round_page(shmseg->u.shm_segsz);
shm_committed -= btoc(size);
shm_nused--;
shmseg->shm_perm.mode = SHMSEG_FREE;
shmseg->u.shm_perm.mode = SHMSEG_FREE;
}
static int
shm_delete_mapping(struct vmspace *vm, struct shmmap_state *shmmap_s)
{
struct shmid_ds *shmseg;
struct shmid_kernel *shmseg;
int segnum, result;
size_t size;
@ -224,14 +224,14 @@ shm_delete_mapping(struct vmspace *vm, struct shmmap_state *shmmap_s)
segnum = IPCID_TO_IX(shmmap_s->shmid);
shmseg = &shmsegs[segnum];
size = round_page(shmseg->shm_segsz);
size = round_page(shmseg->u.shm_segsz);
result = vm_map_remove(&vm->vm_map, shmmap_s->va, shmmap_s->va + size);
if (result != KERN_SUCCESS)
return (EINVAL);
shmmap_s->shmid = -1;
shmseg->shm_dtime = time_second;
if ((--shmseg->shm_nattch <= 0) &&
(shmseg->shm_perm.mode & SHMSEG_REMOVED)) {
shmseg->u.shm_dtime = time_second;
if ((--shmseg->u.shm_nattch <= 0) &&
(shmseg->u.shm_perm.mode & SHMSEG_REMOVED)) {
shm_deallocate_segment(shmseg);
shm_last_free = segnum;
}
@ -301,7 +301,7 @@ kern_shmat(td, shmid, shmaddr, shmflg)
{
struct proc *p = td->td_proc;
int i, flags;
struct shmid_ds *shmseg;
struct shmid_kernel *shmseg;
struct shmmap_state *shmmap_s = NULL;
vm_offset_t attach_va;
vm_prot_t prot;
@ -325,7 +325,7 @@ kern_shmat(td, shmid, shmaddr, shmflg)
error = EINVAL;
goto done2;
}
error = ipcperm(td, &shmseg->shm_perm,
error = ipcperm(td, &shmseg->u.shm_perm,
(shmflg & SHM_RDONLY) ? IPC_R : IPC_R|IPC_W);
if (error)
goto done2;
@ -338,7 +338,7 @@ kern_shmat(td, shmid, shmaddr, shmflg)
error = EMFILE;
goto done2;
}
size = round_page(shmseg->shm_segsz);
size = round_page(shmseg->u.shm_segsz);
#ifdef VM_PROT_READ_IS_EXEC
prot = VM_PROT_READ | VM_PROT_EXECUTE;
#else
@ -368,11 +368,11 @@ kern_shmat(td, shmid, shmaddr, shmflg)
PROC_UNLOCK(p);
}
vm_object_reference(shmseg->shm_internal);
rv = vm_map_find(&p->p_vmspace->vm_map, shmseg->shm_internal,
vm_object_reference(shmseg->u.shm_internal);
rv = vm_map_find(&p->p_vmspace->vm_map, shmseg->u.shm_internal,
0, &attach_va, size, (flags & MAP_FIXED)?0:1, prot, prot, 0);
if (rv != KERN_SUCCESS) {
vm_object_deallocate(shmseg->shm_internal);
vm_object_deallocate(shmseg->u.shm_internal);
error = ENOMEM;
goto done2;
}
@ -381,9 +381,9 @@ kern_shmat(td, shmid, shmaddr, shmflg)
shmmap_s->va = attach_va;
shmmap_s->shmid = shmid;
shmseg->shm_lpid = p->p_pid;
shmseg->shm_atime = time_second;
shmseg->shm_nattch++;
shmseg->u.shm_lpid = p->p_pid;
shmseg->u.shm_atime = time_second;
shmseg->u.shm_nattch++;
td->td_retval[0] = attach_va;
done2:
mtx_unlock(&Giant);
@ -426,7 +426,7 @@ oshmctl(td, uap)
{
#ifdef COMPAT_43
int error = 0;
struct shmid_ds *shmseg;
struct shmid_kernel *shmseg;
struct oshmid_ds outbuf;
if (!jail_sysvipc_allowed && jailed(td->td_ucred))
@ -439,18 +439,18 @@ oshmctl(td, uap)
}
switch (uap->cmd) {
case IPC_STAT:
error = ipcperm(td, &shmseg->shm_perm, IPC_R);
error = ipcperm(td, &shmseg->u.shm_perm, IPC_R);
if (error)
goto done2;
outbuf.shm_perm = shmseg->shm_perm;
outbuf.shm_segsz = shmseg->shm_segsz;
outbuf.shm_cpid = shmseg->shm_cpid;
outbuf.shm_lpid = shmseg->shm_lpid;
outbuf.shm_nattch = shmseg->shm_nattch;
outbuf.shm_atime = shmseg->shm_atime;
outbuf.shm_dtime = shmseg->shm_dtime;
outbuf.shm_ctime = shmseg->shm_ctime;
outbuf.shm_handle = shmseg->shm_internal;
outbuf.shm_perm = shmseg->u.shm_perm;
outbuf.shm_segsz = shmseg->u.shm_segsz;
outbuf.shm_cpid = shmseg->u.shm_cpid;
outbuf.shm_lpid = shmseg->u.shm_lpid;
outbuf.shm_nattch = shmseg->u.shm_nattch;
outbuf.shm_atime = shmseg->u.shm_atime;
outbuf.shm_dtime = shmseg->u.shm_dtime;
outbuf.shm_ctime = shmseg->u.shm_ctime;
outbuf.shm_handle = shmseg->u.shm_internal;
error = copyout(&outbuf, uap->ubuf, sizeof(outbuf));
if (error)
goto done2;
@ -487,7 +487,7 @@ kern_shmctl(td, shmid, cmd, buf, bufsz)
size_t *bufsz;
{
int error = 0;
struct shmid_ds *shmseg;
struct shmid_kernel *shmseg;
if (!jail_sysvipc_allowed && jailed(td->td_ucred))
return (ENOSYS);
@ -526,37 +526,37 @@ kern_shmctl(td, shmid, cmd, buf, bufsz)
switch (cmd) {
case SHM_STAT:
case IPC_STAT:
error = ipcperm(td, &shmseg->shm_perm, IPC_R);
error = ipcperm(td, &shmseg->u.shm_perm, IPC_R);
if (error)
goto done2;
memcpy(buf, shmseg, sizeof(struct shmid_ds));
memcpy(buf, &shmseg->u, sizeof(struct shmid_ds));
if (bufsz)
*bufsz = sizeof(struct shmid_ds);
if (cmd == SHM_STAT)
td->td_retval[0] = IXSEQ_TO_IPCID(shmid, shmseg->shm_perm);
td->td_retval[0] = IXSEQ_TO_IPCID(shmid, shmseg->u.shm_perm);
break;
case IPC_SET: {
struct shmid_ds *shmid;
shmid = (struct shmid_ds *)buf;
error = ipcperm(td, &shmseg->shm_perm, IPC_M);
error = ipcperm(td, &shmseg->u.shm_perm, IPC_M);
if (error)
goto done2;
shmseg->shm_perm.uid = shmid->shm_perm.uid;
shmseg->shm_perm.gid = shmid->shm_perm.gid;
shmseg->shm_perm.mode =
(shmseg->shm_perm.mode & ~ACCESSPERMS) |
shmseg->u.shm_perm.uid = shmid->shm_perm.uid;
shmseg->u.shm_perm.gid = shmid->shm_perm.gid;
shmseg->u.shm_perm.mode =
(shmseg->u.shm_perm.mode & ~ACCESSPERMS) |
(shmid->shm_perm.mode & ACCESSPERMS);
shmseg->shm_ctime = time_second;
shmseg->u.shm_ctime = time_second;
break;
}
case IPC_RMID:
error = ipcperm(td, &shmseg->shm_perm, IPC_M);
error = ipcperm(td, &shmseg->u.shm_perm, IPC_M);
if (error)
goto done2;
shmseg->shm_perm.key = IPC_PRIVATE;
shmseg->shm_perm.mode |= SHMSEG_REMOVED;
if (shmseg->shm_nattch <= 0) {
shmseg->u.shm_perm.key = IPC_PRIVATE;
shmseg->u.shm_perm.mode |= SHMSEG_REMOVED;
if (shmseg->u.shm_nattch <= 0) {
shm_deallocate_segment(shmseg);
shm_last_free = IPCID_TO_IX(shmid);
}
@ -627,17 +627,17 @@ shmget_existing(td, uap, mode, segnum)
int mode;
int segnum;
{
struct shmid_ds *shmseg;
struct shmid_kernel *shmseg;
int error;
shmseg = &shmsegs[segnum];
if (shmseg->shm_perm.mode & SHMSEG_REMOVED) {
if (shmseg->u.shm_perm.mode & SHMSEG_REMOVED) {
/*
* This segment is in the process of being allocated. Wait
* until it's done, and look the key up again (in case the
* allocation failed or it was freed).
*/
shmseg->shm_perm.mode |= SHMSEG_WANTED;
shmseg->u.shm_perm.mode |= SHMSEG_WANTED;
error = tsleep(shmseg, PLOCK | PCATCH, "shmget", 0);
if (error)
return (error);
@ -645,12 +645,12 @@ shmget_existing(td, uap, mode, segnum)
}
if ((uap->shmflg & (IPC_CREAT | IPC_EXCL)) == (IPC_CREAT | IPC_EXCL))
return (EEXIST);
error = ipcperm(td, &shmseg->shm_perm, mode);
error = ipcperm(td, &shmseg->u.shm_perm, mode);
if (error)
return (error);
if (uap->size && uap->size > shmseg->shm_segsz)
if (uap->size && uap->size > shmseg->u.shm_segsz)
return (EINVAL);
td->td_retval[0] = IXSEQ_TO_IPCID(segnum, shmseg->shm_perm);
td->td_retval[0] = IXSEQ_TO_IPCID(segnum, shmseg->u.shm_perm);
return (0);
}
@ -662,7 +662,7 @@ shmget_allocate_segment(td, uap, mode)
{
int i, segnum, shmid, size;
struct ucred *cred = td->td_ucred;
struct shmid_ds *shmseg;
struct shmid_kernel *shmseg;
vm_object_t shm_object;
GIANT_REQUIRED;
@ -677,7 +677,7 @@ shmget_allocate_segment(td, uap, mode)
if (shm_last_free < 0) {
shmrealloc(); /* Maybe expand the shmsegs[] array. */
for (i = 0; i < shmalloced; i++)
if (shmsegs[i].shm_perm.mode & SHMSEG_FREE)
if (shmsegs[i].u.shm_perm.mode & SHMSEG_FREE)
break;
if (i == shmalloced)
return (ENOSPC);
@ -691,10 +691,10 @@ shmget_allocate_segment(td, uap, mode)
* In case we sleep in malloc(), mark the segment present but deleted
* so that noone else tries to create the same key.
*/
shmseg->shm_perm.mode = SHMSEG_ALLOCATED | SHMSEG_REMOVED;
shmseg->shm_perm.key = uap->key;
shmseg->shm_perm.seq = (shmseg->shm_perm.seq + 1) & 0x7fff;
shmid = IXSEQ_TO_IPCID(segnum, shmseg->shm_perm);
shmseg->u.shm_perm.mode = SHMSEG_ALLOCATED | SHMSEG_REMOVED;
shmseg->u.shm_perm.key = uap->key;
shmseg->u.shm_perm.seq = (shmseg->u.shm_perm.seq + 1) & 0x7fff;
shmid = IXSEQ_TO_IPCID(segnum, shmseg->u.shm_perm);
/*
* We make sure that we have allocated a pager before we need
@ -712,24 +712,24 @@ shmget_allocate_segment(td, uap, mode)
vm_object_set_flag(shm_object, OBJ_NOSPLIT);
VM_OBJECT_UNLOCK(shm_object);
shmseg->shm_internal = shm_object;
shmseg->shm_perm.cuid = shmseg->shm_perm.uid = cred->cr_uid;
shmseg->shm_perm.cgid = shmseg->shm_perm.gid = cred->cr_gid;
shmseg->shm_perm.mode = (shmseg->shm_perm.mode & SHMSEG_WANTED) |
shmseg->u.shm_internal = shm_object;
shmseg->u.shm_perm.cuid = shmseg->u.shm_perm.uid = cred->cr_uid;
shmseg->u.shm_perm.cgid = shmseg->u.shm_perm.gid = cred->cr_gid;
shmseg->u.shm_perm.mode = (shmseg->u.shm_perm.mode & SHMSEG_WANTED) |
(mode & ACCESSPERMS) | SHMSEG_ALLOCATED;
shmseg->shm_segsz = uap->size;
shmseg->shm_cpid = td->td_proc->p_pid;
shmseg->shm_lpid = shmseg->shm_nattch = 0;
shmseg->shm_atime = shmseg->shm_dtime = 0;
shmseg->shm_ctime = time_second;
shmseg->u.shm_segsz = uap->size;
shmseg->u.shm_cpid = td->td_proc->p_pid;
shmseg->u.shm_lpid = shmseg->u.shm_nattch = 0;
shmseg->u.shm_atime = shmseg->u.shm_dtime = 0;
shmseg->u.shm_ctime = time_second;
shm_committed += btoc(size);
shm_nused++;
if (shmseg->shm_perm.mode & SHMSEG_WANTED) {
if (shmseg->u.shm_perm.mode & SHMSEG_WANTED) {
/*
* Somebody else wanted this key while we were asleep. Wake
* them up now.
*/
shmseg->shm_perm.mode &= ~SHMSEG_WANTED;
shmseg->u.shm_perm.mode &= ~SHMSEG_WANTED;
wakeup(shmseg);
}
td->td_retval[0] = shmid;
@ -813,7 +813,7 @@ shmfork_myhook(p1, p2)
p2->p_vmspace->vm_shm = shmmap_s;
for (i = 0; i < shminfo.shmseg; i++, shmmap_s++)
if (shmmap_s->shmid != -1)
shmsegs[IPCID_TO_IX(shmmap_s->shmid)].shm_nattch++;
shmsegs[IPCID_TO_IX(shmmap_s->shmid)].u.shm_nattch++;
mtx_unlock(&Giant);
}
@ -839,7 +839,7 @@ static void
shmrealloc(void)
{
int i;
struct shmid_ds *newsegs;
struct shmid_kernel *newsegs;
if (shmalloced >= shminfo.shmmni)
return;
@ -850,8 +850,8 @@ shmrealloc(void)
for (i = 0; i < shmalloced; i++)
bcopy(&shmsegs[i], &newsegs[i], sizeof(newsegs[0]));
for (; i < shminfo.shmmni; i++) {
shmsegs[i].shm_perm.mode = SHMSEG_FREE;
shmsegs[i].shm_perm.seq = 0;
shmsegs[i].u.shm_perm.mode = SHMSEG_FREE;
shmsegs[i].u.shm_perm.seq = 0;
}
free(shmsegs, M_SHM);
shmsegs = newsegs;
@ -879,8 +879,8 @@ shminit()
if (shmsegs == NULL)
panic("cannot allocate initial memory for sysvshm");
for (i = 0; i < shmalloced; i++) {
shmsegs[i].shm_perm.mode = SHMSEG_FREE;
shmsegs[i].shm_perm.seq = 0;
shmsegs[i].u.shm_perm.mode = SHMSEG_FREE;
shmsegs[i].u.shm_perm.seq = 0;
}
shm_last_free = 0;
shm_nused = 0;

View File

@ -100,6 +100,15 @@ struct mymsg {
#ifdef _KERNEL
struct msg {
struct msg *msg_next; /* next msg in the chain */
long msg_type; /* type of this message */
/* >0 -> type of this message */
/* 0 -> free header */
u_short msg_ts; /* size of this message */
short msg_spot; /* location of start of msg in buffer */
};
/*
* Based on the configuration parameters described in an SVR2 (yes, two)
* config(1m) man page.