[PATCH] libc: make I/O locking cancel-safe with futexes

Filippo ARCIDIACONO filippo.arcidiacono at st.com
Fri Sep 28 05:45:12 UTC 2012


Could someone take a look?
Further details could be found at
https://bugzilla.stlinux.com/show_bug.cgi?id=21083
there is also a test case spotting the issue.

> -----Original Message-----
> From: Carmelo AMOROSO [mailto:carmelo.amoroso at st.com]
> Sent: Wednesday, September 12, 2012 4:55 PM
> To: uclibc at uclibc.org
> Cc: Filippo ARCIDIACONO; Carmelo Amoroso
> Subject: [PATCH] libc: make I/O locking cancel-safe with futexes
> 
> From: Filippo ARCIDIACONO <filippo.arcidiacono at st.com>
> 
> Current implementation of I/O locking macros using futexes are not
> cancel safe, as if a thread is cancelled while doing IO operations,
> it does not release the lock on the IO stream. So following
> attempts to acquire the IO stream's lock would dead-lock.
> In order to make it cancel-safe, it needs to rely upon the
> pthread_cleanup push & pop protocol, as it is already done for
> the pthread_mutex counterpart.
> 
> Signed-off-by: Filippo Arcidiacono <filippo.arcidiacono at st.com>
> Signed-off-by: Carmelo Amoroso <carmelo.amoroso at st.com>
> ---
>  libc/stdio/Makefile.in                            |    3 ++
>  libc/stdio/io_lock_unlock.c                       |   16 ++++++++++++++
>  libc/sysdeps/linux/common/bits/uClibc_mutex.h     |   23 +++++++++++++---
> ----
>  libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h |    2 +
>  4 files changed, 36 insertions(+), 8 deletions(-)
>  create mode 100644 libc/stdio/io_lock_unlock.c
> 
> diff --git a/libc/stdio/Makefile.in b/libc/stdio/Makefile.in
> index ff77bcb..4652036 100644
> --- a/libc/stdio/Makefile.in
> +++ b/libc/stdio/Makefile.in
> @@ -52,6 +52,9 @@ endif
> 
>  # pthread functions
>  CSRC += flockfile.c ftrylockfile.c funlockfile.c
> +ifeq ($(UCLIBC_HAS_STDIO_FUTEXES),y)
> +CSRC += io_lock_unlock.c
> +endif
> 
>  # Functions with unlocked versions
>  CUSRC := \
> diff --git a/libc/stdio/io_lock_unlock.c b/libc/stdio/io_lock_unlock.c
> new file mode 100644
> index 0000000..b414264
> --- /dev/null
> +++ b/libc/stdio/io_lock_unlock.c
> @@ -0,0 +1,16 @@
> +/*
> + * Copyright (C) 2012 STMicroelectronics, Ltd
> + *
> + * Author(s): Filippo Arcidiacono  <filippo.arcidiacono at st.com>
> + *
> + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball
> + */
> +
> +#include <bits/stdio-lock.h>
> +
> +/* Function wrapper needed for I/O locking macros. */
> +
> +void IO_lock_unlock (_IO_lock_t *lock)
> +{
> +  _IO_lock_unlock (*lock);
> +}
> diff --git a/libc/sysdeps/linux/common/bits/uClibc_mutex.h
> b/libc/sysdeps/linux/common/bits/uClibc_mutex.h
> index 94597e8..c2a1cc1 100644
> --- a/libc/sysdeps/linux/common/bits/uClibc_mutex.h
> +++ b/libc/sysdeps/linux/common/bits/uClibc_mutex.h
> @@ -12,6 +12,7 @@
> 
>  #ifdef __UCLIBC_HAS_THREADS__
> 
> +
>  #include <pthread.h>
>  #ifdef _LIBC
>  #include <bits/uClibc_pthread.h>
> @@ -79,15 +80,21 @@
>  #define __UCLIBC_IO_MUTEX_INIT(M) 	_IO_lock_t M =
> _IO_lock_initializer
>  #define __UCLIBC_IO_MUTEX_EXTERN(M)		extern _IO_lock_t M
> 
> -#define __UCLIBC_IO_MUTEX_CONDITIONAL_LOCK(M,C)		\
> -	if (C) {
> 		\
> -		_IO_lock_lock(M);
> 		\
> -	}
> +#define __UCLIBC_IO_MUTEX_CONDITIONAL_LOCK(M,C)
> 				\
> +	do {
> 		\
> +		struct _pthread_cleanup_buffer
> __infunc_pthread_cleanup_buffer;		\
> +		int __infunc_need_locking = (C);
> 		\
> +		if (__infunc_need_locking) {
> 		\
> +
> 	_pthread_cleanup_push_defer(&__infunc_pthread_cleanup_buffer
> ,	\
> +						    (void (*) (void
> *))IO_lock_unlock,	\
> +						    &(M));
> 		\
> +			_IO_lock_lock((M));
> 		\
> +		}
> 		\
> +		((void)0)
> +
> 
> -#define __UCLIBC_IO_MUTEX_CONDITIONAL_UNLOCK(M,C)	\
> -	if (C) {
> 		\
> -		_IO_lock_unlock(M);
> 		\
> -	}
> +#define __UCLIBC_IO_MUTEX_CONDITIONAL_UNLOCK(M,C)
> 	\
> +		__UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M,C)
> 
>  #define __UCLIBC_IO_MUTEX_AUTO_LOCK(M,A,V)			\
>  		__UCLIBC_IO_MUTEX_CONDITIONAL_LOCK(M,((A=(V))) ==
> 0)
> diff --git a/libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h
> b/libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h
> index 3437e61..c742644 100644
> --- a/libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h
> +++ b/libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h
> @@ -29,6 +29,8 @@
> 
>  typedef struct { int lock; int cnt; void *owner; } _IO_lock_t;
> 
> +void IO_lock_unlock (_IO_lock_t *lock);
> +
>  #define _IO_lock_initializer { LLL_LOCK_INITIALIZER, 0, NULL }
> 
>  #define _IO_lock_init(_name) \
> --
> 1.7.4.4




More information about the uClibc mailing list