Skip site navigation (1)Skip section navigation (2)
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>