This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Buglet in fseek?


Corinna Vinschen wrote:
On Feb 20 11:44, Jeff Johnston wrote:

Regarding your other note, we could make my initial solution simpler. fflush() on a read-only stream sets the _SNPT flag on and fseek() clears it appropriately after doing the lseek. This solves the problem and doesn't care about what is done in-between. If you fflush() a read-only stream, then the next fseek()/rewind() you do will be unoptimized. I think that is fair.


Yep, that sounds good to me.


Thanks, Corinna


Alright, I have checked in the attached patch. I debugged the two scenarios to verify it was optimizing without the flush and not optimizing with the flush.


-- Jeff J.


Index: ChangeLog
===================================================================
RCS file: /cvs/src/src/newlib/ChangeLog,v
retrieving revision 1.872
diff -u -p -r1.872 ChangeLog
--- ChangeLog	16 Feb 2006 21:25:44 -0000	1.872
+++ ChangeLog	20 Feb 2006 23:23:10 -0000
@@ -1,3 +1,10 @@
+2006-02-20  Jeff Johnston  <jjohnstn@redhat.com>
+
+	* libc/stdio/fflush.c (fflush): For an fflush on a read-only
+	stream, turn off fseek/rewind optimization as per POSIX/SUSv3.
+	* libc/stdio/fseek.c (_fseek_r): After a successful unoptimized
+	seek, turn off the __SNPT no-optimization flag.
+
 2006-02-16  Jeff Johnston  <jjohnstn@redhat.com>
 
 	* libc/sys/linux/aio.c: Define _GNU_SOURCE so struct aioinit
Index: libc/stdio/fflush.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/fflush.c,v
retrieving revision 1.5
diff -u -p -r1.5 fflush.c
--- libc/stdio/fflush.c	8 Feb 2005 01:33:16 -0000	1.5
+++ libc/stdio/fflush.c	20 Feb 2006 23:23:10 -0000
@@ -72,8 +72,18 @@ _DEFUN(fflush, (fp),
   _flockfile (fp);
 
   t = fp->_flags;
-  if ((t & __SWR) == 0 || (p = fp->_bf._base) == NULL)
+  if ((t & __SWR) == 0)
     {
+      /* For a read stream, an fflush causes the next seek to be
+         unoptimized (i.e. forces a system-level seek).  This conforms
+         to the POSIX and SUSv3 standards.  */
+      fp->_flags |= __SNPT;
+      _funlockfile (fp);
+      return 0;
+    }
+  if ((p = fp->_bf._base) == NULL)
+    {
+      /* Nothing to flush.  */
       _funlockfile (fp);
       return 0;
     }
Index: libc/stdio/fseek.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/fseek.c,v
retrieving revision 1.11
diff -u -p -r1.11 fseek.c
--- libc/stdio/fseek.c	8 Feb 2005 01:33:16 -0000	1.11
+++ libc/stdio/fseek.c	20 Feb 2006 23:23:10 -0000
@@ -359,6 +359,13 @@ dumb:
   fp->_r = 0;
   /* fp->_w = 0; *//* unnecessary (I think...) */
   fp->_flags &= ~__SEOF;
+  /* Reset no-optimization flag after successful seek.  The
+     no-optimization flag may be set in the case of a read
+     stream that is flushed which by POSIX/SUSv3 standards,
+     means that a corresponding seek must not optimize.  The
+     optimization is then allowed if no subsequent flush
+     is performed.  */
+  fp->_flags &= ~__SNPT;
   _funlockfile (fp);
   return 0;
 }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]