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:
parent
b85b860ea8
commit
891fcc9766
@ -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);
|
||||
|
@ -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 @@ raced:
|
||||
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 @@ done:
|
||||
}
|
||||
|
||||
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 @@ done:
|
||||
/* 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 @@ done:
|
||||
*/
|
||||
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 @@ done2:
|
||||
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));
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user