diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/librthread/rthread_sem.c | 81 |
1 files changed, 37 insertions, 44 deletions
diff --git a/lib/librthread/rthread_sem.c b/lib/librthread/rthread_sem.c index bb6a9e1b483..20c7aecef29 100644 --- a/lib/librthread/rthread_sem.c +++ b/lib/librthread/rthread_sem.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rthread_sem.c,v 1.15 2013/11/22 07:48:41 deraadt Exp $ */ +/* $OpenBSD: rthread_sem.c,v 1.16 2013/11/26 11:24:43 fgsch Exp $ */ /* * Copyright (c) 2004,2005,2013 Ted Unangst <tedu@openbsd.org> * All Rights Reserved. @@ -20,7 +20,6 @@ #include <sys/mman.h> #include <sys/stat.h> -#include <err.h> #include <errno.h> #include <fcntl.h> #include <sha2.h> @@ -114,50 +113,42 @@ _sem_post(sem_t sem) int sem_init(sem_t *semp, int pshared, unsigned int value) { - sem_t sem, *sempshared; - int i, oerrno; char name[SEM_RANDOM_NAME_LEN]; + sem_t sem, *sempshared; + int i; - if (!semp) { + if (value > SEM_VALUE_MAX) { errno = EINVAL; return (-1); } if (pshared) { - while (1) { + for (;;) { for (i = 0; i < SEM_RANDOM_NAME_LEN - 1; i++) name[i] = arc4random_uniform(255) + 1; name[SEM_RANDOM_NAME_LEN - 1] = '\0'; - sempshared = sem_open(name, O_CREAT|O_EXCL); - if (sempshared) + sempshared = sem_open(name, O_CREAT | O_EXCL, 0, value); + if (sempshared != SEM_FAILED) break; if (errno == EEXIST) continue; - if (errno != EINVAL && errno != EPERM) + if (errno != EPERM) errno = ENOSPC; return (-1); } /* unnamed semaphore should not be opened twice */ if (sem_unlink(name) == -1) { - oerrno = errno; sem_close(sempshared); - errno = oerrno; + errno = ENOSPC; return (-1); } - sem = *sempshared; - sem->value = value; - *semp = sem; + *semp = *sempshared; free(sempshared); return (0); } - if (value > SEM_VALUE_MAX) { - errno = EINVAL; - return (-1); - } - sem = calloc(1, sizeof(*sem)); if (!sem) { errno = ENOSPC; @@ -313,79 +304,80 @@ sem_open(const char *name, int oflag, ...) { char sempath[SEM_PATH_SIZE]; struct stat sb; - int created = 0, fd, oerrno; - sem_t sem; - sem_t *semp = SEM_FAILED; - mode_t unusedmode; - unsigned value = 0; + sem_t sem, *semp; + unsigned int value = 0; + int created = 0, fd; if (oflag & ~(O_CREAT | O_EXCL)) { errno = EINVAL; - return (semp); + return (SEM_FAILED); } if (oflag & O_CREAT) { va_list ap; va_start(ap, oflag); - unusedmode = va_arg(ap, mode_t); + /* 3rd parameter mode is not used */ + va_arg(ap, mode_t); value = va_arg(ap, unsigned); va_end(ap); + + if (value > SEM_VALUE_MAX) { + errno = EINVAL; + return (SEM_FAILED); + } } makesempath(name, sempath, sizeof(sempath)); fd = open(sempath, O_RDWR | O_NOFOLLOW | oflag, 0600); if (fd == -1) - return (semp); + return (SEM_FAILED); if (fstat(fd, &sb) == -1 || !S_ISREG(sb.st_mode)) { close(fd); errno = EINVAL; - return (semp); + return (SEM_FAILED); } if (sb.st_uid != getuid()) { close(fd); errno = EPERM; - return (semp); + return (SEM_FAILED); } if (sb.st_size != SEM_MMAP_SIZE) { if (!(oflag & O_CREAT)) { close(fd); errno = EINVAL; - return (semp); + return (SEM_FAILED); } if (sb.st_size != 0) { close(fd); errno = EINVAL; - return (semp); + return (SEM_FAILED); } if (ftruncate(fd, SEM_MMAP_SIZE) == -1) { - oerrno = errno; close(fd); - errno = oerrno; - /* XXX can set errno to EIO, ENOTDIR... */ - return (semp); + errno = EINVAL; + return (SEM_FAILED); } + created = 1; } sem = mmap(NULL, SEM_MMAP_SIZE, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED | MAP_HASSEMAPHORE, fd, 0); - oerrno = errno; close(fd); if (sem == MAP_FAILED) { - errno = oerrno; - return (semp); - } - if (created) { - sem->lock = _SPINLOCK_UNLOCKED_ASSIGN; - sem->value = value; + errno = EINVAL; + return (SEM_FAILED); } - sem->shared = 1; semp = malloc(sizeof(*semp)); if (!semp) { - free(semp); munmap(sem, SEM_MMAP_SIZE); errno = ENOSPC; return (SEM_FAILED); } + if (created) { + sem->lock = _SPINLOCK_UNLOCKED_ASSIGN; + sem->value = value; + sem->shared = 1; + } *semp = sem; return (semp); @@ -401,6 +393,7 @@ sem_close(sem_t *semp) return (-1); } + *semp = NULL; munmap(sem, SEM_MMAP_SIZE); free(semp); |