Date: Sat, 25 Oct 2014 01:35:22 +0000 From: "Bjoern A. Zeeb" <bz@FreeBSD.org> To: John Baldwin <jhb@FreeBSD.org> Cc: svn-src-head@freebsd.org, svn-src-all@freebsd.org, src-committers@freebsd.org Subject: Re: svn commit: r273604 - in head: include lib/libc/gen sys/kern sys/sys usr.bin/truss Message-ID: <88B273DE-C9EB-4C11-AE9E-0136BC2324C2@FreeBSD.org> In-Reply-To: <201410242002.s9OK2i3w018818@svn.freebsd.org> References: <201410242002.s9OK2i3w018818@svn.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On 24 Oct 2014, at 20:02 , John Baldwin <jhb@FreeBSD.org> wrote: > Author: jhb > Date: Fri Oct 24 20:02:44 2014 > New Revision: 273604 > URL: https://svnweb.freebsd.org/changeset/base/273604 >=20 > Log: > The current POSIX semaphore implementation stores the _has_waiters = flag > in a separate word from the _count. This does not permit both items = to > be updated atomically in a portable manner. As a result, sem_post() > must always perform a system call to safely clear _has_waiters. >=20 > This change removes the _has_waiters field and instead uses the high = bit > of _count as the _has_waiters flag. A new umtx object type (_usem2) = and > two new umtx operations are added (SEM_WAIT2 and SEM_WAKE2) to = implement > these semantics. The older operations are still supported under the > COMPAT_FREEBSD9/10 options. The POSIX semaphore API in libc has > been updated to use the new implementation. Note that the new > implementation is not compatible with the previous implementation. > However, this only affects static binaries (which cannot be helped by > symbol versioning). Binaries using a dynamic libc will continue to = work > fine. SEM_MAGIC has been bumped so that mismatched binaries will = error > rather than corrupting a shared semaphore. In addition, a padding = field > has been added to sem_t so that it remains the same size. >=20 > Differential Revision: https://reviews.freebsd.org/D961 > Reported by: adrian > Reviewed by: kib, jilles (earlier version) > Sponsored by: Norse >=20 > Modified: > head/include/semaphore.h > head/lib/libc/gen/sem_new.c > head/sys/kern/kern_umtx.c > head/sys/sys/_umtx.h > head/sys/sys/umtx.h > head/usr.bin/truss/syscalls.c >=20 Has anyone fixed this: /scratch/tmp/bz/head.svn/sys/kern/kern_umtx.c:2898:21: error: passing = 'volatile __uint32_t *' (aka 'volatile unsigned int *') to parameter of = type 'const void *' discards qualifiers = [-Werror,-Wincompatible-pointer-types-discards-qualifier s] count =3D fuword32(&sem->_count); ^~~~~~~~~~~~ /scratch/tmp/bz/head.svn/sys/sys/systm.h:258:30: note: passing argument = to parameter 'base' here int32_t fuword32(const void *base); ^ 1 error generated. --- kern_umtx.o --- *** [kern_umtx.o] Error code 1 cc1: warnings being treated as errors /scratch/tmp/bz/head.svn/sys/kern/kern_umtx.c: In function = 'do_sem2_wake': /scratch/tmp/bz/head.svn/sys/kern/kern_umtx.c:2898: warning: passing = argument 1 of 'fuword32' discards qualifiers from pointer target type --- kern_umtx.o --- *** [kern_umtx.o] Error code 1 > Modified: head/sys/kern/kern_umtx.c > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- head/sys/kern/kern_umtx.c Fri Oct 24 19:58:24 2014 = (r273603) > +++ head/sys/kern/kern_umtx.c Fri Oct 24 20:02:44 2014 = (r273604) > @@ -2710,6 +2710,7 @@ out: > return (error); > } >=20 > +#if defined(COMPAT_FREEBSD9) || defined(COMPAT_FREEBSD10) > static int > do_sem_wait(struct thread *td, struct _usem *sem, struct _umtx_time = *timeout) > { > @@ -2731,7 +2732,7 @@ do_sem_wait(struct thread *td, struct _u > umtxq_busy(&uq->uq_key); > umtxq_insert(uq); > umtxq_unlock(&uq->uq_key); > - casuword32(__DEVOLATILE(uint32_t *, &sem->_has_waiters), 0, 1); > + casuword32(&sem->_has_waiters, 0, 1); > count =3D fuword32(__DEVOLATILE(uint32_t *, &sem->_count)); > if (count !=3D 0) { > umtxq_lock(&uq->uq_key); > @@ -2761,7 +2762,7 @@ do_sem_wait(struct thread *td, struct _u > } >=20 > /* > - * Signal a userland condition variable. > + * Signal a userland semaphore. > */ > static int > do_sem_wake(struct thread *td, struct _usem *sem) > @@ -2795,6 +2796,119 @@ do_sem_wake(struct thread *td, struct _u > umtx_key_release(&key); > return (error); > } > +#endif > + > +static int > +do_sem2_wait(struct thread *td, struct _usem2 *sem, struct _umtx_time = *timeout) > +{ > + struct abs_timeout timo; > + struct umtx_q *uq; > + uint32_t count, flags; > + int error; > + > + uq =3D td->td_umtxq; > + flags =3D fuword32(&sem->_flags); > + error =3D umtx_key_get(sem, TYPE_SEM, GET_SHARE(flags), = &uq->uq_key); > + if (error !=3D 0) > + return (error); > + > + if (timeout !=3D NULL) > + abs_timeout_init2(&timo, timeout); > + > + umtxq_lock(&uq->uq_key); > + umtxq_busy(&uq->uq_key); > + umtxq_insert(uq); > + umtxq_unlock(&uq->uq_key); > + count =3D fuword32(__DEVOLATILE(uint32_t *, &sem->_count)); > + if (count =3D=3D -1) { > + umtxq_lock(&uq->uq_key); > + umtxq_unbusy(&uq->uq_key); > + umtxq_remove(uq); > + umtxq_unlock(&uq->uq_key); > + umtx_key_release(&uq->uq_key); > + return (EFAULT); > + } > + for (;;) { > + if (USEM_COUNT(count) !=3D 0) { > + umtxq_lock(&uq->uq_key); > + umtxq_unbusy(&uq->uq_key); > + umtxq_remove(uq); > + umtxq_unlock(&uq->uq_key); > + umtx_key_release(&uq->uq_key); > + return (0); > + } > + if (count =3D=3D USEM_HAS_WAITERS) > + break; > + count =3D casuword32(&sem->_count, 0, USEM_HAS_WAITERS); > + if (count =3D=3D -1) { > + umtxq_lock(&uq->uq_key); > + umtxq_unbusy(&uq->uq_key); > + umtxq_remove(uq); > + umtxq_unlock(&uq->uq_key); > + umtx_key_release(&uq->uq_key); > + return (EFAULT); > + } > + if (count =3D=3D 0) > + break; > + } > + umtxq_lock(&uq->uq_key); > + umtxq_unbusy(&uq->uq_key); > + > + error =3D umtxq_sleep(uq, "usem", timeout =3D=3D NULL ? NULL : = &timo); > + > + if ((uq->uq_flags & UQF_UMTXQ) =3D=3D 0) > + error =3D 0; > + else { > + umtxq_remove(uq); > + /* A relative timeout cannot be restarted. */ > + if (error =3D=3D ERESTART && timeout !=3D NULL && > + (timeout->_flags & UMTX_ABSTIME) =3D=3D 0) > + error =3D EINTR; > + } > + umtxq_unlock(&uq->uq_key); > + umtx_key_release(&uq->uq_key); > + return (error); > +} > + > +/* > + * Signal a userland semaphore. > + */ > +static int > +do_sem2_wake(struct thread *td, struct _usem2 *sem) > +{ > + struct umtx_key key; > + int error, cnt; > + uint32_t count, flags; > + > + flags =3D fuword32(&sem->_flags); > + if ((error =3D umtx_key_get(sem, TYPE_SEM, GET_SHARE(flags), = &key)) !=3D 0) > + return (error);=09 > + umtxq_lock(&key); > + umtxq_busy(&key); > + cnt =3D umtxq_count(&key); > + if (cnt > 0) { > + umtxq_signal(&key, 1); > + > + /* > + * If this was the last sleeping thread, clear the = waiters > + * flag in _count. > + */ > + if (cnt =3D=3D 1) { > + umtxq_unlock(&key); > + count =3D fuword32(&sem->_count); > + while (count !=3D -1 && count & = USEM_HAS_WAITERS) > + count =3D casuword32(&sem->_count, = count, > + count & ~USEM_HAS_WAITERS); > + if (count =3D=3D -1) > + error =3D EFAULT; > + umtxq_lock(&key); > + } > + } > + umtxq_unbusy(&key); > + umtxq_unlock(&key); > + umtx_key_release(&key); > + return (error); > +} >=20 > inline int > umtx_copyin_timeout(const void *addr, struct timespec *tsp) > @@ -3066,6 +3180,7 @@ __umtx_op_rw_unlock(struct thread *td, s > return do_rw_unlock(td, uap->obj); > } >=20 > +#if defined(COMPAT_FREEBSD9) || defined(COMPAT_FREEBSD10) > static int > __umtx_op_sem_wait(struct thread *td, struct _umtx_op_args *uap) > { > @@ -3090,6 +3205,7 @@ __umtx_op_sem_wake(struct thread *td, st > { > return do_sem_wake(td, uap->obj); > } > +#endif >=20 > static int > __umtx_op_wake2_umutex(struct thread *td, struct _umtx_op_args *uap) > @@ -3097,6 +3213,31 @@ __umtx_op_wake2_umutex(struct thread *td > return do_wake2_umutex(td, uap->obj, uap->val); > } >=20 > +static int > +__umtx_op_sem2_wait(struct thread *td, struct _umtx_op_args *uap) > +{ > + struct _umtx_time *tm_p, timeout; > + int error; > + > + /* Allow a null timespec (wait forever). */ > + if (uap->uaddr2 =3D=3D NULL) > + tm_p =3D NULL; > + else { > + error =3D umtx_copyin_umtx_time( > + uap->uaddr2, (size_t)uap->uaddr1, &timeout); > + if (error !=3D 0) > + return (error); > + tm_p =3D &timeout; > + } > + return (do_sem2_wait(td, uap->obj, tm_p)); > +} > + > +static int > +__umtx_op_sem2_wake(struct thread *td, struct _umtx_op_args *uap) > +{ > + return do_sem2_wake(td, uap->obj); > +} > + > typedef int (*_umtx_op_func)(struct thread *td, struct _umtx_op_args = *uap); >=20 > static _umtx_op_func op_table[] =3D { > @@ -3119,10 +3260,17 @@ static _umtx_op_func op_table[] =3D { > __umtx_op_wake_private, /* UMTX_OP_WAKE_PRIVATE */ > __umtx_op_wait_umutex, /* UMTX_OP_MUTEX_WAIT */ > __umtx_op_wake_umutex, /* UMTX_OP_MUTEX_WAKE */ > +#if defined(COMPAT_FREEBSD9) || defined(COMPAT_FREEBSD10) > __umtx_op_sem_wait, /* UMTX_OP_SEM_WAIT */ > __umtx_op_sem_wake, /* UMTX_OP_SEM_WAKE */ > +#else > + __umtx_op_unimpl, /* UMTX_OP_SEM_WAIT */ > + __umtx_op_unimpl, /* UMTX_OP_SEM_WAKE */ > +#endif > __umtx_op_nwake_private, /* UMTX_OP_NWAKE_PRIVATE */ > - __umtx_op_wake2_umutex /* UMTX_OP_MUTEX_WAKE2 */ > + __umtx_op_wake2_umutex, /* UMTX_OP_MUTEX_WAKE2 */ > + __umtx_op_sem2_wait, /* UMTX_OP_SEM2_WAIT */ > + __umtx_op_sem2_wake, /* UMTX_OP_SEM2_WAKE */ > }; >=20 > int > @@ -3320,6 +3468,7 @@ __umtx_op_wait_uint_private_compat32(str > return do_wait(td, uap->obj, uap->val, tm_p, 1, 1); > } >=20 > +#if defined(COMPAT_FREEBSD9) || defined(COMPAT_FREEBSD10) > static int > __umtx_op_sem_wait_compat32(struct thread *td, struct _umtx_op_args = *uap) > { > @@ -3338,6 +3487,26 @@ __umtx_op_sem_wait_compat32(struct threa > } > return (do_sem_wait(td, uap->obj, tm_p)); > } > +#endif > + > +static int > +__umtx_op_sem2_wait_compat32(struct thread *td, struct _umtx_op_args = *uap) > +{ > + struct _umtx_time *tm_p, timeout; > + int error; > + > + /* Allow a null timespec (wait forever). */ > + if (uap->uaddr2 =3D=3D NULL) > + tm_p =3D NULL; > + else { > + error =3D umtx_copyin_umtx_time32(uap->uaddr2, > + (size_t)uap->uaddr1, &timeout); > + if (error !=3D 0) > + return (error); > + tm_p =3D &timeout; > + } > + return (do_sem2_wait(td, uap->obj, tm_p)); > +} >=20 > static int > __umtx_op_nwake_private32(struct thread *td, struct _umtx_op_args = *uap) > @@ -3385,10 +3554,17 @@ static _umtx_op_func op_table_compat32[] > __umtx_op_wake_private, /* UMTX_OP_WAKE_PRIVATE */ > __umtx_op_wait_umutex_compat32, /* UMTX_OP_MUTEX_WAIT */ > __umtx_op_wake_umutex, /* UMTX_OP_MUTEX_WAKE */ > +#if defined(COMPAT_FREEBSD9) || defined(COMPAT_FREEBSD10) > __umtx_op_sem_wait_compat32, /* UMTX_OP_SEM_WAIT */ > __umtx_op_sem_wake, /* UMTX_OP_SEM_WAKE */ > +#else > + __umtx_op_unimpl, /* UMTX_OP_SEM_WAIT */ > + __umtx_op_unimpl, /* UMTX_OP_SEM_WAKE */ > +#endif > __umtx_op_nwake_private32, /* UMTX_OP_NWAKE_PRIVATE */ > - __umtx_op_wake2_umutex /* UMTX_OP_MUTEX_WAKE2 */ > + __umtx_op_wake2_umutex, /* UMTX_OP_MUTEX_WAKE2 */ > + __umtx_op_sem2_wait_compat32, /* UMTX_OP_SEM2_WAIT */ > + __umtx_op_sem2_wake, /* UMTX_OP_SEM2_WAKE */ > }; >=20 > int =97=20 Bjoern A. Zeeb "Come on. Learn, goddamn it.", WarGames, 1983
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?88B273DE-C9EB-4C11-AE9E-0136BC2324C2>