diff options
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/subr_param.c | 45 | ||||
-rw-r--r-- | sys/kern/sysv_msg.c | 129 | ||||
-rw-r--r-- | sys/kern/sysv_sem.c | 143 |
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 |