2013/11/21 Ted Unangst <[email protected]>:
> 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.
And we also could return some errors that are not specified in POSIX,
too (I've added XXX for the path I found, there could be others). Not
sure, what's worse: not following standard or hiding errors.
> 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);
>
okay zhuk@