From: Filippo ARCIDIACONO <filippo.arcidiac...@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.arcidiac...@st.com>
Signed-off-by: Carmelo Amoroso <carmelo.amor...@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.arcidiac...@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

_______________________________________________
uClibc mailing list
uClibc@uclibc.org
http://lists.busybox.net/mailman/listinfo/uclibc

Reply via email to