svn commit: trunk/uClibc/libc: stdio sysdeps/linux/common/bits

andersen at uclibc.org andersen at uclibc.org
Wed Dec 6 22:41:22 UTC 2006


Author: andersen
Date: 2006-12-06 14:41:21 -0800 (Wed, 06 Dec 2006)
New Revision: 16793

Log:
stdio update from mjn3


Modified:
   trunk/uClibc/libc/stdio/_READ.c
   trunk/uClibc/libc/stdio/_WRITE.c
   trunk/uClibc/libc/stdio/_fopen.c
   trunk/uClibc/libc/stdio/_stdio.c
   trunk/uClibc/libc/stdio/_stdio.h
   trunk/uClibc/libc/stdio/_vfprintf.c
   trunk/uClibc/libc/stdio/fclose.c
   trunk/uClibc/libc/stdio/fcloseall.c
   trunk/uClibc/libc/stdio/fflush.c
   trunk/uClibc/libc/stdio/flockfile.c
   trunk/uClibc/libc/stdio/freopen.c
   trunk/uClibc/libc/stdio/ftello.c
   trunk/uClibc/libc/stdio/ftrylockfile.c
   trunk/uClibc/libc/stdio/funlockfile.c
   trunk/uClibc/libc/stdio/setvbuf.c
   trunk/uClibc/libc/stdio/vdprintf.c
   trunk/uClibc/libc/sysdeps/linux/common/bits/uClibc_stdio.h


Changeset:
Modified: trunk/uClibc/libc/stdio/_READ.c
===================================================================
--- trunk/uClibc/libc/stdio/_READ.c	2006-12-06 21:51:59 UTC (rev 16792)
+++ trunk/uClibc/libc/stdio/_READ.c	2006-12-06 22:41:21 UTC (rev 16793)
@@ -44,7 +44,7 @@
 #warning EINTR?
 #endif
 /* 	RETRY: */
-		if ((rv = __READ(stream, buf, bufsize)) <= 0) {
+		if ((rv = __READ(stream, (char *) buf, bufsize)) <= 0) {
 			if (rv == 0) {
 				__STDIO_STREAM_SET_EOF(stream);
 			} else {

Modified: trunk/uClibc/libc/stdio/_WRITE.c
===================================================================
--- trunk/uClibc/libc/stdio/_WRITE.c	2006-12-06 21:51:59 UTC (rev 16792)
+++ trunk/uClibc/libc/stdio/_WRITE.c	2006-12-06 22:41:21 UTC (rev 16793)
@@ -49,7 +49,7 @@
 			return bufsize;
 		}
 		stodo = (todo <= SSIZE_MAX) ? todo : SSIZE_MAX;
-		if ((rv = __WRITE(stream, buf, stodo)) >= 0) {
+		if ((rv = __WRITE(stream, (char *) buf, stodo)) >= 0) {
 #ifdef __UCLIBC_MJN3_ONLY__
 #warning TODO: Make custom stream write return check optional.
 #endif

Modified: trunk/uClibc/libc/stdio/_fopen.c
===================================================================
--- trunk/uClibc/libc/stdio/_fopen.c	2006-12-06 21:51:59 UTC (rev 16792)
+++ trunk/uClibc/libc/stdio/_fopen.c	2006-12-06 22:41:21 UTC (rev 16793)
@@ -198,11 +198,24 @@
 #endif
 
 #ifdef __STDIO_HAS_OPENLIST
-	__STDIO_THREADLOCK_OPENLIST;
-	stream->__nextopen = _stdio_openlist; /* New files are inserted at */
-	_stdio_openlist = stream;			  /*   the head of the list. */
-	__STDIO_THREADUNLOCK_OPENLIST;
+#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS)
+	if (!(stream->__modeflags & __FLAG_FREEFILE))
+	{
+		/* An freopen call so the file was never removed from the list. */
+	}
+	else
 #endif
+	{
+		/* We have to lock the del mutex in case another thread wants to fclose()
+		 * the last file. */
+		__STDIO_THREADLOCK_OPENLIST_DEL;
+		__STDIO_THREADLOCK_OPENLIST_ADD;
+		stream->__nextopen = _stdio_openlist; /* New files are inserted at */
+		_stdio_openlist = stream;			  /*   the head of the list. */
+		__STDIO_THREADUNLOCK_OPENLIST_ADD;
+		__STDIO_THREADUNLOCK_OPENLIST_DEL;
+	}
+#endif
 
 	__STDIO_STREAM_VALIDATE(stream);
 

Modified: trunk/uClibc/libc/stdio/_stdio.c
===================================================================
--- trunk/uClibc/libc/stdio/_stdio.c	2006-12-06 21:51:59 UTC (rev 16792)
+++ trunk/uClibc/libc/stdio/_stdio.c	2006-12-06 22:41:21 UTC (rev 16793)
@@ -154,8 +154,12 @@
 FILE *_stdio_openlist = _stdio_streams;
 
 # ifdef __UCLIBC_HAS_THREADS__
-pthread_mutex_t _stdio_openlist_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
-int _stdio_openlist_delflag = 0;
+pthread_mutex_t _stdio_openlist_add_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+#ifdef __STDIO_BUFFERS
+pthread_mutex_t _stdio_openlist_del_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+volatile int _stdio_openlist_use_count = 0;
+int _stdio_openlist_del_count = 0;
+#endif
 # endif
 
 #endif
@@ -187,7 +191,11 @@
 	 * locked, then I suppose there is a chance that a pointer in the
 	 * chain might be corrupt due to a partial store.
 	 */ 
-	__stdio_init_mutex(&_stdio_openlist_lock);
+	__stdio_init_mutex(&_stdio_openlist_add_lock);
+#warning check
+#ifdef __STDIO_BUFFERS
+	__stdio_init_mutex(&_stdio_openlist_del_lock);
+#endif
 
 	/* Next we need to worry about the streams themselves.  If a stream
 	 * is currently locked, then it may be in an invalid state.  So we
@@ -195,7 +203,7 @@
 	 * Then we reinitialize the locks.
 	 */
 	for (ptr = _stdio_openlist ; ptr ; ptr = ptr->__nextopen ) {
-		if (__STDIO_ALWAYS_THREADTRYLOCK(ptr)) {
+		if (__STDIO_ALWAYS_THREADTRYLOCK_CANCEL_UNSAFE(ptr)) {
 			/* The stream is already locked, so we don't want to touch it.
 			 * However, if we have custom streams, we can't just close it
 			 * or leave it locked since a custom stream may be stacked

Modified: trunk/uClibc/libc/stdio/_stdio.h
===================================================================
--- trunk/uClibc/libc/stdio/_stdio.h	2006-12-06 21:51:59 UTC (rev 16792)
+++ trunk/uClibc/libc/stdio/_stdio.h	2006-12-06 22:41:21 UTC (rev 16793)
@@ -23,22 +23,78 @@
 #ifdef __UCLIBC_HAS_THREADS__
 #include <pthread.h>
 
-#define __STDIO_THREADLOCK_OPENLIST \
-	__pthread_mutex_lock(&_stdio_openlist_lock)
+#define __STDIO_THREADLOCK_OPENLIST_ADD										\
+	do {																	\
+		struct _pthread_cleanup_buffer __infunc_pthread_cleanup_buffer;		\
+		_pthread_cleanup_push_defer(&__infunc_pthread_cleanup_buffer,		\
+									__pthread_mutex_unlock,					\
+									&_stdio_openlist_add_lock);				\
+		__pthread_mutex_lock(&_stdio_openlist_add_lock);					\
 
-#define __STDIO_THREADUNLOCK_OPENLIST \
-	__pthread_mutex_unlock(&_stdio_openlist_lock)
+#define __STDIO_THREADUNLOCK_OPENLIST_ADD									\
+		_pthread_cleanup_pop_restore(&__infunc_pthread_cleanup_buffer,1);	\
+	} while (0)
 
-#define __STDIO_THREADTRYLOCK_OPENLIST \
-	__pthread_mutex_trylock(&_stdio_openlist_lock)
 
-#else
+#ifdef __STDIO_BUFFERS
 
-#define	__STDIO_THREADLOCK_OPENLIST     ((void)0)
-#define	__STDIO_THREADUNLOCK_OPENLIST   ((void)0)
+#define __STDIO_THREADLOCK_OPENLIST_DEL										\
+	do {																	\
+		struct _pthread_cleanup_buffer __infunc_pthread_cleanup_buffer;		\
+		_pthread_cleanup_push_defer(&__infunc_pthread_cleanup_buffer,		\
+									__pthread_mutex_unlock,					\
+									&_stdio_openlist_del_lock);				\
+		__pthread_mutex_lock(&_stdio_openlist_del_lock);					\
 
+#define __STDIO_THREADUNLOCK_OPENLIST_DEL									\
+		_pthread_cleanup_pop_restore(&__infunc_pthread_cleanup_buffer,1);	\
+	} while (0)
+
+#define __STDIO_OPENLIST_INC_USE \
+do { \
+	__STDIO_THREADLOCK_OPENLIST_DEL; \
+	++_stdio_openlist_use_count; \
+	__STDIO_THREADUNLOCK_OPENLIST_DEL; \
+} while (0)
+
+extern void _stdio_openlist_dec_use(void);
+
+#define __STDIO_OPENLIST_DEC_USE \
+	_stdio_openlist_dec_use()
+
+#define __STDIO_OPENLIST_INC_DEL_CNT \
+do { \
+	__STDIO_THREADLOCK_OPENLIST_DEL; \
+	++_stdio_openlist_del_count; \
+	__STDIO_THREADUNLOCK_OPENLIST_DEL; \
+} while (0)
+
+#define __STDIO_OPENLIST_DEC_DEL_CNT \
+do { \
+	__STDIO_THREADLOCK_OPENLIST_DEL; \
+	--_stdio_openlist_del_count; \
+	__STDIO_THREADUNLOCK_OPENLIST_DEL; \
+} while (0)
+
 #endif
 
+#endif  /* __UCLIBC_HAS_THREADS__ */
+
+#ifndef __STDIO_THREADLOCK_OPENLIST_ADD
+#define	__STDIO_THREADLOCK_OPENLIST_ADD     ((void)0)
+#define	__STDIO_THREADUNLOCK_OPENLIST_ADD   ((void)0)
+#endif
+
+#ifndef __STDIO_THREADLOCK_OPENLIST_DEL
+#define	__STDIO_THREADLOCK_OPENLIST_DEL     ((void)0)
+#define	__STDIO_THREADUNLOCK_OPENLIST_DEL   ((void)0)
+/* #define __STDIO_OPENLIST_USE_CNT() (0) */
+#define __STDIO_OPENLIST_INC_USE            ((void)0)
+#define __STDIO_OPENLIST_DEC_USE            ((void)0)
+#define __STDIO_OPENLIST_INC_DEL_CNT        ((void)0)
+#define __STDIO_OPENLIST_DEC_DEL_CNT        ((void)0)
+#endif
+
 #define __UNDEFINED_OR_NONPORTABLE ((void)0)
 
 /**********************************************************************/

Modified: trunk/uClibc/libc/stdio/_vfprintf.c
===================================================================
--- trunk/uClibc/libc/stdio/_vfprintf.c	2006-12-06 21:51:59 UTC (rev 16792)
+++ trunk/uClibc/libc/stdio/_vfprintf.c	2006-12-06 22:41:21 UTC (rev 16793)
@@ -1234,7 +1234,7 @@
 		}
 		len = buflen;
 	}
-	return r + OUTNSTR(fp, (const char *) buf, len);
+	return r + OUTNSTR(fp, (const unsigned char *) buf, len);
 }
 
 #endif /* __STDIO_PRINTF_FLOAT */

Modified: trunk/uClibc/libc/stdio/fclose.c
===================================================================
--- trunk/uClibc/libc/stdio/fclose.c	2006-12-06 21:51:59 UTC (rev 16792)
+++ trunk/uClibc/libc/stdio/fclose.c	2006-12-06 22:41:21 UTC (rev 16793)
@@ -16,30 +16,36 @@
 	int rv = 0;
 	__STDIO_AUTO_THREADLOCK_VAR;
 
-	/* First, remove the file from the open file list. */
-#ifdef __STDIO_HAS_OPENLIST
-	{
-		register FILE *ptr;
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning REMINDER: dead code... but may want to simply check and not remove
+#endif
+/* #ifdef __STDIO_HAS_OPENLIST */
+/* #if !defined(__UCLIBC_HAS_THREADS__) || !defined(__STDIO_BUFFERS) */
+/* 	/\* First, remove the file from the open file list. *\/ */
+/* 	{ */
+/* 		register FILE *ptr; */
 
-		__STDIO_THREADLOCK_OPENLIST;
-		if ((ptr = _stdio_openlist) == stream) {
-			_stdio_openlist = stream->__nextopen;
-		} else {
-			while (ptr) {
-				if (ptr->__nextopen == stream) {
-					ptr->__nextopen = stream->__nextopen;
-					break;
-				}
-				ptr = ptr->__nextopen;
-			}
-		}
-		__STDIO_THREADUNLOCK_OPENLIST;
+/* 		__STDIO_THREADLOCK_OPENLIST; */
+/* 		if ((ptr = _stdio_openlist) == stream) { */
+/* #warning does a mod!!! */
+/* 			_stdio_openlist = stream->__nextopen; */
+/* 		} else { */
+/* 			while (ptr) { */
+/* 				if (ptr->__nextopen == stream) { */
+/* 					ptr->__nextopen = stream->__nextopen; */
+/* 					break; */
+/* 				} */
+/* 				ptr = ptr->__nextopen; */
+/* 			} */
+/* 		} */
+/* 		__STDIO_THREADUNLOCK_OPENLIST; */
 
-		if (!ptr) {	  /* Did not find stream in the open file list! */
-			return EOF;
-		}
-	}
-#endif
+/* 		if (!ptr) {	  /\* Did not find stream in the open file list! *\/ */
+/* 			return EOF; */
+/* 		} */
+/* 	} */
+/* #endif */
+/* #endif */
 
 	__STDIO_AUTO_THREADLOCK(stream);
 
@@ -62,6 +68,11 @@
 	 * Since a file can't be both readonly and writeonly, that makes
 	 * an effective signal.  It also has the benefit of disabling
 	 * transitions to either reading or writing. */
+#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS)
+	/* Before we mark the file as closed, make sure we increment the openlist use count
+	 * so it isn't freed under us while still cleaning up. */
+	__STDIO_OPENLIST_INC_USE;
+#endif
 	stream->__modeflags &= (__FLAG_FREEBUF|__FLAG_FREEFILE);
 	stream->__modeflags |= (__FLAG_READONLY|__FLAG_WRITEONLY);
 
@@ -84,7 +95,16 @@
 	__STDIO_AUTO_THREADUNLOCK(stream);
 
 	__STDIO_STREAM_FREE_BUFFER(stream);
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning REMINDER: inefficient - locks and unlocks twice and walks whole list
+#endif
+#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS)
+	/* inefficient - locks/unlocks twice and walks whole list */
+	__STDIO_OPENLIST_INC_DEL_CNT;
+	__STDIO_OPENLIST_DEC_USE;	/* This with free the file if necessary. */
+#else
 	__STDIO_STREAM_FREE_FILE(stream);
+#endif
 
 	return rv;
 }

Modified: trunk/uClibc/libc/stdio/fcloseall.c
===================================================================
--- trunk/uClibc/libc/stdio/fcloseall.c	2006-12-06 21:51:59 UTC (rev 16792)
+++ trunk/uClibc/libc/stdio/fcloseall.c	2006-12-06 22:41:21 UTC (rev 16793)
@@ -24,15 +24,40 @@
 #ifdef __STDIO_HAS_OPENLIST
 
 	int retval = 0;
+	FILE *f;
 
-	__STDIO_THREADLOCK_OPENLIST;
-	while (_stdio_openlist) {
-		if (fclose(_stdio_openlist)) {
-			retval = EOF;
+	__STDIO_OPENLIST_INC_USE;
+
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning REMINDER: should probably have a get_head() operation
+#endif
+	__STDIO_THREADLOCK_OPENLIST_ADD;
+	f = _stdio_openlist;
+	__STDIO_THREADUNLOCK_OPENLIST_ADD;
+
+	while (f) {
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning REMINDER: should probably have a get_next() operation
+#endif
+		FILE *n = f->__nextopen;
+		__STDIO_AUTO_THREADLOCK_VAR;
+
+		__STDIO_AUTO_THREADLOCK(f);
+		/* Only call fclose on the stream if it is not already closed. */
+		if ((f->__modeflags & (__FLAG_READONLY|__FLAG_WRITEONLY))
+		    != (__FLAG_READONLY|__FLAG_WRITEONLY)
+		    ) {
+			if (fclose(f)) {
+				retval = EOF;
+			}
 		}
+		__STDIO_AUTO_THREADUNLOCK(f);
+
+		f = n;
 	}
-	__STDIO_THREADUNLOCK_OPENLIST;
 
+	__STDIO_OPENLIST_DEC_USE;
+
 	return retval;
 
 #else

Modified: trunk/uClibc/libc/stdio/fflush.c
===================================================================
--- trunk/uClibc/libc/stdio/fflush.c	2006-12-06 21:51:59 UTC (rev 16792)
+++ trunk/uClibc/libc/stdio/fflush.c	2006-12-06 22:41:21 UTC (rev 16793)
@@ -18,21 +18,69 @@
 #ifdef __UCLIBC_HAS_THREADS__
 /* Even if the stream is set to user-locking, we still need to lock
  * when all (lbf) writing streams are flushed. */
-#define MY_STDIO_THREADLOCK(STREAM) \
+
+#define __MY_STDIO_THREADLOCK(__stream)										\
+	do {																	\
+		struct _pthread_cleanup_buffer __infunc_pthread_cleanup_buffer;		\
 	if (_stdio_user_locking != 2) { \
-		__STDIO_ALWAYS_THREADLOCK(STREAM); \
-	}
+			_pthread_cleanup_push_defer(&__infunc_pthread_cleanup_buffer,	\
+										__pthread_mutex_unlock,				\
+										&(__stream)->__lock);				\
+			__pthread_mutex_lock(&(__stream)->__lock);						\
+		}																	\
+		((void)0)
 
-#define MY_STDIO_THREADUNLOCK(STREAM) \
+#define __MY_STDIO_THREADUNLOCK(__stream)									\
 	if (_stdio_user_locking != 2) { \
-		__STDIO_ALWAYS_THREADUNLOCK(STREAM); \
-	}
+			_pthread_cleanup_pop_restore(&__infunc_pthread_cleanup_buffer,1);\
+		}																	\
+	} while (0)
+
 #else
-#define MY_STDIO_THREADLOCK(STREAM)		((void)0)
-#define MY_STDIO_THREADUNLOCK(STREAM)	((void)0)
+#define __MY_STDIO_THREADLOCK(STREAM)		((void)0)
+#define __MY_STDIO_THREADUNLOCK(STREAM)		((void)0)
 #endif
 
+#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS)
+void _stdio_openlist_dec_use(void)
+{
+	__STDIO_THREADLOCK_OPENLIST_DEL;
+	if ((_stdio_openlist_use_count == 1) && (_stdio_openlist_del_count > 0)) {
+		FILE *p = NULL;
+		FILE *n;
+		FILE *stream;
 
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning REMINDER: As an optimization, we could unlock after we move past the head.
+#endif
+		/* Grab the openlist add lock since we might change the head of the list. */
+		__STDIO_THREADLOCK_OPENLIST_ADD;
+		for (stream = _stdio_openlist; stream; stream = n) {
+			n = stream->__nextopen;
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning REMINDER: fix for nonatomic
+#endif
+			if ((stream->__modeflags & (__FLAG_READONLY|__FLAG_WRITEONLY|__FLAG_FAILED_FREOPEN))
+				== (__FLAG_READONLY|__FLAG_WRITEONLY)
+				) {		 /* The file was closed and should be removed from the list. */
+				if (!p) {
+					_stdio_openlist = n;
+				} else {
+					p->__nextopen = n;
+				}
+				__STDIO_STREAM_FREE_FILE(stream);
+			} else {
+				p = stream;
+			}
+		}
+		__STDIO_THREADUNLOCK_OPENLIST_ADD;
+		_stdio_openlist_del_count = 0; /* Should be clean now. */
+	}
+	--_stdio_openlist_use_count;
+	__STDIO_THREADUNLOCK_OPENLIST_DEL;
+}
+#endif
+
 int fflush_unlocked(register FILE *stream)
 {
 #ifdef __STDIO_BUFFERS
@@ -55,23 +103,39 @@
 	}
 
 	if (!stream) {				/* Flush all (lbf) writing streams. */
-		__STDIO_THREADLOCK_OPENLIST;
-		for (stream = _stdio_openlist; stream ; stream = stream->__nextopen) {
-			MY_STDIO_THREADLOCK(stream);
-			if (!(((stream->__modeflags | bufmask)
-				   ^ (__FLAG_WRITING|__FLAG_LBF)
-				   ) & (__FLAG_WRITING|__MASK_BUFMODE))
-				) {
-				if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) {
-					__STDIO_STREAM_DISABLE_PUTC(stream);
-					__STDIO_STREAM_CLEAR_WRITING(stream);
-				} else {
-					retval = EOF;
+
+		__STDIO_OPENLIST_INC_USE;
+
+		__STDIO_THREADLOCK_OPENLIST_ADD;
+		stream = _stdio_openlist;
+		__STDIO_THREADUNLOCK_OPENLIST_ADD;
+
+		while(stream) {
+			/* We only care about currently writing streams and do not want to
+			 * block trying to obtain mutexes on non-writing streams. */
+#warning fix for nonatomic
+#warning unnecessary check if no threads
+			if (__STDIO_STREAM_IS_WRITING(stream)) { /* ONLY IF ATOMIC!!! */
+				__MY_STDIO_THREADLOCK(stream);
+				/* Need to check again once we have the lock. */
+				if (!(((stream->__modeflags | bufmask)
+					   ^ (__FLAG_WRITING|__FLAG_LBF)
+					   ) & (__FLAG_WRITING|__MASK_BUFMODE))
+					) {
+					if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) {
+						__STDIO_STREAM_DISABLE_PUTC(stream);
+						__STDIO_STREAM_CLEAR_WRITING(stream);
+					} else {
+						retval = EOF;
+					}
 				}
+				__MY_STDIO_THREADUNLOCK(stream);
 			}
-			MY_STDIO_THREADUNLOCK(stream);
+			stream = stream->__nextopen;
 		}
-		__STDIO_THREADUNLOCK_OPENLIST;
+
+		__STDIO_OPENLIST_DEC_USE;
+
 	} else if (__STDIO_STREAM_IS_WRITING(stream)) {
 		if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) {
 			__STDIO_STREAM_DISABLE_PUTC(stream);

Modified: trunk/uClibc/libc/stdio/flockfile.c
===================================================================
--- trunk/uClibc/libc/stdio/flockfile.c	2006-12-06 21:51:59 UTC (rev 16792)
+++ trunk/uClibc/libc/stdio/flockfile.c	2006-12-06 22:41:21 UTC (rev 16793)
@@ -11,6 +11,6 @@
 {
 	__STDIO_STREAM_VALIDATE(stream);
 
-	__STDIO_ALWAYS_THREADLOCK(stream);
+	__STDIO_ALWAYS_THREADLOCK_CANCEL_UNSAFE(stream);
 }
 

Modified: trunk/uClibc/libc/stdio/freopen.c
===================================================================
--- trunk/uClibc/libc/stdio/freopen.c	2006-12-06 21:51:59 UTC (rev 16792)
+++ trunk/uClibc/libc/stdio/freopen.c	2006-12-06 22:41:21 UTC (rev 16793)
@@ -37,6 +37,8 @@
 
 	__STDIO_STREAM_VALIDATE(stream);
 
+	__STDIO_OPENLIST_INC_USE;	/* Do not remove the file from the list. */
+
 	/* First, flush and close, but don't deallocate, the stream. */
 	/* This also removes the stream for the open file list. */
 	dynmode = (stream->__modeflags & (__FLAG_FREEBUF|__FLAG_FREEFILE));
@@ -48,13 +50,26 @@
 		!= (__FLAG_READONLY|__FLAG_WRITEONLY)
 		) {
 		fclose(stream);			/* Failures are ignored. */
+		/* NOTE: fclose always does __STDIO_OPENLIST_INC_DEL_CNT.  But we don't
+		 * want to remove this FILE from the open list, even if the freopen fails.
+		 * Consider the case of a failed freopen() on stdin.  You probably still
+		 * want to be able to call freopen() again.  Similarly for other "malloc'd"
+		 * streams. */
+		__STDIO_OPENLIST_DEC_DEL_CNT;
 	}
 
 	fp = _stdio_fopen(((intptr_t) filename), mode, stream, FILEDES_ARG);
+	if (!fp) {
+		/* Don't remove stream from the open file list and (potentially) free it.
+		 * See _stdio_openlist_dec_use() in fflush.c. */
+		stream->__modeflags = __FLAG_READONLY|__FLAG_WRITEONLY|__FLAG_FAILED_FREOPEN;
+	}
 
 	/* Reset the allocation flags. */
 	stream->__modeflags |= dynmode;
 
+	__STDIO_OPENLIST_DEC_USE;
+
 	__STDIO_AUTO_THREADUNLOCK(stream);
 
 	return fp;

Modified: trunk/uClibc/libc/stdio/ftello.c
===================================================================
--- trunk/uClibc/libc/stdio/ftello.c	2006-12-06 21:51:59 UTC (rev 16792)
+++ trunk/uClibc/libc/stdio/ftello.c	2006-12-06 22:41:21 UTC (rev 16793)
@@ -39,7 +39,10 @@
 
 	__STDIO_STREAM_VALIDATE(stream);
 
-	if ((__SEEK(stream, &pos, SEEK_CUR) < 0)
+	if ((__SEEK(stream, &pos,
+				((__STDIO_STREAM_IS_WRITING(stream)
+				  && (stream->__modeflags & __FLAG_APPEND))
+				 ? SEEK_END : SEEK_CUR)) < 0)
 		|| (__stdio_adjust_position(stream, &pos) < 0)) {
 		pos = -1;
 	}

Modified: trunk/uClibc/libc/stdio/ftrylockfile.c
===================================================================
--- trunk/uClibc/libc/stdio/ftrylockfile.c	2006-12-06 21:51:59 UTC (rev 16792)
+++ trunk/uClibc/libc/stdio/ftrylockfile.c	2006-12-06 22:41:21 UTC (rev 16793)
@@ -15,5 +15,5 @@
 {
 	__STDIO_STREAM_VALIDATE(stream);
 
-	return __STDIO_ALWAYS_THREADTRYLOCK(stream);
+	return __STDIO_ALWAYS_THREADTRYLOCK_CANCEL_UNSAFE(stream);
 }

Modified: trunk/uClibc/libc/stdio/funlockfile.c
===================================================================
--- trunk/uClibc/libc/stdio/funlockfile.c	2006-12-06 21:51:59 UTC (rev 16792)
+++ trunk/uClibc/libc/stdio/funlockfile.c	2006-12-06 22:41:21 UTC (rev 16793)
@@ -11,5 +11,5 @@
 {
 	__STDIO_STREAM_VALIDATE(stream);
 
-	__STDIO_ALWAYS_THREADUNLOCK(stream);
+	__STDIO_ALWAYS_THREADUNLOCK_CANCEL_UNSAFE(stream);
 }

Modified: trunk/uClibc/libc/stdio/setvbuf.c
===================================================================
--- trunk/uClibc/libc/stdio/setvbuf.c	2006-12-06 21:51:59 UTC (rev 16792)
+++ trunk/uClibc/libc/stdio/setvbuf.c	2006-12-06 22:41:21 UTC (rev 16793)
@@ -76,8 +76,8 @@
 	}
 
 	stream->__modeflags |= alloc_flag;
-	stream->__bufstart = buf;
-	stream->__bufend = buf + size;
+	stream->__bufstart = (unsigned char *) buf;
+	stream->__bufend = (unsigned char *) buf + size;
 	__STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream);
 	__STDIO_STREAM_DISABLE_GETC(stream);
 	__STDIO_STREAM_DISABLE_PUTC(stream);

Modified: trunk/uClibc/libc/stdio/vdprintf.c
===================================================================
--- trunk/uClibc/libc/stdio/vdprintf.c	2006-12-06 21:51:59 UTC (rev 16792)
+++ trunk/uClibc/libc/stdio/vdprintf.c	2006-12-06 22:41:21 UTC (rev 16793)
@@ -22,8 +22,8 @@
 #ifdef __STDIO_BUFFERS
 	char buf[64];				/* TODO: provide _optional_ buffering? */
 
-	f.__bufend = buf + sizeof(buf);
-	f.__bufstart = buf;
+	f.__bufend = (unsigned char *) buf + sizeof(buf);
+	f.__bufstart = (unsigned char *) buf;
 	__STDIO_STREAM_DISABLE_GETC(&f);
 	__STDIO_STREAM_DISABLE_PUTC(&f);
 	__STDIO_STREAM_INIT_BUFREAD_BUFPOS(&f);

Modified: trunk/uClibc/libc/sysdeps/linux/common/bits/uClibc_stdio.h
===================================================================
--- trunk/uClibc/libc/sysdeps/linux/common/bits/uClibc_stdio.h	2006-12-06 21:51:59 UTC (rev 16792)
+++ trunk/uClibc/libc/sysdeps/linux/common/bits/uClibc_stdio.h	2006-12-06 22:41:21 UTC (rev 16793)
@@ -148,24 +148,47 @@
 #define __STDIO_AUTO_THREADLOCK_VAR			int __infunc_user_locking
 
 #define __STDIO_AUTO_THREADLOCK(__stream)								\
+	do {																	\
+		struct _pthread_cleanup_buffer __infunc_pthread_cleanup_buffer;		\
 	if ((__infunc_user_locking = (__stream)->__user_locking) == 0) {	\
+			_pthread_cleanup_push_defer(&__infunc_pthread_cleanup_buffer,	\
+										__pthread_mutex_unlock,				\
+										&(__stream)->__lock);				\
 		__pthread_mutex_lock(&(__stream)->__lock);						\
-	}
+		}																	\
+		((void)0)
 
 #define __STDIO_AUTO_THREADUNLOCK(__stream)				\
 	if (__infunc_user_locking == 0) {					\
-		__pthread_mutex_unlock(&(__stream)->__lock);		\
-	}
+			_pthread_cleanup_pop_restore(&__infunc_pthread_cleanup_buffer,1);\
+		}																	\
+	} while (0)
 
 #define __STDIO_SET_USER_LOCKING(__stream)	((__stream)->__user_locking = 1)
 
 #define __STDIO_ALWAYS_THREADLOCK(__stream)	\
+	do {																	\
+		struct _pthread_cleanup_buffer __infunc_pthread_cleanup_buffer;		\
+		_pthread_cleanup_push_defer(&__infunc_pthread_cleanup_buffer,		\
+									__pthread_mutex_unlock,					\
+									&(__stream)->__lock);					\
+		__pthread_mutex_lock(&(__stream)->__lock);							\
+		((void)0)
+
+/* #define __STDIO_ALWAYS_THREADTRYLOCK(__stream)	\ */
+/* 		__pthread_mutex_trylock(&(__stream)->__lock) */
+
+#define __STDIO_ALWAYS_THREADUNLOCK(__stream)								\
+		_pthread_cleanup_pop_restore(&__infunc_pthread_cleanup_buffer,1);	\
+	} while (0)
+
+#define __STDIO_ALWAYS_THREADLOCK_CANCEL_UNSAFE(__stream)		\
 		__pthread_mutex_lock(&(__stream)->__lock)
 
-#define __STDIO_ALWAYS_THREADTRYLOCK(__stream)	\
+#define __STDIO_ALWAYS_THREADTRYLOCK_CANCEL_UNSAFE(__stream)	\
 		__pthread_mutex_trylock(&(__stream)->__lock)
 
-#define __STDIO_ALWAYS_THREADUNLOCK(__stream) \
+#define __STDIO_ALWAYS_THREADUNLOCK_CANCEL_UNSAFE(__stream) 	\
 		__pthread_mutex_unlock(&(__stream)->__lock)
 
 #else  /* __UCLIBC_HAS_THREADS__ */
@@ -178,9 +201,13 @@
 #define __STDIO_SET_USER_LOCKING(__stream)		((void)0)
 
 #define __STDIO_ALWAYS_THREADLOCK(__stream)		((void)0)
-#define __STDIO_ALWAYS_THREADTRYLOCK(__stream)	(0)	/* Always succeed. */
+/* #define __STDIO_ALWAYS_THREADTRYLOCK(__stream)	(0)	/\* Always succeed. *\/ */
 #define __STDIO_ALWAYS_THREADUNLOCK(__stream)	((void)0)
 
+#define __STDIO_ALWAYS_THREADLOCK_CANCEL_UNSAFE(__stream)		((void)0)
+#define __STDIO_ALWAYS_THREADTRYLOCK_CANCEL_UNSAFE(__stream)	(0)	/* Ok? */
+#define __STDIO_ALWAYS_THREADUNLOCK_CANCEL_UNSAFE(__stream)		((void)0)
+
 #endif /* __UCLIBC_HAS_THREADS__ */
 /**********************************************************************/
 
@@ -343,6 +370,7 @@
 #define __FLAG_FREEFILE		0x2000U
 #define __FLAG_FREEBUF		0x4000U
 #define __FLAG_LARGEFILE    0x8000U /* fixed! == 0_LARGEFILE for linux */
+#define __FLAG_FAILED_FREOPEN    __FLAG_LARGEFILE
 
 /* Note: In no-buffer mode, it would be possible to pack the necessary
  * flags into one byte.  Since we wouldn't be buffering and there would
@@ -371,8 +399,12 @@
 extern struct __STDIO_FILE_STRUCT *_stdio_openlist;
 
 #ifdef __UCLIBC_HAS_THREADS__
-extern pthread_mutex_t _stdio_openlist_lock;
-extern int _stdio_openlist_delflag;
+extern pthread_mutex_t _stdio_openlist_add_lock;
+#ifdef __STDIO_BUFFERS
+extern pthread_mutex_t _stdio_openlist_del_lock;
+extern volatile int _stdio_openlist_use_count; /* _stdio_openlist_del_lock */
+extern int _stdio_openlist_del_count; /* _stdio_openlist_del_lock */
+#endif
 extern int _stdio_user_locking;
 /* #ifdef _LIBC */
 extern void __stdio_init_mutex(pthread_mutex_t *m) attribute_hidden;




More information about the uClibc-cvs mailing list