summaryrefslogtreecommitdiffstats
path: root/sys/kern
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
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')
-rw-r--r--sys/kern/subr_param.c45
-rw-r--r--sys/kern/sysv_msg.c129
-rw-r--r--sys/kern/sysv_sem.c143
3 files changed, 222 insertions, 95 deletions
diff --git a/sys/kern/subr_param.c b/sys/kern/subr_param.c
index f26c3ba..42b124d 100644
--- a/sys/kern/subr_param.c
+++ b/sys/kern/subr_param.c
@@ -41,18 +41,10 @@
#include <stddef.h>
-#include "opt_sysvipc.h"
#include "opt_param.h"
#include <sys/param.h>
-#ifdef SYSVSEM
-#include <sys/sem.h>
-#endif
-#ifdef SYSVMSG
-#include <sys/msg.h>
-#endif
-
/*
* System parameter formulae.
*
@@ -87,43 +79,6 @@ int mbuf_wait = 32; /* mbuf sleep time in ticks */
int nsfbufs = NSFBUFS;
/*
- * Values in support of System V compatible semaphores.
- */
-
-#ifdef SYSVSEM
-
-struct seminfo seminfo = {
- SEMMAP, /* # of entries in semaphore map */
- SEMMNI, /* # of semaphore identifiers */
- SEMMNS, /* # of semaphores in system */
- SEMMNU, /* # of undo structures in system */
- SEMMSL, /* max # of semaphores per id */
- SEMOPM, /* max # of operations per semop call */
- SEMUME, /* max # of undo entries per process */
- SEMUSZ, /* size in bytes of undo structure */
- SEMVMX, /* semaphore maximum value */
- SEMAEM /* adjust on exit max value */
-};
-#endif
-
-/*
- * Values in support of System V compatible messages.
- */
-
-#ifdef SYSVMSG
-
-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 */
-};
-#endif
-
-/*
* These may be set to nonzero here or by patching.
* If they are nonzero at bootstrap time then they are
* initialized to values dependent on the memory size.
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
}
}
diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c
index 944ae66..7d78bfd 100644
--- a/sys/kern/sysv_sem.c
+++ b/sys/kern/sysv_sem.c
@@ -8,6 +8,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>
@@ -15,9 +17,12 @@
#include <sys/proc.h>
#include <sys/sem.h>
#include <sys/sysent.h>
+#include <sys/sysctl.h>
+#include <sys/malloc.h>
+
+static MALLOC_DEFINE(M_SEM, "sem", "SVID compatible semaphores");
static void seminit __P((void *));
-SYSINIT(sysv_sem, SI_SUB_SYSV_SEM, SI_ORDER_FIRST, seminit, NULL)
#ifndef _SYS_SYSPROTO_H_
struct __semctl_args;
@@ -40,19 +45,135 @@ static sy_call_t *semcalls[] = {
};
static int semtot = 0;
-struct semid_ds *sema; /* semaphore id pool */
-struct sem *sem; /* semaphore pool */
-static struct sem_undo *semu_list; /* list of active undo structures */
-int *semu; /* undo structure pool */
+static struct semid_ds *sema; /* semaphore id pool */
+static struct sem *sem; /* semaphore pool */
+static struct sem_undo *semu_list; /* list of active undo structures */
+static int *semu; /* undo structure pool */
+
+struct sem {
+ u_short semval; /* semaphore value */
+ pid_t sempid; /* pid of last operation */
+ u_short semncnt; /* # awaiting semval > cval */
+ u_short semzcnt; /* # awaiting semval = 0 */
+};
-void
+/*
+ * Undo structure (one per process)
+ */
+struct sem_undo {
+ struct sem_undo *un_next; /* ptr to next active undo structure */
+ struct proc *un_proc; /* owner of this structure */
+ short un_cnt; /* # of active entries */
+ struct undo {
+ short un_adjval; /* adjust on exit values */
+ short un_num; /* semaphore # */
+ int un_id; /* semid */
+ } un_ent[1]; /* undo entries */
+};
+
+/*
+ * Configuration parameters
+ */
+#ifndef SEMMNI
+#define SEMMNI 10 /* # of semaphore identifiers */
+#endif
+#ifndef SEMMNS
+#define SEMMNS 60 /* # of semaphores in system */
+#endif
+#ifndef SEMUME
+#define SEMUME 10 /* max # of undo entries per process */
+#endif
+#ifndef SEMMNU
+#define SEMMNU 30 /* # of undo structures in system */
+#endif
+
+/* shouldn't need tuning */
+#ifndef SEMMAP
+#define SEMMAP 30 /* # of entries in semaphore map */
+#endif
+#ifndef SEMMSL
+#define SEMMSL SEMMNS /* max # of semaphores per id */
+#endif
+#ifndef SEMOPM
+#define SEMOPM 100 /* max # of operations per semop call */
+#endif
+
+#define SEMVMX 32767 /* semaphore maximum value */
+#define SEMAEM 16384 /* adjust on exit max value */
+
+/*
+ * Due to the way semaphore memory is allocated, we have to ensure that
+ * SEMUSZ is properly aligned.
+ */
+
+#ifndef offsetof
+#define offsetof(type, member) ((size_t)(&((type *)0)->member))
+#endif
+
+#define SEM_ALIGN(bytes) (((bytes) + (sizeof(long) - 1)) & ~(sizeof(long) - 1))
+
+/* actual size of an undo structure */
+#define SEMUSZ SEM_ALIGN(offsetof(struct sem_undo, un_ent[SEMUME]))
+
+/*
+ * Macro to find a particular sem_undo vector
+ */
+#define SEMU(ix) ((struct sem_undo *)(((intptr_t)semu)+ix * seminfo.semusz))
+
+/*
+ * semaphore info struct
+ */
+struct seminfo seminfo = {
+ SEMMAP, /* # of entries in semaphore map */
+ SEMMNI, /* # of semaphore identifiers */
+ SEMMNS, /* # of semaphores in system */
+ SEMMNU, /* # of undo structures in system */
+ SEMMSL, /* max # of semaphores per id */
+ SEMOPM, /* max # of operations per semop call */
+ SEMUME, /* max # of undo entries per process */
+ SEMUSZ, /* size in bytes of undo structure */
+ SEMVMX, /* semaphore maximum value */
+ SEMAEM /* adjust on exit max value */
+};
+
+SYSCTL_DECL(_kern_ipc);
+SYSCTL_INT(_kern_ipc, OID_AUTO, semmap, CTLFLAG_RW, &seminfo.semmap, 0, "");
+SYSCTL_INT(_kern_ipc, OID_AUTO, semmni, CTLFLAG_RD, &seminfo.semmni, 0, "");
+SYSCTL_INT(_kern_ipc, OID_AUTO, semmns, CTLFLAG_RD, &seminfo.semmns, 0, "");
+SYSCTL_INT(_kern_ipc, OID_AUTO, semmnu, CTLFLAG_RD, &seminfo.semmnu, 0, "");
+SYSCTL_INT(_kern_ipc, OID_AUTO, semmsl, CTLFLAG_RW, &seminfo.semmsl, 0, "");
+SYSCTL_INT(_kern_ipc, OID_AUTO, semopm, CTLFLAG_RD, &seminfo.semopm, 0, "");
+SYSCTL_INT(_kern_ipc, OID_AUTO, semume, CTLFLAG_RD, &seminfo.semume, 0, "");
+SYSCTL_INT(_kern_ipc, OID_AUTO, semusz, CTLFLAG_RD, &seminfo.semusz, 0, "");
+SYSCTL_INT(_kern_ipc, OID_AUTO, semvmx, CTLFLAG_RW, &seminfo.semvmx, 0, "");
+SYSCTL_INT(_kern_ipc, OID_AUTO, semaem, CTLFLAG_RW, &seminfo.semaem, 0, "");
+
+#if 0
+RO seminfo.semmap /* SEMMAP unused */
+RO seminfo.semmni
+RO seminfo.semmns
+RO seminfo.semmnu /* undo entries per system */
+RW seminfo.semmsl
+RO seminfo.semopm /* SEMOPM unused */
+RO seminfo.semume
+RO seminfo.semusz /* param - derived from SEMUME for per-proc sizeof */
+RO seminfo.semvmx /* SEMVMX unused - user param */
+RO seminfo.semaem /* SEMAEM unused - user param */
+#endif
+
+static void
seminit(dummy)
void *dummy;
{
register int i;
+ sem = malloc(sizeof(struct sem) * seminfo.semmns, M_SEM, M_WAITOK);
+ if (sem == NULL)
+ panic("sem is NULL");
+ sema = malloc(sizeof(struct semid_ds) * seminfo.semmni, M_SEM, M_WAITOK);
if (sema == NULL)
panic("sema is NULL");
+ semu = malloc(seminfo.semmnu * seminfo.semusz, M_SEM, M_WAITOK);
if (semu == NULL)
panic("semu is NULL");
@@ -66,6 +187,7 @@ seminit(dummy)
}
semu_list = NULL;
}
+SYSINIT(sysv_sem, SI_SUB_SYSV_SEM, SI_ORDER_FIRST, seminit, NULL)
/*
* Entry point for all SEM calls
@@ -708,15 +830,8 @@ semop(p, 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)) {
- /* The man page says to return EIDRM. */
- /* Unfortunately, BSD doesn't define that code! */
-#ifdef EIDRM
+ semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid))
return(EIDRM);
-#else
- return(EINVAL);
-#endif
- }
/*
* The semaphore is still alive. Readjust the count of
OpenPOWER on IntegriCloud