summaryrefslogtreecommitdiffstats
path: root/sys/kern/sysv_msg.c
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2000-05-01 13:33:56 +0000
committerpeter <peter@FreeBSD.org>2000-05-01 13:33:56 +0000
commit1adeb7ffb16ca15e57e103f0b216470ee1d82d99 (patch)
treef0135209ea67526adebb763b0b5d2397fb40369b /sys/kern/sysv_msg.c
parentfd776bd6a962dc53c287071dcc755263f80b2cf8 (diff)
downloadFreeBSD-src-1adeb7ffb16ca15e57e103f0b216470ee1d82d99.zip
FreeBSD-src-1adeb7ffb16ca15e57e103f0b216470ee1d82d99.tar.gz
Move the MSG* and SEM* options to opt_sysvipc.h
Remove evil allocation macros from machdep.c (why was that there???) and use malloc() instead. Move paramters out of param.h and into the code itself. Move a bunch of internal definitions from public sys/*.h headers (without #ifdef _KERNEL even) into the code itself. I had hoped to make some of this more dynamic, but the cost of doing wakeups on all sleeping processes on old arrays was too frightening. The other possibility is to initialize on the first use, and allow dynamic sysctl changes to parameters right until that point. That would allow /etc/rc.sysctl to change SEM* and MSG* defaults as we presently do with SHM*, but without the nightmare of changing a running system.
Diffstat (limited to 'sys/kern/sysv_msg.c')
-rw-r--r--sys/kern/sysv_msg.c129
1 files changed, 93 insertions, 36 deletions
diff --git a/sys/kern/sysv_msg.c b/sys/kern/sysv_msg.c
index badbdc4..aa84283 100644
--- a/sys/kern/sysv_msg.c
+++ b/sys/kern/sysv_msg.c
@@ -19,6 +19,8 @@
* This software is provided ``AS IS'' without any warranties of any kind.
*/
+#include "opt_sysvipc.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
@@ -26,23 +28,16 @@
#include <sys/proc.h>
#include <sys/msg.h>
#include <sys/sysent.h>
+#include <sys/sysctl.h>
+#include <sys/malloc.h>
+
+static MALLOC_DEFINE(M_MSG, "msg", "SVID compatible message queues");
static void msginit __P((void *));
-SYSINIT(sysv_msg, SI_SUB_SYSV_MSG, SI_ORDER_FIRST, msginit, NULL)
#define MSG_DEBUG
#undef MSG_DEBUG_OK
-#ifndef _SYS_SYSPROTO_H_
-struct msgctl_args;
-int msgctl __P((struct proc *p, struct msgctl_args *uap));
-struct msgget_args;
-int msgget __P((struct proc *p, struct msgget_args *uap));
-struct msgsnd_args;
-int msgsnd __P((struct proc *p, struct msgsnd_args *uap));
-struct msgrcv_args;
-int msgrcv __P((struct proc *p, struct msgrcv_args *uap));
-#endif
static void msg_freehdr __P((struct msg *msghdr));
/* XXX casting to (sy_call_t *) is bogus, as usual. */
@@ -51,20 +46,100 @@ 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
+#ifndef MSGSEG
+#define MSGSEG 2048 /* must be less than 32767 */
+#endif
+#define MSGMAX (MSGSSZ*MSGSEG)
+#ifndef MSGMNB
+#define MSGMNB 2048 /* max # of bytes in a queue */
+#endif
+#ifndef MSGMNI
+#define MSGMNI 40
+#endif
+#ifndef MSGTQL
+#define MSGTQL 40
+#endif
+
+/*
+ * Based on the configuration parameters described in an SVR2 (yes, two)
+ * config(1m) man page.
+ *
+ * Each message is broken up and stored in segments that are msgssz bytes
+ * long. For efficiency reasons, this should be a power of two. Also,
+ * it doesn't make sense if it is less than 8 or greater than about 256.
+ * Consequently, msginit in kern/sysv_msg.c checks that msgssz is a power of
+ * two between 8 and 1024 inclusive (and panic's if it isn't).
+ */
+struct msginfo msginfo = {
+ MSGMAX, /* max chars in a message */
+ MSGMNI, /* # of message queue identifiers */
+ MSGMNB, /* max chars in a queue */
+ MSGTQL, /* max messages in system */
+ MSGSSZ, /* size of a message segment */
+ /* (must be small power of 2 greater than 4) */
+ MSGSEG /* number of message segments */
+};
+
+/*
+ * macros to convert between msqid_ds's and msqid's.
+ * (specific to this implementation)
+ */
+#define MSQID(ix,ds) ((ix) & 0xffff | (((ds).msg_perm.seq << 16) & 0xffff0000))
+#define MSQID_IX(id) ((id) & 0xffff)
+#define MSQID_SEQ(id) (((id) >> 16) & 0xffff)
+
+/*
+ * The rest of this file is specific to this particular implementation.
+ */
+
+struct msgmap {
+ short next; /* next segment in buffer */
+ /* -1 -> available */
+ /* 0..(MSGSEG-1) -> index of next segment */
+};
+
+#define MSG_LOCKED 01000 /* Is this msqid_ds locked? */
+
static int nfree_msgmaps; /* # of free map entries */
static short free_msgmaps; /* head of linked list of free map entries */
-static struct msg *free_msghdrs; /* list of free msg headers */
-char *msgpool; /* MSGMAX byte long msg buffer pool */
-struct msgmap *msgmaps; /* MSGSEG msgmap structures */
-struct msg *msghdrs; /* MSGTQL msg headers */
-struct msqid_ds *msqids; /* MSGMNI msqid_ds struct's */
+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 */
-void
+static void
msginit(dummy)
void *dummy;
{
register int i;
+ msgpool = malloc(msginfo.msgmax, M_MSG, M_WAITOK);
+ if (msgpool == NULL)
+ panic("msgpool is NULL");
+ msgmaps = malloc(sizeof(struct msgmap) * msginfo.msgseg, M_MSG, M_WAITOK);
+ if (msgmaps == NULL)
+ panic("msgmaps is NULL");
+ 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);
+ if (msqids == NULL)
+ panic("msqids is NULL");
+
/*
* msginfo.msgssz should be a power of two for efficiency reasons.
* It is also pretty silly if msginfo.msgssz is less than 8
@@ -115,6 +190,7 @@ msginit(dummy)
msqids[i].msg_perm.seq = 0; /* reset to a known value */
}
}
+SYSINIT(sysv_msg, SI_SUB_SYSV_MSG, SI_ORDER_FIRST, msginit, NULL)
/*
* Entry point for all MSG calls
@@ -559,14 +635,7 @@ msgsnd(p, uap)
#ifdef MSG_DEBUG_OK
printf("msqid deleted\n");
#endif
- /* The SVID says to return EIDRM. */
-#ifdef EIDRM
return(EIDRM);
-#else
- /* Unfortunately, BSD doesn't define that code
- yet! */
- return(EINVAL);
-#endif
}
} else {
@@ -708,13 +777,7 @@ msgsnd(p, uap)
if (msqptr->msg_qbytes == 0) {
msg_freehdr(msghdr);
wakeup((caddr_t)msqptr);
- /* The SVID says to return EIDRM. */
-#ifdef EIDRM
return(EIDRM);
-#else
- /* Unfortunately, BSD doesn't define that code yet! */
- return(EINVAL);
-#endif
}
/*
@@ -935,13 +998,7 @@ msgrcv(p, uap)
#ifdef MSG_DEBUG_OK
printf("msqid deleted\n");
#endif
- /* The SVID says to return EIDRM. */
-#ifdef EIDRM
return(EIDRM);
-#else
- /* Unfortunately, BSD doesn't define that code yet! */
- return(EINVAL);
-#endif
}
}
OpenPOWER on IntegriCloud