Read the standard again and discovered some more missing features.

1. sem_open allows setting the value via a fourth argument. Fixed.

2. Multiple sem_open calls of the same path in the same process are
supposed to return the same pointer. Not the same semaphore, the same
pointer. This is mind boggling and hard to accomplish with this
implementation. Not fixed.

3. There are also some requirements that sem_open be atomic in
ways that it is not. We're publishing, via the filesystem, the new
semaphore before we're done initializing it. This is fixable, but
requires bizarro filesystem rename hijinks. Maybe another diff.

Index: rthread_sem.c
===================================================================
RCS file: /cvs/src/lib/librthread/rthread_sem.c,v
retrieving revision 1.13
diff -u -p -r1.13 rthread_sem.c
--- rthread_sem.c       20 Nov 2013 23:18:17 -0000      1.13
+++ rthread_sem.c       21 Nov 2013 03:34:03 -0000
@@ -24,6 +24,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <sha2.h>
+#include <stdarg.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -315,12 +316,22 @@ sem_open(const char *name, int oflag, ..
        int created = 0, fd, oerrno;
        sem_t sem;
        sem_t *semp = SEM_FAILED;
+       mode_t unusedmode;
+       unsigned value = 0;
 
        if (oflag & ~(O_CREAT | O_EXCL)) {
                errno = EINVAL;
                return (semp);
        }
 
+       if (oflag & O_CREAT) {
+               va_list ap;
+               va_start(ap, oflag);
+               unusedmode = va_arg(ap, mode_t);
+               value = va_arg(ap, unsigned);
+               va_end(ap);
+       }
+
        makesempath(name, sempath, sizeof(sempath));
        fd = open(sempath, O_RDWR | O_NOFOLLOW | oflag, 0600);
        if (fd == -1)
@@ -363,8 +374,10 @@ sem_open(const char *name, int oflag, ..
                errno = oerrno;
                return (semp);
        }
-       if (created)
+       if (created) {
                sem->lock = _SPINLOCK_UNLOCKED_ASSIGN;
+               sem->value = value;
+       }
        sem->shared = 1;
        semp = malloc(sizeof(*semp));
        if (!semp) {
@@ -382,7 +395,7 @@ int
 sem_close(sem_t *semp)
 {
        sem_t sem;
-       
+
        if (!semp || !(sem = *semp) || !sem->shared) {
                errno = EINVAL;
                return (-1);

Reply via email to