From c6ef5fb7ece1079ccd298b89b63c051cbb7b80e0 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Fri, 1 Oct 2004 11:18:10 +0000 Subject: [PATCH] * sysv_sem.cc: Update to FreeBSD version 1.69. 1.68: Reduce the overhead of semop() by using the kernel stack instead of malloc'd memory to store the operations array if it is small enough to fit. 1.69: Adjust the number of processes waiting on a semaphore properly if we're woken up in the middle of sleeping. --- winsup/cygserver/ChangeLog | 9 ++++++++ winsup/cygserver/sysv_sem.cc | 41 ++++++++++++++++++++++++------------ 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/winsup/cygserver/ChangeLog b/winsup/cygserver/ChangeLog index 99b69a24e..5597350aa 100644 --- a/winsup/cygserver/ChangeLog +++ b/winsup/cygserver/ChangeLog @@ -1,3 +1,12 @@ +2004-10-01 Corinna Vinschen + + * sysv_sem.cc: Update to FreeBSD version 1.69. + 1.68: Reduce the overhead of semop() by using the kernel stack + instead of malloc'd memory to store the operations array if it + is small enough to fit. + 1.69: Adjust the number of processes waiting on a semaphore properly + if we're woken up in the middle of sleeping. + 2004-09-23 Corinna Vinschen * sysv_shm.cc (kern_shmat): Avoid compiler warning. diff --git a/winsup/cygserver/sysv_sem.cc b/winsup/cygserver/sysv_sem.cc index bcb312d58..a4acf37f1 100644 --- a/winsup/cygserver/sysv_sem.cc +++ b/winsup/cygserver/sysv_sem.cc @@ -17,7 +17,7 @@ #ifndef __FBSDID #define __FBSDID(s) const char version[] = (s) #endif -__FBSDID("$FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/sys/kern/sysv_sem.c,v 1.67 2003/11/15 11:56:53 tjr Exp $"); +__FBSDID("$FreeBSD: /repoman/r/ncvs/src/sys/kern/sysv_sem.c,v 1.70 2004/05/30 20:34:58 phk Exp $"); #define _KERNEL 1 #define __BSD_VISIBLE 1 @@ -953,6 +953,8 @@ struct semop_args { int semop(struct thread *td, struct semop_args *uap) { +#define SMALL_SOPS 8 + struct sembuf small_sops[SMALL_SOPS]; int semid = uap->semid; size_t nsops = uap->nsops; struct sembuf *sops; @@ -976,16 +978,20 @@ semop(struct thread *td, struct semop_args *uap) return (EINVAL); /* Allocate memory for sem_ops */ - if (nsops > (unsigned long) seminfo.semopm) { + if (nsops <= SMALL_SOPS) + sops = small_sops; + else if (nsops <= (unsigned long) seminfo.semopm) + sops = (struct sembuf *) sys_malloc(nsops * sizeof(*sops), M_SEM, M_WAITOK); + else { DPRINTF(("too many sops (max=%d, nsops=%d)\n", seminfo.semopm, nsops)); return (E2BIG); } - sops = (struct sembuf *) sys_malloc(nsops * sizeof(sops[0]), M_SEM, M_WAITOK); if ((error = copyin(uap->sops, sops, nsops * sizeof(sops[0]))) != 0) { DPRINTF(("error = %d from copyin(%08x, %08x, %d)\n", error, uap->sops, sops, nsops * sizeof(sops[0]))); - sys_free(sops, M_SEM); + if (sops != small_sops) + sys_free(sops, M_SEM); return (error); } @@ -1110,15 +1116,7 @@ semop(struct thread *td, struct semop_args *uap) error = msleep(semaptr, sema_mtxp, (PZERO - 4) | PCATCH, "semwait", 0); DPRINTF(("semop: good morning (error=%d)!\n", error)); - - if (error != 0) { -#ifdef __CYGWIN__ - if (error != EIDRM) -#endif /* __CYGWIN__ */ - error = EINTR; - goto done2; - } - DPRINTF(("semop: good morning!\n")); + /* return code is checked below, after sem[nz]cnt-- */ /* * Make sure that the semaphore still exists @@ -1137,6 +1135,20 @@ semop(struct thread *td, struct semop_args *uap) semptr->semzcnt--; else semptr->semncnt--; + + /* + * Is it really morning, or was our sleep interrupted? + * (Delayed check of msleep() return code because we + * need to decrement sem[nz]cnt either way.) + */ + if (error != 0) { +#ifdef __CYGWIN__ + if (error != EIDRM) +#endif /* __CYGWIN__ */ + error = EINTR; + goto done2; + } + DPRINTF(("semop: good morning!\n")); } done: @@ -1216,7 +1228,8 @@ done: td->td_retval[0] = 0; done2: mtx_unlock(sema_mtxp); - sys_free(sops, M_SEM); + if (sops != small_sops) + sys_free(sops, M_SEM); return (error); }