Bug 28747 - Empty write STREAM I/O file positioning problem
Summary: Empty write STREAM I/O file positioning problem
Status: RESOLVED DUPLICATE of bug 29053
Alias: None
Product: gcc
Classification: Unclassified
Component: libfortran (show other bugs)
Version: 4.2.0
: P3 normal
Target Milestone: 4.2.0
Assignee: Not yet assigned to anyone
Depends on:
Blocks: F2003
  Show dependency treegraph
Reported: 2006-08-16 03:11 UTC by Jerry DeLisle
Modified: 2006-09-15 13:35 UTC (History)
1 user (show)

See Also:
Host: x86_64-unknown-freebsd7.0
Target: x86_64-unknown-freebsd7.0
Known to work:
Known to fail:
Last reconfirmed: 2006-08-20 04:25:42

assembly output for reduced case (914 bytes, text/plain)
2006-08-18 16:08 UTC, Jerry DeLisle

Note You need to log in before you can comment on or make changes to this bug.
Description Jerry DeLisle 2006-08-16 03:11:55 UTC
The following does not work with bleeding edge FreeBSD:

program streamtest
  implicit none
  character(1)   :: lf = char(10)
  character(1)   :: tchar
  integer        :: i,j,k
  real(kind=4), dimension(100,100) :: anarray
  open(10, file="teststream", access="stream", form="unformatted")
  anarray = 3.14159
  write(10) anarray
  anarray = 0.0
  write(10, pos=1) ! This should position for the following read
  read(10) anarray
  anarray = abs(anarray - 3.14159)
  if (any(anarray.gt.0.00001)) call abort()
end program streamtest
Comment 1 Jerry DeLisle 2006-08-18 16:08:22 UTC
Created attachment 12093 [details]
assembly output for reduced case

There is wrong code generated setting up the parameters for the second call to write.  The pointers are off by 400.  You can see this by comparing the instructions just before the first call too _gfortran_st_write vs the instructions leading up to the second _gfortran_st_write.

-fdump-tree-original looks OK.  Inserting a flush right after the first call to write in the test case and the problem goes away.

Middle-end or backend problem?
Comment 2 Jerry DeLisle 2006-08-18 16:12:26 UTC
Simplified test case used in discussion above.

program streamtest
  implicit none
  real, dimension(2,3) :: anarray
  open(10, file="teststream", access="stream", form="unformatted")
  anarray = 3.14159
  write(10) anarray
  write(10, pos=1) ! This is a way to position an unformatted file
  anarray = 0.0
  read(10) anarray
end program streamtest

Additional info:

Using built-in specs.
Target: x86_64-unknown-freebsd7.0
Configured with: ../gcc4x/configure --prefix=/home/sgk/work/4x --enable-languages=c,fortran
Thread model: posix
gcc version 4.2.0 20060816 (experimental)

Comment 3 Andrew Pinski 2006-08-18 16:15:20 UTC
(In reply to comment #1)
> Middle-end or backend problem?
Can you look at the dump that is produced by -fdump-tree-final_cleanup
and see if it is correct?
Comment 4 Jerry DeLisle 2006-08-18 16:29:53 UTC
Using -fdump-tree-final_cleanup all looks OK.
Comment 5 Jerry DeLisle 2006-08-18 20:54:26 UTC
Here is a debug trace showing the steps leading up to the mutation of the dtp pointer.  StevebB on IRC indicated that the assembly output on linux x86-64 natch the freebsd version I posted here and the problem does not occur on that platform.  Notice the before an after values of the dtp pointer!

(gdb) s
*_gfortran_st_write_done (dtp=0x7fffffffe640)
    at ../../../gcc4x/libgfortran/io/transfer.c:2546
2546      if (dtp->u.p.scratch != NULL)
(gdb) s
2548      if (dtp->u.p.current_unit != NULL)
(gdb) s
2549        unlock_unit (dtp->u.p.current_unit);
(gdb) s
*_gfortrani_unlock_unit (u=0x2008103b0) at gthr-posix.h:566
566       if (__gthread_active_p ())
(gdb) p dtp
No symbol "dtp" in current context.
(gdb) p u
$5 = (gfc_unit *) 0x2008103b0
(gdb) p *u
$6 = {unit_number = 10, s = 0x200828000, left = 0x0, right = 0x0,
  priority = 14047, read_bad = 1, current_record = 1, endfile = NO_ENDFILE,
  mode = WRITING, flags = {access = ACCESS_STREAM, action = ACTION_READWRITE,
    blank = BLANK_NULL, delim = DELIM_NONE, form = FORM_UNFORMATTED,
    is_notpadded = 0, position = POSITION_ASIS, status = STATUS_UNKNOWN,
    pad = PAD_YES, convert = CONVERT_NATIVE}, recl = 1, last_record = 25,
  maxrec = 9223372036854775807, bytes_left = 0, lock = 0x0, waiting = 0,
  closed = 0, ls = 0x0, rank = 0, file_len = 10,
  file = 0x20082c140 "teststream"}
(gdb) s
567         return __gthrw_(pthread_mutex_unlock) (mutex);
(gdb) s

Breakpoint 1, *_gfortran_st_write (dtp=0x7fffffffe7d0)
    at ../../../gcc4x/libgfortran/io/transfer.c:2506
2506    {
Comment 6 Jerry DeLisle 2006-08-19 03:29:26 UTC
Here is a comparison of no optimization and with -O1.  Does this code look the same on x86-64 that is not FreeBSD?

Code with no optimization: This does not work.

	call	_gfortran_st_write_done
	movq	$.LC0, -424(%rbp)
	movl	$8, -416(%rbp)
	movl	$10, -428(%rbp)
	movq	$1, -392(%rbp)
	movl	$512, -432(%rbp)
	leaq	-432(%rbp), %rdi
	call	_gfortran_st_write

Code with -O1: This works

        call    _gfortran_st_write_done
        movq    $.LC0, 8(%rsp)
        movl    $8, 16(%rsp)
        movl    $10, 4(%rsp)
        movq    $1, 40(%rsp)
        movl    $512, (%rsp)
        movq    %rsp, %rdi
        call    _gfortran_st_write
Comment 7 Jack Howarth 2006-08-19 15:55:05 UTC
    On Fedora Core 5 x86_64 with the svn pull from  a few days back and last stream patch
I get the follow diff between the code generated with -O0 and -O1...

        call    _gfortran_st_write_done
-       movq    $.LC0, -600(%rbp)
-       movl    $8, -592(%rbp)
-       movl    $10, -604(%rbp)
-       movq    $1, -568(%rbp)
-       movl    $512, -608(%rbp)
-       leaq    -608(%rbp), %rdi
+       movq    $.LC0, 8(%rsp)
+       movl    $8, 16(%rsp)
+       movl    $10, 4(%rsp)
+       movq    $1, 40(%rsp)
+       movl    $512, (%rsp)
+       movq    %rsp, %rdi
        call    _gfortran_st_write

In both cases the reduced test case runs fine.
Comment 8 Jerry DeLisle 2006-08-19 16:52:24 UTC
I think this confirms the problem is in __gthrw_(pthread_mutex_unlock) (mutex) on FreeBSD.
Comment 9 Jerry DeLisle 2006-09-15 13:35:25 UTC
Fixed on 4.2, will not go to 4.1

*** This bug has been marked as a duplicate of 29053 ***