Subject: Re: ipc errors/Linux Emulation NetBSD-3BETA using Oracle
To: None <current-users@netbsd.org>
From: Chuck Silvers <chuq@chuq.com>
List: tech-kern
Date: 11/02/2005 02:11:36
--/9DWx/yDrRhgMJTb
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
On Wed, Nov 02, 2005 at 01:28:06AM +0000, Christos Zoulas wrote:
> Try to recompile with a different MAX_SOPS define in <sys/sem.h> It is
> currently 5. You might want to add a debugging message to see how much
> is needed. If you need help doing that, please let me know.
the MAX_SOPS constant seems bogus in general. there's a seminfo.semopm
global which can be changed via a SEMOPM kernel config option and
is reported by "ipcs -S", but this is ignored and MAX_SOPS used instead.
as a first step we should get rid of MAX_SOPS and use seminfo.semopm.
later we should add sysctl tunables like the other BSDs have.
a patch for the former is attached, anyone see any problems with it?
-Chuck
--/9DWx/yDrRhgMJTb
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="diff.semopm"
Index: src/sys/sys/sem.h
===================================================================
RCS file: /cvsroot/src/sys/sys/sem.h,v
retrieving revision 1.19
diff -u -p -r1.19 sem.h
--- src/sys/sys/sem.h 13 Sep 2005 01:42:51 -0000 1.19
+++ src/sys/sys/sem.h 2 Nov 2005 09:59:02 -0000
@@ -100,8 +100,6 @@ struct sembuf {
#define SEMVMX 32767 /* semaphore maximum value */
#define SEMAEM 16384 /* adjust on exit max value */
-#define MAX_SOPS 5 /* maximum # of sembuf's per semop call */
-
/*
* Permissions
*/
Index: src/sys/kern/sysv_sem.c
===================================================================
RCS file: /cvsroot/src/sys/kern/sysv_sem.c,v
retrieving revision 1.56
diff -u -p -r1.56 sysv_sem.c
--- src/sys/kern/sysv_sem.c 1 Apr 2005 11:59:37 -0000 1.56
+++ src/sys/kern/sysv_sem.c 2 Nov 2005 09:59:02 -0000
@@ -54,6 +54,7 @@ __KERNEL_RCSID(0, "$NetBSD: sysv_sem.c,v
#include <sys/kernel.h>
#include <sys/sem.h>
#include <sys/sysctl.h>
+#include <sys/malloc.h>
#include <sys/mount.h> /* XXX for <sys/syscallargs.h> */
#include <sys/sa.h>
#include <sys/syscallargs.h>
@@ -565,6 +566,8 @@ found:
return (0);
}
+#define SMALL_SOPS 8
+
int
sys_semop(l, v, retval)
struct lwp *l;
@@ -579,7 +582,8 @@ sys_semop(l, v, retval)
struct proc *p = l->l_proc;
int semid = SCARG(uap, semid), seq;
size_t nsops = SCARG(uap, nsops);
- struct sembuf sops[MAX_SOPS];
+ struct sembuf small_sops[SMALL_SOPS];
+ struct sembuf *sops;
struct semid_ds *semaptr;
struct sembuf *sopptr = NULL;
struct __sem *semptr = NULL;
@@ -588,8 +592,7 @@ sys_semop(l, v, retval)
int i, eval;
int do_wakeup, do_undos;
- SEM_PRINTF(("call to semop(%d, %p, %lld)\n", semid, sops,
- (long long)nsops));
+ SEM_PRINTF(("call to semop(%d, %p, %zd)\n", semid, sops, nsops));
semid = IPCID_TO_IX(semid); /* Convert back to zero origin */
if (semid < 0 || semid >= seminfo.semmni)
@@ -606,23 +609,28 @@ sys_semop(l, v, retval)
return (eval);
}
- if (nsops > MAX_SOPS) {
- SEM_PRINTF(("too many sops (max=%d, nsops=%lld)\n", MAX_SOPS,
- (long long)nsops));
+ if (nsops <= SMALL_SOPS) {
+ sops = small_sops;
+ } else if (nsops <= seminfo.semopm) {
+ sops = malloc(nsops * sizeof(*sops), M_TEMP, M_WAITOK);
+ } else {
+ SEM_PRINTF(("too many sops (max=%d, nsops=%zd)\n",
+ seminfo.semopm, nsops));
return (E2BIG);
}
if ((eval = copyin(SCARG(uap, sops),
sops, nsops * sizeof(sops[0]))) != 0) {
- SEM_PRINTF(("eval = %d from copyin(%p, %p, %lld)\n", eval,
- SCARG(uap, sops), &sops,
- (long long)(nsops * sizeof(sops[0]))));
- return (eval);
+ SEM_PRINTF(("eval = %d from copyin(%p, %p, %zd)\n", eval,
+ SCARG(uap, sops), &sops, nsops * sizeof(sops[0])));
+ goto out;
}
for (i = 0; i < nsops; i++)
- if (sops[i].sem_num >= semaptr->sem_nsems)
- return (EFBIG);
+ if (sops[i].sem_num >= semaptr->sem_nsems) {
+ eval = EFBIG;
+ goto out;
+ }
/*
* Loop trying to satisfy the vector of requests.
@@ -695,8 +703,10 @@ sys_semop(l, v, retval)
* If the request that we couldn't satisfy has the
* NOWAIT flag set then return with EAGAIN.
*/
- if (sopptr->sem_flg & IPC_NOWAIT)
- return (EAGAIN);
+ if (sopptr->sem_flg & IPC_NOWAIT) {
+ eval = EAGAIN;
+ goto out;
+ }
if (sopptr->sem_op == 0)
semptr->semzcnt++;
@@ -713,13 +723,8 @@ sys_semop(l, v, retval)
*/
if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0 ||
semaptr->sem_perm._seq != seq) {
- /* The man page says to return EIDRM. */
- /* Unfortunately, BSD doesn't define that code! */
-#ifdef EIDRM
- return (EIDRM);
-#else
- return (EINVAL);
-#endif
+ eval = EIDRM;
+ goto out;
}
/*
@@ -736,8 +741,10 @@ sys_semop(l, v, retval)
* (Delayed check of tsleep() return code because we
* need to decrement sem[nz]cnt either way.)
*/
- if (eval != 0)
- return (EINTR);
+ if (eval != 0) {
+ eval = EINTR;
+ goto out;
+ }
SEM_PRINTF(("semop: good morning!\n"));
}
@@ -788,7 +795,7 @@ done:
sops[i].sem_op;
SEM_PRINTF(("eval = %d from semundo_adjust\n", eval));
- return (eval);
+ goto out;
} /* loop through the sops */
} /* if (do_undos) */
@@ -814,7 +821,12 @@ done:
}
SEM_PRINTF(("semop: done\n"));
*retval = 0;
- return (0);
+
+out:
+ if (sops != small_sops) {
+ free(sops, M_TEMP);
+ }
+ return eval;
}
/*
--/9DWx/yDrRhgMJTb--