> From: "Ted Unangst" <t...@tedunangst.com> > Date: Wed, 08 Jul 2020 05:20:23 -0400 > > On 2020-07-08, Ted Unangst wrote: > > I think this makes sem_init(pshared) work. > > Whoops, need more context to include the header file changes.
It is a bit of a pity that we have to expose the internals here, but I don't see an easy way to avoid that, especially since hppa requires 16-byte alignment. At least <machine/spinlock.h> doesn't do any namespace pollution as I believe a single underscore is enough here as everything is in file scope? This will require a libpthread major bump, and those are really painful! So I'm not sure we should do this just for pshared semaphores which hardly anybody uses. I wonder if we do this, should we include some additional padding in the struct for future expansion? > Index: include/semaphore.h > =================================================================== > RCS file: /home/cvs/src/include/semaphore.h,v > retrieving revision 1.1 > diff -u -p -r1.1 semaphore.h > --- include/semaphore.h 15 Oct 2017 23:40:33 -0000 1.1 > +++ include/semaphore.h 8 Jul 2020 08:47:06 -0000 > @@ -38,10 +38,16 @@ > #define _SEMAPHORE_H_ > > #include <sys/cdefs.h> > +#include <machine/spinlock.h> > > /* Opaque type definition. */ > -struct __sem; > -typedef struct __sem *sem_t; > +struct __sem { > + _atomic_lock_t lock; > + volatile int waitcount; > + volatile int value; > + int shared; > +}; > +typedef struct __sem sem_t; > struct timespec; > > #define SEM_FAILED ((sem_t *)0) > Index: lib/libc/include/thread_private.h > =================================================================== > RCS file: /home/cvs/src/lib/libc/include/thread_private.h,v > retrieving revision 1.35 > diff -u -p -r1.35 thread_private.h > --- lib/libc/include/thread_private.h 13 Feb 2019 13:22:14 -0000 1.35 > +++ lib/libc/include/thread_private.h 8 Jul 2020 08:44:45 -0000 > @@ -273,13 +273,6 @@ __END_HIDDEN_DECLS > > #define _SPINLOCK_UNLOCKED _ATOMIC_LOCK_UNLOCKED > > -struct __sem { > - _atomic_lock_t lock; > - volatile int waitcount; > - volatile int value; > - int shared; > -}; > - > TAILQ_HEAD(pthread_queue, pthread); > > #ifdef FUTEX > Index: lib/librthread/rthread.h > =================================================================== > RCS file: /home/cvs/src/lib/librthread/rthread.h,v > retrieving revision 1.64 > diff -u -p -r1.64 rthread.h > --- lib/librthread/rthread.h 13 Feb 2019 13:22:14 -0000 1.64 > +++ lib/librthread/rthread.h 8 Jul 2020 09:18:34 -0000 > @@ -79,8 +79,8 @@ struct pthread_spinlock { > (((size) + (_thread_pagesize - 1)) & ~(_thread_pagesize - 1)) > > __BEGIN_HIDDEN_DECLS > -int _sem_wait(sem_t, int, const struct timespec *, int *); > -int _sem_post(sem_t); > +int _sem_wait(sem_t *, int, const struct timespec *, int *); > +int _sem_post(sem_t *); > > void _rthread_init(void); > struct stack *_rthread_alloc_stack(pthread_t); > Index: lib/librthread/rthread_sem.c > =================================================================== > RCS file: /home/cvs/src/lib/librthread/rthread_sem.c,v > retrieving revision 1.32 > diff -u -p -r1.32 rthread_sem.c > --- lib/librthread/rthread_sem.c 6 Apr 2020 00:01:08 -0000 1.32 > +++ lib/librthread/rthread_sem.c 8 Jul 2020 09:18:34 -0000 > @@ -55,7 +55,7 @@ > * Internal implementation of semaphores > */ > int > -_sem_wait(sem_t sem, int can_eintr, const struct timespec *abstime, > +_sem_wait(sem_t *sem, int can_eintr, const struct timespec *abstime, > int *delayed_cancel) > { > unsigned int val; > @@ -86,7 +86,7 @@ _sem_wait(sem_t sem, int can_eintr, cons > > /* always increment count */ > int > -_sem_post(sem_t sem) > +_sem_post(sem_t *sem) > { > membar_exit_before_atomic(); > atomic_inc_int(&sem->value); > @@ -98,70 +98,29 @@ _sem_post(sem_t sem) > * exported semaphores > */ > int > -sem_init(sem_t *semp, int pshared, unsigned int value) > +sem_init(sem_t *sem, int pshared, unsigned int value) > { > - sem_t sem; > > if (value > SEM_VALUE_MAX) { > errno = EINVAL; > return (-1); > } > > - if (pshared) { > - errno = EPERM; > - return (-1); > -#ifdef notyet > - char name[SEM_RANDOM_NAME_LEN]; > - sem_t *sempshared; > - int i; > - > - 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, 0, value); > - if (sempshared != SEM_FAILED) > - break; > - if (errno == EEXIST) > - continue; > - if (errno != EPERM) > - errno = ENOSPC; > - return (-1); > - } > - > - /* unnamed semaphore should not be opened twice */ > - if (sem_unlink(name) == -1) { > - sem_close(sempshared); > - errno = ENOSPC; > - return (-1); > - } > - > - *semp = *sempshared; > - free(sempshared); > - return (0); > -#endif > - } > - > - sem = calloc(1, sizeof(*sem)); > - if (!sem) { > - errno = ENOSPC; > - return (-1); > - } > + memset(sem, 0, sizeof(*sem)); > sem->value = value; > - *semp = sem; > + sem->shared = pshared; > > return (0); > } > > int > -sem_destroy(sem_t *semp) > +sem_destroy(sem_t *sem) > { > - sem_t sem; > > if (!_threads_ready) /* for SEM_MMAP_SIZE */ > _rthread_init(); > > - if (!semp || !(sem = *semp)) { > + if (!sem) { > errno = EINVAL; > return (-1); > } > @@ -174,21 +133,19 @@ sem_destroy(sem_t *semp) > return (-1); > } > > - *semp = NULL; > if (sem->shared) > munmap(sem, SEM_MMAP_SIZE); > else > - free(sem); > + memset(sem, 0, sizeof(*sem)); > > return (0); > } > > int > -sem_getvalue(sem_t *semp, int *sval) > +sem_getvalue(sem_t *sem, int *sval) > { > - sem_t sem; > > - if (!semp || !(sem = *semp)) { > + if (!sem) { > errno = EINVAL; > return (-1); > } > @@ -199,11 +156,10 @@ sem_getvalue(sem_t *semp, int *sval) > } > > int > -sem_post(sem_t *semp) > +sem_post(sem_t *sem) > { > - sem_t sem; > > - if (!semp || !(sem = *semp)) { > + if (!sem) { > errno = EINVAL; > return (-1); > } > @@ -214,11 +170,10 @@ sem_post(sem_t *semp) > } > > int > -sem_wait(sem_t *semp) > +sem_wait(sem_t *sem) > { > struct tib *tib = TIB_GET(); > pthread_t self; > - sem_t sem; > int error; > PREP_CANCEL_POINT(tib); > > @@ -226,7 +181,7 @@ sem_wait(sem_t *semp) > _rthread_init(); > self = tib->tib_thread; > > - if (!semp || !(sem = *semp)) { > + if (!sem) { > errno = EINVAL; > return (-1); > } > @@ -246,15 +201,14 @@ sem_wait(sem_t *semp) > } > > int > -sem_timedwait(sem_t *semp, const struct timespec *abstime) > +sem_timedwait(sem_t *sem, const struct timespec *abstime) > { > struct tib *tib = TIB_GET(); > pthread_t self; > - sem_t sem; > int error; > PREP_CANCEL_POINT(tib); > > - if (!semp || !(sem = *semp) || abstime == NULL || > + if (!sem || abstime == NULL || > abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) { > errno = EINVAL; > return (-1); > @@ -279,12 +233,11 @@ sem_timedwait(sem_t *semp, const struct > } > > int > -sem_trywait(sem_t *semp) > +sem_trywait(sem_t *sem) > { > - sem_t sem; > unsigned int val; > > - if (!semp || !(sem = *semp)) { > + if (!sem) { > errno = EINVAL; > return (-1); > } > @@ -316,7 +269,7 @@ sem_open(const char *name, int oflag, .. > { > char sempath[SEM_PATH_SIZE]; > struct stat sb; > - sem_t sem, *semp; > + sem_t *sem; > unsigned int value = 0; > int created = 0, fd; > > @@ -382,34 +335,24 @@ sem_open(const char *name, int oflag, .. > errno = EINVAL; > return (SEM_FAILED); > } > - semp = malloc(sizeof(*semp)); > - if (!semp) { > - munmap(sem, SEM_MMAP_SIZE); > - errno = ENOSPC; > - return (SEM_FAILED); > - } > if (created) { > sem->value = value; > sem->shared = 1; > } > - *semp = sem; > > - return (semp); > + return (sem); > } > > int > -sem_close(sem_t *semp) > +sem_close(sem_t *sem) > { > - sem_t sem; > > - if (!semp || !(sem = *semp) || !sem->shared) { > + if (!sem) { > errno = EINVAL; > return (-1); > } > > - *semp = NULL; > munmap(sem, SEM_MMAP_SIZE); > - free(semp); > > return (0); > } > Index: lib/librthread/rthread_sem_compat.c > =================================================================== > RCS file: /home/cvs/src/lib/librthread/rthread_sem_compat.c,v > retrieving revision 1.1 > diff -u -p -r1.1 rthread_sem_compat.c > --- lib/librthread/rthread_sem_compat.c 8 Jun 2018 13:53:01 -0000 > 1.1 > +++ lib/librthread/rthread_sem_compat.c 8 Jul 2020 09:18:35 -0000 > @@ -53,7 +53,7 @@ > * Internal implementation of semaphores > */ > int > -_sem_wait(sem_t sem, int can_eintr, const struct timespec *abstime, > +_sem_wait(sem_t *sem, int can_eintr, const struct timespec *abstime, > int *delayed_cancel) > { > void *ident = (void *)&sem->waitcount; > @@ -87,7 +87,7 @@ _sem_wait(sem_t sem, int can_eintr, cons > > /* always increment count */ > int > -_sem_post(sem_t sem) > +_sem_post(sem_t *sem) > { > void *ident = (void *)&sem->waitcount; > int rv = 0; > @@ -109,71 +109,31 @@ _sem_post(sem_t sem) > * exported semaphores > */ > int > -sem_init(sem_t *semp, int pshared, unsigned int value) > +sem_init(sem_t *sem, int pshared, unsigned int value) > { > - sem_t sem; > > if (value > SEM_VALUE_MAX) { > errno = EINVAL; > return (-1); > } > > - if (pshared) { > - errno = EPERM; > - return (-1); > -#ifdef notyet > - char name[SEM_RANDOM_NAME_LEN]; > - sem_t *sempshared; > - int i; > - > - 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, 0, value); > - if (sempshared != SEM_FAILED) > - break; > - if (errno == EEXIST) > - continue; > - if (errno != EPERM) > - errno = ENOSPC; > - return (-1); > - } > - > - /* unnamed semaphore should not be opened twice */ > - if (sem_unlink(name) == -1) { > - sem_close(sempshared); > - errno = ENOSPC; > - return (-1); > - } > > - *semp = *sempshared; > - free(sempshared); > - return (0); > -#endif > - } > - > - sem = calloc(1, sizeof(*sem)); > - if (!sem) { > - errno = ENOSPC; > - return (-1); > - } > + memset(sem, 0, sizeof(*sem)); > sem->lock = _SPINLOCK_UNLOCKED; > sem->value = value; > - *semp = sem; > + sem->shared = pshared; > > return (0); > } > > int > -sem_destroy(sem_t *semp) > +sem_destroy(sem_t *sem) > { > - sem_t sem; > > if (!_threads_ready) /* for SEM_MMAP_SIZE */ > _rthread_init(); > > - if (!semp || !(sem = *semp)) { > + if (!sem) { > errno = EINVAL; > return (-1); > } > @@ -186,21 +146,17 @@ sem_destroy(sem_t *semp) > return (-1); > } > > - *semp = NULL; > if (sem->shared) > munmap(sem, SEM_MMAP_SIZE); > - else > - free(sem); > > return (0); > } > > int > -sem_getvalue(sem_t *semp, int *sval) > +sem_getvalue(sem_t *sem, int *sval) > { > - sem_t sem; > > - if (!semp || !(sem = *semp)) { > + if (!sem) { > errno = EINVAL; > return (-1); > } > @@ -213,11 +169,10 @@ sem_getvalue(sem_t *semp, int *sval) > } > > int > -sem_post(sem_t *semp) > +sem_post(sem_t *sem) > { > - sem_t sem; > > - if (!semp || !(sem = *semp)) { > + if (!sem) { > errno = EINVAL; > return (-1); > } > @@ -228,11 +183,10 @@ sem_post(sem_t *semp) > } > > int > -sem_wait(sem_t *semp) > +sem_wait(sem_t *sem) > { > struct tib *tib = TIB_GET(); > pthread_t self; > - sem_t sem; > int r; > PREP_CANCEL_POINT(tib); > > @@ -240,7 +194,7 @@ sem_wait(sem_t *semp) > _rthread_init(); > self = tib->tib_thread; > > - if (!semp || !(sem = *semp)) { > + if (!sem) { > errno = EINVAL; > return (-1); > } > @@ -258,15 +212,14 @@ sem_wait(sem_t *semp) > } > > int > -sem_timedwait(sem_t *semp, const struct timespec *abstime) > +sem_timedwait(sem_t *sem, const struct timespec *abstime) > { > struct tib *tib = TIB_GET(); > pthread_t self; > - sem_t sem; > int r; > PREP_CANCEL_POINT(tib); > > - if (!semp || !(sem = *semp) || abstime == NULL || > + if (!sem || abstime == NULL || > abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) { > errno = EINVAL; > return (-1); > @@ -289,12 +242,11 @@ sem_timedwait(sem_t *semp, const struct > } > > int > -sem_trywait(sem_t *semp) > +sem_trywait(sem_t *sem) > { > - sem_t sem; > int r; > > - if (!semp || !(sem = *semp)) { > + if (!sem) { > errno = EINVAL; > return (-1); > } > @@ -330,7 +282,7 @@ sem_open(const char *name, int oflag, .. > { > char sempath[SEM_PATH_SIZE]; > struct stat sb; > - sem_t sem, *semp; > + sem_t *sem; > unsigned int value = 0; > int created = 0, fd; > > @@ -396,35 +348,25 @@ sem_open(const char *name, int oflag, .. > errno = EINVAL; > return (SEM_FAILED); > } > - semp = malloc(sizeof(*semp)); > - if (!semp) { > - munmap(sem, SEM_MMAP_SIZE); > - errno = ENOSPC; > - return (SEM_FAILED); > - } > if (created) { > sem->lock = _SPINLOCK_UNLOCKED; > sem->value = value; > sem->shared = 1; > } > - *semp = sem; > > - return (semp); > + return (sem); > } > > int > -sem_close(sem_t *semp) > +sem_close(sem_t *sem) > { > - sem_t sem; > > - if (!semp || !(sem = *semp) || !sem->shared) { > + if (!sem || !sem->shared) { > errno = EINVAL; > return (-1); > } > > - *semp = NULL; > munmap(sem, SEM_MMAP_SIZE); > - free(semp); > > return (0); > } > >