diff options
author | tjr <tjr@FreeBSD.org> | 2003-12-19 13:07:17 +0000 |
---|---|---|
committer | tjr <tjr@FreeBSD.org> | 2003-12-19 13:07:17 +0000 |
commit | 50207b49b7023e9dddefa0910c7bb006aa4ddaaf (patch) | |
tree | 0724d62cda807213b78ef8bf6cf65ae390044294 /sys/kern/sysv_sem.c | |
parent | c7be5e14dca38359438c2fb698ff8d5c6c75d0f7 (diff) | |
download | FreeBSD-src-50207b49b7023e9dddefa0910c7bb006aa4ddaaf.zip FreeBSD-src-50207b49b7023e9dddefa0910c7bb006aa4ddaaf.tar.gz |
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.
Diffstat (limited to 'sys/kern/sysv_sem.c')
-rw-r--r-- | sys/kern/sysv_sem.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c index 42a4faa..e07e632 100644 --- a/sys/kern/sysv_sem.c +++ b/sys/kern/sysv_sem.c @@ -877,6 +877,8 @@ semop(td, uap) 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; @@ -900,16 +902,20 @@ semop(td, uap) return (EINVAL); /* Allocate memory for sem_ops */ - if (nsops > seminfo.semopm) { + if (nsops <= SMALL_SOPS) + sops = small_sops; + else if (nsops <= seminfo.semopm) + sops = malloc(nsops * sizeof(*sops), M_TEMP, M_WAITOK); + else { DPRINTF(("too many sops (max=%d, nsops=%d)\n", seminfo.semopm, nsops)); return (E2BIG); } - sops = 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]))); - free(sops, M_SEM); + if (sops != small_sops) + free(sops, M_SEM); return (error); } @@ -1137,7 +1143,8 @@ done: td->td_retval[0] = 0; done2: mtx_unlock(sema_mtxp); - free(sops, M_SEM); + if (sops != small_sops) + free(sops, M_SEM); return (error); } |