summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
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