aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/sysv_sem.c
diff options
context:
space:
mode:
authorTim J. Robbins <tjr@FreeBSD.org>2003-12-19 13:07:17 +0000
committerTim J. Robbins <tjr@FreeBSD.org>2003-12-19 13:07:17 +0000
commitf5925b74365a9223710735c5935cc7c5fa06502c (patch)
tree0724d62cda807213b78ef8bf6cf65ae390044294 /sys/kern/sysv_sem.c
parent22df7d650a24281e61947913c736b7163416dc39 (diff)
downloadsrc-f5925b74365a9223710735c5935cc7c5fa06502c.tar.gz
src-f5925b74365a9223710735c5935cc7c5fa06502c.zip
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.
Notes
Notes: svn path=/head/; revision=123667
Diffstat (limited to 'sys/kern/sysv_sem.c')
-rw-r--r--sys/kern/sysv_sem.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c
index 42a4faac59a2..e07e632d8af4 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);
}