Fix a few things. I think I started down the sem inside a sem road
because I misunderstood some minor point of the API. Turns out it's
entirely possible to just map the semaphore and be done with it. We
only need a flag to identify shared semaphores. This makes everything
a little bit easier.

In the process of adding einval checking to sem_close, I noticed
that the inval checks are all broken because they deref a pointer
before checking for null. So fix all of those.

Index: rthread.h
===================================================================
RCS file: /cvs/src/lib/librthread/rthread.h,v
retrieving revision 1.46
diff -u -p -r1.46 rthread.h
--- rthread.h   18 Nov 2013 23:10:48 -0000      1.46
+++ rthread.h   20 Nov 2013 19:04:23 -0000
@@ -64,7 +64,7 @@ struct __sem {
        struct _spinlock lock;
        volatile int waitcount;
        volatile int value;
-       struct __sem *shared;
+       int shared;
 };
 
 TAILQ_HEAD(pthread_queue, pthread);
Index: rthread_sem.c
===================================================================
RCS file: /cvs/src/lib/librthread/rthread_sem.c,v
retrieving revision 1.12
diff -u -p -r1.12 rthread_sem.c
--- rthread_sem.c       20 Nov 2013 03:16:39 -0000      1.12
+++ rthread_sem.c       20 Nov 2013 19:04:23 -0000
@@ -58,10 +58,8 @@ _sem_wait(sem_t sem, int tryonly, const 
        void *ident = (void *)&sem->waitcount;
        int r;
 
-       if (sem->shared) {
-               sem = sem->shared;
+       if (sem->shared)
                ident = SHARED_IDENT;
-       }
 
        _spinlock(&sem->lock);
        if (sem->value) {
@@ -96,10 +94,8 @@ _sem_post(sem_t sem)
        void *ident = (void *)&sem->waitcount;
        int rv = 0;
 
-       if (sem->shared) {
-               sem = sem->shared;
+       if (sem->shared)
                ident = SHARED_IDENT;
-       }
 
        _spinlock(&sem->lock);
        sem->value++;
@@ -119,7 +115,12 @@ sem_init(sem_t *semp, int pshared, unsig
 {
        sem_t sem, *sempshared;
        int i, oerrno;
-       char name[SEM_RANDOM_NAME_LEN];    
+       char name[SEM_RANDOM_NAME_LEN];
+
+       if (!semp) {
+               errno = EINVAL;
+               return (-1);
+       }
 
        if (pshared) {
                while (1) {
@@ -145,9 +146,9 @@ sem_init(sem_t *semp, int pshared, unsig
                }
 
                sem = *sempshared;
-               free(sempshared);
                sem->value = value;
                *semp = sem;
+               free(sempshared);
                return (0);
        }
 
@@ -173,11 +174,10 @@ sem_destroy(sem_t *semp)
 {
        sem_t sem;
 
-       if (!semp || !*semp) {
+       if (!semp || !(sem = *semp)) {
                errno = EINVAL;
                return (-1);
        }
-       sem = *semp;
 
        if (sem->waitcount) {
 #define MSG "sem_destroy on semaphore with waiters!\n"
@@ -187,11 +187,11 @@ sem_destroy(sem_t *semp)
                return (-1);
        }
 
-       if (sem->shared)
-               munmap(sem->shared, SEM_MMAP_SIZE);
-
        *semp = NULL;
-       free(sem);
+       if (sem->shared)
+               munmap(sem, SEM_MMAP_SIZE);
+       else
+               free(sem);
 
        return (0);
 }
@@ -199,16 +199,13 @@ sem_destroy(sem_t *semp)
 int
 sem_getvalue(sem_t *semp, int *sval)
 {
-       sem_t sem = *semp;
+       sem_t sem;
 
-       if (!semp || !*semp) {
+       if (!semp || !(sem = *semp)) {
                errno = EINVAL;
                return (-1);
        }
 
-       if (sem->shared)
-               sem = sem->shared;
-
        _spinlock(&sem->lock);
        *sval = sem->value;
        _spinunlock(&sem->lock);
@@ -219,9 +216,9 @@ sem_getvalue(sem_t *semp, int *sval)
 int
 sem_post(sem_t *semp)
 {
-       sem_t sem = *semp;
+       sem_t sem;
 
-       if (!semp || !*semp) {
+       if (!semp || !(sem = *semp)) {
                errno = EINVAL;
                return (-1);
        }
@@ -234,11 +231,11 @@ sem_post(sem_t *semp)
 int
 sem_wait(sem_t *semp)
 {
-       sem_t sem = *semp;
        pthread_t self = pthread_self();
+       sem_t sem;
        int r;
 
-       if (!semp || !*semp) {
+       if (!semp || !(sem = *semp)) {
                errno = EINVAL;
                return (-1);
        }
@@ -258,11 +255,11 @@ sem_wait(sem_t *semp)
 int
 sem_timedwait(sem_t *semp, const struct timespec *abstime)
 {
-       sem_t sem = *semp;
        pthread_t self = pthread_self();
+       sem_t sem;
        int r;
 
-       if (!semp || !*semp) {
+       if (!semp || !(sem = *semp)) {
                errno = EINVAL;
                return (-1);
        }
@@ -282,10 +279,10 @@ sem_timedwait(sem_t *semp, const struct 
 int
 sem_trywait(sem_t *semp)
 {
-       sem_t sem = *semp;
+       sem_t sem;
        int r;
 
-       if (!semp || !*semp) {
+       if (!semp || !(sem = *semp)) {
                errno = EINVAL;
                return (-1);
        }
@@ -316,7 +313,7 @@ sem_open(const char *name, int oflag, ..
        char sempath[SEM_PATH_SIZE];
        struct stat sb;
        int fd, oerrno;
-       sem_t sem, shared;
+       sem_t sem;
        sem_t *semp = SEM_FAILED;
 
        if (oflag & ~(O_CREAT | O_EXCL)) {
@@ -338,7 +335,17 @@ sem_open(const char *name, int oflag, ..
                errno = EPERM;
                return (semp);
        }
-       if (sb.st_size < SEM_MMAP_SIZE) {
+       if (sb.st_size != SEM_MMAP_SIZE) {
+               if (!(oflag & O_CREAT)) {
+                       close(fd);
+                       errno = EINVAL;
+                       return (semp);
+               }
+               if (sb.st_size != 0) {
+                       close(fd);
+                       errno = EINVAL;
+                       return (semp);
+               }
                if (ftruncate(fd, SEM_MMAP_SIZE) == -1) {
                        oerrno = errno;
                        close(fd);
@@ -347,25 +354,23 @@ sem_open(const char *name, int oflag, ..
                        return (semp);
                }
        }
-       shared = mmap(NULL, SEM_MMAP_SIZE, PROT_READ | PROT_WRITE,
+       sem = mmap(NULL, SEM_MMAP_SIZE, PROT_READ | PROT_WRITE,
            MAP_FILE | MAP_SHARED | MAP_HASSEMAPHORE, fd, 0);
        oerrno = errno;
        close(fd);
-       if (shared == MAP_FAILED) {
+       if (sem == MAP_FAILED) {
                errno = oerrno;
                return (semp);
        }
+       sem->shared = 1;
        semp = malloc(sizeof(*semp));
-       sem = calloc(1, sizeof(*sem));
-       if (!semp || !sem) {
-               free(sem);
+       if (!semp) {
                free(semp);
-               munmap(shared, SEM_MMAP_SIZE);
+               munmap(sem, SEM_MMAP_SIZE);
                errno = ENOSPC;
                return (SEM_FAILED);
        }
        *semp = sem;
-       sem->shared = shared;
 
        return (semp);
 }
@@ -373,10 +378,14 @@ sem_open(const char *name, int oflag, ..
 int
 sem_close(sem_t *semp)
 {
-       sem_t sem = *semp;
+       sem_t sem;
+       
+       if (!semp || !(sem = *semp) || !sem->shared) {
+               errno = EINVAL;
+               return (-1);
+       }
 
-       munmap(sem->shared, SEM_MMAP_SIZE);
-       free(sem);
+       munmap(sem, SEM_MMAP_SIZE);
        free(semp);
 
        return (0);
@@ -390,4 +399,3 @@ sem_unlink(const char *name)
        makesempath(name, sempath, sizeof(sempath));
        return (unlink(sempath));
 }
-


Reply via email to