Bug 25829 - [F03] Asynchronous IO support
Summary: [F03] Asynchronous IO support
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.2.0
: P3 enhancement
Target Milestone: ---
Assignee: Nicolas Koenig
URL:
Keywords:
Depends on: 25561 34705 35339 87048
Blocks: F2003
  Show dependency treegraph
 
Reported: 2006-01-17 21:53 UTC by Janne Blomqvist
Modified: 2018-09-19 16:36 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2008-02-17 01:19:36


Attachments
Early patch (4.29 KB, patch)
2017-10-28 17:28 UTC, Nicolas Koenig
Details | Diff
Proof of concept for transfer of a single integer (4.61 KB, patch)
2018-04-08 14:04 UTC, Nicolas Koenig
Details | Diff
Concept patch (works with read and simple wait for integers) (4.81 KB, patch)
2018-04-28 12:07 UTC, Nicolas Koenig
Details | Diff
Next version of patch (7.25 KB, patch)
2018-05-09 22:43 UTC, Nicolas Koenig
Details | Diff
Next version of patch. (8.77 KB, patch)
2018-05-20 18:48 UTC, Nicolas Koenig
Details | Diff
objdump of OK ELF file (754.67 KB, application/x-xz)
2018-08-06 11:23 UTC, Christophe Lyon
Details
objdump of KO ELF file (766.28 KB, application/x-xz)
2018-08-06 11:23 UTC, Christophe Lyon
Details
execution trace of OK ELF file (34.22 KB, application/x-xz)
2018-08-06 11:24 UTC, Christophe Lyon
Details
execution trace of KO ELF file (34.84 KB, application/x-xz)
2018-08-06 11:25 UTC, Christophe Lyon
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Janne Blomqvist 2006-01-17 21:53:56 UTC
F2003 supports the ASYNCHRONOUS='YES' specifier in some IO statements, as well as the WAIT io-unit statement.
Comment 1 Andrew Pinski 2006-01-17 23:33:35 UTC
Confirmed.
Comment 2 Jerry DeLisle 2008-02-17 01:19:36 UTC
I will be working pn this and have a strat in my local experimental branch
Comment 3 Jerry DeLisle 2008-02-17 05:02:02 UTC
Keep this PR in mind while doing this. PR34705
Comment 4 Jerry DeLisle 2008-02-23 16:48:30 UTC
Status: local experimental trunk

Front-end has most if not all keywords compiling.

DECIMAL= is working all the way through to runtime.

WAIT compiles and executes a stub in the runtime with a new st_parameter_wait structure to pass parameters from the front end to the library.  The stub is _gfortran_st_wait.
Comment 5 Jerry DeLisle 2008-04-05 22:18:49 UTC
Subject: Bug 25829

Author: jvdelisle
Date: Sat Apr  5 22:18:03 2008
New Revision: 133943

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=133943
Log:
2008-04-05  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR fortran/25829 28655
	* gfortran.map: Add new symbol, _gfortran_st_wait.
	* libgfortran.h (st_paramter_common): Add new I/O parameters.
	* open.c (st_option decimal_opt[], st_option encoding_opt[],
	st_option round_opt[], st_option sign_opt[], st_option async_opt[]): New
	parameter option arrays. (edit_modes): Add checks for new parameters.
	(new_unit): Likewise. (st_open): Likewise.
	* list_read.c (CASE_SEPERATORS): Add ';' as a valid separator.
	(eat_separator): Handle deimal comma. (read_logical): Fix whitespace.
	(parse_real): Handle decimal comma. (read_real): Handle decimal comma.
	* read.c (read_a): Use decimal status flag to allow comma in place of a
	decimal point. (read_f): Allow comma as acceptable character in float.
	According to decimal flag, substitute a period for a comma.
	(read_x): If decimal status flag is comma, disable the read_comma flag,
	not allowing comma as a delimiter, an extension otherwise.
	* io.h: (unit_decimal, unit_encoding, unit_round, unit_sign,
	unit_async): New enumerators. Add all new I/O parameters.
	* unix.c (unix_stream, int_stream): Add io_mode	asychronous I/O	control.
	(move_pos_offset, fd_alloc_w_at): Fix some whitespace.
	(fd_sfree): Use new enumerator. (fd_read): Likewise.
	(fd_write): Likewise. (fd_close): Fix whitespace.
	(fd_open): Use new enumertors. (tempfile, regular_file,
	open_external): Fix whitespace. (output_stream, error_stream): Set
	method. (stream_offset): Fix whitespace.
	* transfer.c: (st_option decimal_opt[], sign_opt[], blank_opt[]): New
	option arrays. 	(formatted_transfer_scalar): Set sf_read_comma flag
	based on new decimal_status flag. (data_transfer_init): Initialize new
	parameters. Add checks for decimal, sign, and blank. (st_wait): New stub.
	* format.c: (format_lex): Add format specifiers DP, DC, and D.
	(parse_format_list): Parse the new specifiers.
	* write.c (write_decimal): Use new sign enumerators to set the sign.
	(write_complex): Handle decimal comma and semi-colon separator.
	(nml_write_obj): Likewise.
	* write_float.def: Revise sign enumerators. (calculate_sign): Use new
	sign enumerators. (output_float): Likewise. Use new decimal_status flag
	to set the decimal character to a point or a comma.

Modified:
    trunk/libgfortran/ChangeLog
    trunk/libgfortran/gfortran.map
    trunk/libgfortran/io/format.c
    trunk/libgfortran/io/io.h
    trunk/libgfortran/io/list_read.c
    trunk/libgfortran/io/open.c
    trunk/libgfortran/io/read.c
    trunk/libgfortran/io/transfer.c
    trunk/libgfortran/io/unit.c
    trunk/libgfortran/io/unix.c
    trunk/libgfortran/io/write.c
    trunk/libgfortran/io/write_float.def
    trunk/libgfortran/libgfortran.h

Comment 6 Jerry DeLisle 2008-04-05 22:24:10 UTC
Subject: Bug 25829

Author: jvdelisle
Date: Sat Apr  5 22:23:27 2008
New Revision: 133944

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=133944
Log:
2008-04-05  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
	    Francois-Xavier Coudert  <fxcoudert@gcc.gnu.org>

	PR fortran/25829 28655
	* dump-parse-tree.c (gfc_show_code_node): Show new I/O parameters.
	* gfortran.h (gfc_statement): Add ST_WAIT enumerator.
	(gfc_open): Add pointers for decimal, encoding, round, sign,
	asynchronous. (gfc_inquire): Add pointers for asynchronous, decimal,
	encoding, pending, round, sign, size, id.
	(gfc_wait): New typedef struct. (gfc_dt): Add pointers for id, pos,
	asynchronous, blank, decimal, delim, pad, round, sign.
	(gfc_exec_op): Add EXEC_WAIT enumerator. (gfc_code): Add pointer for
	wait. (gfc_free_wait), (gfc_resolve_wait): New function prototypes.
	* trans-stmt.h (gfc_trans_wait): New function prototype.
	* trans.c (gfc_trans_code): Add case for EXEC_WAIT.
	* io.c (io_tag): Add new tags for DECIMAL, ENCODING, ROUND, SIGN,
	ASYCHRONOUS, ID. (match_open_element): Add matchers for new tags.
	(gfc_free_open): Free new pointers. (gfc_resolve_open): Resolve new
	tags. (gfc_resolve_open): Remove comment around check for allowed
	values and ASYNCHRONOUS, update it.  Likewise for DECIMAL, ENCODING,
	ROUND, and SIGN. (match_dt_element): Add matching for new tags.
	(gfc_free_wait): New function. (gfc_resolve_wait): New function.
	(match_wait_element): New function. (gfc_match_wait): New function.
	* resolve.c (gfc_resolve_blocks): Add case for EXEC_WAIT.
	(resolve_code): Add case for EXEC_WAIT. 
	* st.c (gfc_free_statement): Add case for EXEC_WAIT.
	* trans-io.c (ioparam_type): Add IOPARM_ptype_wait. (gfc_st_parameter):
	Add "wait" entry. (iocall): Add IOCALL_WAIT enumerator.
	(gfc_build_io_library_fndecls): Add function declaration for st_wait.
	(gfc_trans_open): Add mask bits for new I/O tags.
	(gfc_trans_inquire): Add mask bits for new I/O tags.
	(gfc_trans_wait): New translation function.
	(build_dt): Add mask bits for new I/O tags.
	* match.c (gfc_match_if) Add matcher for "wait".
	* match.h (gfc_match_wait): Prototype for new function.
	* ioparm.def: Add new I/O parameter definitions.
	* parse.c (decode_statement): Add match for "wait" statement.
	(next_statement): Add case for ST_WAIT. (gfc_ascii_statement): Same.

Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/dump-parse-tree.c
    trunk/gcc/fortran/gfortran.h
    trunk/gcc/fortran/io.c
    trunk/gcc/fortran/ioparm.def
    trunk/gcc/fortran/match.c
    trunk/gcc/fortran/match.h
    trunk/gcc/fortran/parse.c
    trunk/gcc/fortran/resolve.c
    trunk/gcc/fortran/st.c
    trunk/gcc/fortran/trans-io.c
    trunk/gcc/fortran/trans-stmt.h
    trunk/gcc/fortran/trans.c

Comment 7 Jerry DeLisle 2008-04-05 22:34:08 UTC
Subject: Bug 25829

Author: jvdelisle
Date: Sat Apr  5 22:33:14 2008
New Revision: 133945

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=133945
Log:
2008-04-05  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR fortran/25829 28655
	* gfortran.dg/f2003_io_1.f03: New test.
	* gfortran.dg/f2003_io_2.f03: New test.
	* gfortran.dg/f2003_io_3.f03: New test.
	* gfortran.dg/f2003_io_4.f03: New test.
	* gfortran.dg/f2003_io_5.f03: New test.
	* gfortran.dg/f2003_io_6.f03: New test.
	* gfortran.dg/f2003_io_7.f03: New test.

Added:
    trunk/gcc/testsuite/gfortran.dg/f2003_io_1.f03
    trunk/gcc/testsuite/gfortran.dg/f2003_io_2.f03
    trunk/gcc/testsuite/gfortran.dg/f2003_io_3.f03
    trunk/gcc/testsuite/gfortran.dg/f2003_io_4.f03
    trunk/gcc/testsuite/gfortran.dg/f2003_io_5.f03
    trunk/gcc/testsuite/gfortran.dg/f2003_io_6.f03
    trunk/gcc/testsuite/gfortran.dg/f2003_io_7.f03
Modified:
    trunk/gcc/testsuite/ChangeLog

Comment 8 Jerry DeLisle 2008-04-07 22:06:37 UTC
Subject: Bug 25829

Author: jvdelisle
Date: Mon Apr  7 22:05:52 2008
New Revision: 133988

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=133988
Log:
2008-04-07  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR fortran/25829 28655
	* io/open.c (edit_modes): Set flags.async. (new_unit) Set flags.async
	and flags.status. (st_open): Initialize flags.async.
	* io/list_read.c (read_charactor): Use delim_status instead of
	flags.delim.
	* io/read.c (read_x): Use pad_status instead of flags.pad.
	* io/inquire.c (inquire_via_unit): Add new checks.
	(inquire_via_filename): Likewise.
	* io/io.h (st_parameter_inquire): Add new flags.
	(st_parameter_dt): Likewise.
	* io/unit.c (get_internal_unit): Set flags.async. (init_units): Set
	flags.async.
	* io/transfer.c: Add delim and pad option arrays. (read_sf): Use
	pad_status instead of flags.pad. (read_block): Likewise.
	(data_transfer_init): Set flags.async and add checks.
	* io/write.c (write_character): Use delim_status.
	(list_formatted_write_scalar): Likewise. (nml_write_obj): Likewise.
	(namelist_write): Likewise.

Modified:
    trunk/libgfortran/ChangeLog
    trunk/libgfortran/io/inquire.c
    trunk/libgfortran/io/io.h
    trunk/libgfortran/io/list_read.c
    trunk/libgfortran/io/open.c
    trunk/libgfortran/io/read.c
    trunk/libgfortran/io/transfer.c
    trunk/libgfortran/io/unit.c
    trunk/libgfortran/io/write.c

Comment 9 Jerry DeLisle 2008-04-07 22:08:31 UTC
Subject: Bug 25829

Author: jvdelisle
Date: Mon Apr  7 22:07:44 2008
New Revision: 133989

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=133989
Log:
2008-04-07  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR fortran/25829 28655
	* io.c (io_tag): Add new tags for decimal, encoding, asynchronous,
	round, sign, and id. (match_open_element): Match new tags.
	(gfc_resolve_open): Resolve new tags. (gfc_match_open): Enable encoding
	for DEFAULT only. Update error messages. (match_dt_element): Fix match
	tag for asynchronous. Update error messages. (gfc_free_inquire): Free
	new expressions. (match_inquire_element): Match new tags.
	(gfc_match_inquire): Add constraint for ID and PENDING.
	(gfc_resolve_inquire): Resolve new tags.
	* trans-io.c (gfc_trans_inquire): Clean up whitespace and fix setting of
	mask for ID parameter.
	* ioparm.def: Fix order of parameters for pending, round, and sign.
	NOTE: These must line up with the definitions in libgfortran/io/io.h. or
	things don't work.

Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/io.c
    trunk/gcc/fortran/ioparm.def
    trunk/gcc/fortran/trans-io.c

Comment 10 Jerry DeLisle 2008-04-07 22:11:26 UTC
Subject: Bug 25829

Author: jvdelisle
Date: Mon Apr  7 22:10:41 2008
New Revision: 133991

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=133991
Log:
2008-04-07  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR fortran/25829 28655
	* gfortran.dg/write_check2.f90: Update dg-error.
	* gfortran.dg/io_constraints_1.f90: Udate dg-error.

Modified:
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gfortran.dg/io_constraints_1.f90
    trunk/gcc/testsuite/gfortran.dg/write_check2.f90

Comment 11 Daniel Franke 2009-04-10 21:23:03 UTC
Jerry, is this complete? If not, could you please summarize what's left?
Thanks.
Comment 12 Jerry DeLisle 2009-04-11 15:26:30 UTC
gfortran currently accepts asynchronous I/O syntax. The F2003 standard permits the implementation to actually do synchronous I/O.  gfortran run time library does not actually perform I/O asynchronously, but does so synchronously.

To implement this we need to develop the underlying scheme with the unit and DTP structures, develop config magic to identify targets that actually have support for asynchronous I/O, write the code that keeps track of the I/O calls, there status and completion, and address the threading concerns.
Comment 13 Janne Blomqvist 2009-10-28 22:03:37 UTC
Reassigning to myself, I have a plan how to proceed with supporting proper async I/O in the library.
Comment 14 Tobias Burnus 2009-12-11 22:28:03 UTC
Test case:
  http://users.erols.com/dnagle/pub/async_io.f03

Works with ifort, fails with gfortran. I think it needs real asynchronous I/O to work. Additionally, gfortran does not yet support the ASYNCHRONOUS attribute.
Comment 15 Tobias Burnus 2009-12-11 22:28:55 UTC
(In reply to comment #14)
> Test case:
>   http://users.erols.com/dnagle/pub/async_io.f03
which additionally needs the file/module:
  http://users.erols.com/dnagle/pub/f03def.f90
Comment 16 Tobias Burnus 2010-01-08 10:11:18 UTC
For completeness: I just committed support for the ASYNCHRONOUS attribute:
  http://gcc.gnu.org/ml/fortran/2010-01/msg00049.html
  http://gcc.gnu.org/ml/gcc-cvs/2010-01/msg00192.html
which is treated as no op.

One needs to think carefully whether one needs to take care of ASYNCHRONOUS for the middle end when real async I/O is implemented. For a simple:
  write(9, ..., asynchronous='yes') foo
  ...
  write(9, ...) ! force WAIT on unit 9
  foo = 8
presumably not using "&foo" in the first write call lets the address escape thus unless a function is known (to the ME) to not touch "foo" (indirectly), no problem should occur. But how about:

  ! Note: using "foo" in AIO implies the ASYNCHRONOUS attribute for foo
  write(9, ..., asynchronous='yes', id=waitid) foo
  call finish(foo, waitid)
contains
  subroutine finish(var, wait)
    asynchronous :: var
    wait(wait)
    var = 7
  end subroutine finish

Here, the ME might be tempted to change the order of WAIT and "var = 7"; thus in this case we probably need to tell the ME about the ASYNCHRONOUS attribute.
Comment 17 Tobias Burnus 2010-01-08 10:42:17 UTC
(In reply to comment #16)
> Here, the ME might be tempted to change the order of WAIT and "var = 7"; thus
> in this case we probably need to tell the ME about the ASYNCHRONOUS attribute.

Probably by dropping the "restricted" for the pointer argument (as one would to for TARGET). One should also check that it works for:
  subroutine finish(var, wait)
    BLOCK
      asynchronous :: var
      wait(wait)
      var = 7
    end BLOCK
  end subroutine finish
assuming that "asynchronous" applies in the block to the dummy argument. (Should work analogously for volatile.)
Comment 18 Tobias Burnus 2010-07-13 17:34:20 UTC
Reminder: The function decl ("fn spec") needs to be updated for asynchronous I/O; in particular WAIT needs to have the "X" (unused argument) removed. Possibly, other function names should be used to keep the nonclobber of the current transfer functions. Cf. also PR 43665.
Comment 19 Tobias Burnus 2011-03-04 18:08:14 UTC
(In reply to comment #16)
>   subroutine finish(var, wait)
>     asynchronous :: var
>     wait(wait)
>     var = 7
>   end subroutine finish
> 
> Here, the ME might be tempted to change the order of WAIT and "var = 7"; thus
> in this case we probably need to tell the ME about the ASYNCHRONOUS attribute.

A brute-force method would be to add a __sync_synchronize (BUILT_IN_SYNCHRONIZE) call after the WAIT. But maybe one finds a better way which restricts the barrier to only "var" (and other asynchronous variables) without influencing unrelated variables.
Comment 20 Jakub Jelinek 2011-03-04 18:11:56 UTC
If ASYNCHRONOUS expands to volatile, no barrier should be necessary.
Comment 21 Tobias Burnus 2011-04-15 09:10:56 UTC
(In reply to comment #19)
> A brute-force method would be to add a __sync_synchronize

Actually, this idea does not work properly - neither for INQUIRE(...,PENDING=) nor for ASYNCHRONOUS with MPI 3. (Cf. link below)

(In reply to comment #20)
> If ASYNCHRONOUS expands to volatile, no barrier should be necessary.

Well, VOLATILE has the wrong semantics, i.e. it will only partially solve the problem. Additionally, you create huge missed-optimization issues.

I have now asked at GCC@ (and fortran@) for some suggestions:
http://gcc.gnu.org/ml/fortran/2011-04/msg00143.html

(There is currently also a vivid discussion on J3's interop and MPI Forum's MPI3-Fortran mailing lists about ASYNCHRONOUS and nonblocking MPI calls.)
Comment 22 Tobias Burnus 2011-07-13 09:24:40 UTC
Note: TR 29113 introduces a wider coverage of ASYNCHRONOUS, cf. almost-PDTR 29113 at ftp://ftp.nag.co.uk/sc22wg5/N1851-N1900/N1866.pdf.

I think the easiest is to not set the "restrict" of dummy arguments involved in ASYNCHRONOUS I/O. That way, one has:

  call user_write(id, var)
  ...
  call user_wait(id)
  var = ...

The address of the "var" escapes at "user_write" and is thus available to "user_wait" - hence, "var =" will not be moved across "user_wait". Ditto for gfortran's asynchronous I/O.
Comment 23 Tobias Burnus 2011-07-13 13:15:39 UTC
(In reply to comment #22)
> I think the easiest is to not set the "restrict" of dummy arguments involved in
> ASYNCHRONOUS I/O.

It seems that GCC understands something different than I by "restrict"; it seems to be much less aggressive than I thought - and seems to match exactly what we need, such that no action seems to be required.

Cf. http://gcc.gnu.org/ml/gcc/2011-07/msg00208.html and see PR 49733 for a missed-optimization PR, which is for adding an variable attribute which does optimize across function calls - which is allowed most of the time in Fortran (except for ASYNCHRONOUS and for coarrays).
Comment 24 Janne Blomqvist 2016-10-09 18:17:20 UTC
Unassigning myself.
Comment 25 Thomas Koenig 2017-09-23 12:44:12 UTC
Just to make sure there is no double work here :-)
Comment 26 Janne Blomqvist 2017-10-02 08:39:46 UTC
I though I wrote somewhere why I gave up on this, after thinking a lot about the problem in general. However, I can't find my writeup now, so I'll add a short version here so that others who are interested in this problem may benefit.

So, to begin with, non-blocking socket I/O is widely used on Linux and works well (select(), epoll() etc.). However, here we're talking about file IO, not sockets. For file IO, the non-blocking socket programming model doesn't work; files are always considered "fast" devices and thus always return ready if you try to poll them. Thus, asynchronous I/O. The choices are roughly:

1) Linux native AIO: syscalls like io_submit() etc. This however works only on files opened with O_DIRECT, and all I/O must be 512-byte aligned. So clearly this disqualifies this solution for something general purpose like Fortran AIO.

2) POSIX AIO (aio_read() etc.). This, in principle, could work. Except for 1) It uses signals for reporting completions, which is horrible. Also, some may consider it bad form if libgfortran uses (limited) signal numbers for its internal use, preventing applications from using them.  2) On Linux, glibc implements POSIX AIO using a userspace thread pool, with the further restriction that only a single outstanding I/O per file descriptor is possible (which may or may not matter for Fortran AIO). 

3) Do it yourself with a thread pool. Similar to POSIX AIO on Linux/glibc, except you can use something more sane than signals for signaling completion (e.g. pipes or a pure userspace queue).

See also e.g. http://blog.libtorrent.org/2012/10/asynchronous-disk-io/


So, the only solution that has the potential to work well and is portable is #3. It's a fair amount of work, though, and in the end I wasn't convinced it was worth the effort.
Comment 27 Nicolas Koenig 2017-10-02 09:45:25 UTC
(In reply to Janne Blomqvist from comment #26)
> I though I wrote somewhere why I gave up on this, after thinking a lot about
> the problem in general. However, I can't find my writeup now, so I'll add a
> short version here so that others who are interested in this problem may
> benefit.
> 
> So, to begin with, non-blocking socket I/O is widely used on Linux and works
> well (select(), epoll() etc.). However, here we're talking about file IO,
> not sockets. For file IO, the non-blocking socket programming model doesn't
> work; files are always considered "fast" devices and thus always return
> ready if you try to poll them. Thus, asynchronous I/O. The choices are
> roughly:
> 
> 1) Linux native AIO: syscalls like io_submit() etc. This however works only
> on files opened with O_DIRECT, and all I/O must be 512-byte aligned. So
> clearly this disqualifies this solution for something general purpose like
> Fortran AIO.
> 
> 2) POSIX AIO (aio_read() etc.). This, in principle, could work. Except for
> 1) It uses signals for reporting completions, which is horrible. Also, some
> may consider it bad form if libgfortran uses (limited) signal numbers for
> its internal use, preventing applications from using them.  2) On Linux,
> glibc implements POSIX AIO using a userspace thread pool, with the further
> restriction that only a single outstanding I/O per file descriptor is
> possible (which may or may not matter for Fortran AIO). 
> 
> 3) Do it yourself with a thread pool. Similar to POSIX AIO on Linux/glibc,
> except you can use something more sane than signals for signaling completion
> (e.g. pipes or a pure userspace queue).
> 
> See also e.g. http://blog.libtorrent.org/2012/10/asynchronous-disk-io/
> 
> 
> So, the only solution that has the potential to work well and is portable is
> #3. It's a fair amount of work, though, and in the end I wasn't convinced it
> was worth the effort.

At the moment I only plan on using the normal pthread-API. My Idea for an algorythm would be something like this:

=> if a unit is opened with the "asynchronous" flag, a new thread is spun up for this unit.
=> when a TRANSFER_* funktion is called, the buffer and all the other necessary information is enqueued in a asynchronous work queue. (see below)
=> the thread is notified that work has been added
=> the thread takes care of the io
=> when the unit is closed pthread_join() is called

I plan to enqueue the pdt->transfer() calls with their respective arguments in the work queue.

I actually already have a small prototype that implements the principal behind this in c and it works :)

One of the problems I found up until now with this approach is for example the following code snippet:

program main
    implicit none
    open (10, file='foo.dat', asynchronous='yes')
    call s()
    close(10)
contains
    subroutine s()
        integer, dimension (3)::i !presumably on the stack
        i = [0, 1]
        write(10,*) i
        !Now the stack frame is dropped and the pointer that previously
        !pointed to the array now points to nowhere, but it is still enqueued
    end subroutine
end program

Do you see any fundamental problems with this approach or its integration with libgfortran?
Comment 28 Thomas Koenig 2017-10-02 17:39:08 UTC
(In reply to Nicolas Koenig from comment #27)
 
> program main
>     implicit none
>     open (10, file='foo.dat', asynchronous='yes')
>     call s()
>     close(10)
> contains
>     subroutine s()
>         integer, dimension (3)::i !presumably on the stack
>         i = [0, 1]
>         write(10,*) i
>         !Now the stack frame is dropped and the pointer that previously
>         !pointed to the array now points to nowhere, but it is still enqueued
>     end subroutine
> end program

This program is illegal (J3/09-007r3, 9.6.4.1, paragraph 4),
so you do not have to do anything about it.

An interesting case is mixing of synchronous and
asynchronous I/O for the same unit, which is permitted.
I think this is like an implicit WAIT, same as a BACKSPACE,
FLUSH, ...
Comment 29 Thomas Koenig 2017-10-03 15:43:48 UTC
Another thing... if we do

WRITE (10, ASYNCHRONOUS="YES") A

we need to mark A as ASYNCHRONOUS which we will probably have
to treat similar (or identically) to VOLATILE.
Comment 30 Nicolas Koenig 2017-10-28 17:28:41 UTC
Created attachment 42494 [details]
Early patch

Hello everyone,

attached is a first patch that implements async io for integers. I will extend it to work for everything and heavily optimize it before submitting, but I would like some feedback on the overall structure.
Comment 31 Jerry DeLisle 2017-11-06 20:01:36 UTC
(In reply to Nicolas Koenig from comment #30)
> Created attachment 42494 [details]
> Early patch
> 
> Hello everyone,
> 
> attached is a first patch that implements async io for integers. I will
> extend it to work for everything and heavily optimize it before submitting,
> but I would like some feedback on the overall structure.

Lets talk at a little higher level. Some systems provide asynchrounous I/O as a feature of the OS while others do not.

Are you seeking to implement generically for any system or just those that support it more directly?

Do we conclude that we must lock all variables in an asynchronous statement or that they are buffered into the operating system so there is no need to lock the variables.  As soon as they are "written" to the system, those values have been copied into the buffer and there is no need to lock. Then the user is responsible to "WAIT" before doing anything else. ?

I am trying to make sure we all understand how this feature is intended to work. I think I need to read the standard over. So forgive me if I am off base.
Comment 32 Janne Blomqvist 2017-11-16 21:34:34 UTC
Interestingly, Linux 4.14 contains a way to avoid a context switch to a threadpool in case the data is already in the page cache: https://kernelnewbies.org/Linux_4.14#head-8c8861fbded3e87631ab06bcd511f5f0d8bfa220

Might be an interesting optimization sometime in the future..
Comment 33 Jerry DeLisle 2017-11-17 02:41:15 UTC
(In reply to Janne Blomqvist from comment #32)
> Interestingly, Linux 4.14 contains a way to avoid a context switch to a
> threadpool in case the data is already in the page cache:
> https://kernelnewbies.org/Linux_4.14#head-
> 8c8861fbded3e87631ab06bcd511f5f0d8bfa220
> 
> Might be an interesting optimization sometime in the future..

It is interesting that I was reading this very webpage myself today looking at 4.14 feature. I am pretty sure we can hand off the I/O to the OS. I am not so sure how one checks the status of the operaton. This is what wait should do, wait for completion.
Comment 34 Nicolas Koenig 2018-04-08 14:04:35 UTC
Created attachment 43877 [details]
Proof of concept for transfer of a single integer

Here is a proof of concept patch which transfers a single integer:

$ cat foo.f90
program main
  integer :: i
  i = 42
  open(10,asynchronous="yes")
  write (10, *, asynchronous="yes") i
  close (10)
end program main
$ gfortran foo.f90 -lpthread
$ ./a.out
M: LOCK: lock                        prev: unlocked         change_pdt():336
M: ACQ: lock
M: UNLOCK: lock                                             change_pdt():345
M: SIGNAL: &au->work                                        change_pdt():346
T: LOCK: lock                        prev: unlocked         async_io():164
T: ACQ: lock
T: UNLOCK: lock                                             async_io():166
T: WAITING: &au->work                                       async_io():169
M: LOCK: lock                        prev: unlocked         enqueue_transfer():278
M: ACQ: lock
M: UNLOCK: lock                                             enqueue_transfer():287
M: SIGNAL: &au->work                                        enqueue_transfer():288
T: LOCK: lock                        prev: unlocked         async_io():170
T: ACQ: lock
T: UNLOCK: lock                                             async_io():175
T: NOTE: Changing pdts                                      update_pdt():134
T: LOCK: lock                        prev: unlocked         async_io():200
T: ACQ: lock
T: UNLOCK: lock                                             async_io():175
T: NOTE: Starting transfer                                  async_io():189
M: LOCK: lock                        prev: unlocked         enqueue_done():297
M: ACQ: lock
M: UNLOCK: lock                                             enqueue_done():306
M: SIGNAL: &au->work                                        enqueue_done():307
T: LOCK: lock                        prev: locked           async_io():200
T: ACQ: lock
T: UNLOCK: lock                                             async_io():175
T: NOTE: Finalizing write                                   async_io():182
T: LOCK: lock                        prev: unlocked         async_io():200
T: ACQ: lock
T: SIGNAL: &au->emptysignal                                 async_io():215
T: UNLOCK: lock                                             async_io():219
T: WAITING: &au->work                                       async_io():169
T: LOCK: lock                        prev: unlocked         async_io():170
T: ACQ: lock
T: SIGNAL: &au->emptysignal                                 async_io():215
T: UNLOCK: lock                                             async_io():219
T: WAITING: &au->work                                       async_io():169
M: LOCK: lock                        prev: locked           async_close():388
M: ACQ: lock
M: UNLOCK: lock                                             async_close():390
M: SIGNAL: &(au->work)                                      async_wait():375
M: LOCK: lock                        prev: unlocked         async_wait():376
M: ACQ: lock
M: UNLOCK: lock                                             async_wait():378
T: REC: &au->work                                           async_io():169
T: LOCK: lock                        prev: unlocked         async_io():170
T: ACQ: lock
T: SIGNAL: &au->emptysignal                                 async_io():215
T: UNLOCK: lock                                             async_io():221
$ cat fort.10
          42
Comment 35 Nicolas Koenig 2018-04-28 12:07:22 UTC
Created attachment 44034 [details]
Concept patch (works with read and simple wait for integers)
Comment 36 Nicolas Koenig 2018-04-28 12:36:20 UTC
There seems to be a mismatch between the front end and the library.

For

program main
  integer :: id
  character(len=50) :: iomsg
  integer :: iostat
  id = 0
  open(10,file="wait.dat",iostat=iostat,iomsg=iomsg, asynchronous="yes")
  wait (10,id=id)
end program main

the front end generates

    struct __st_parameter_wait wait_parm.1;

    wait_parm.1.common.filename = &"wait.f90"[1]{lb: 1 sz: 1};
    wait_parm.1.common.line = 7;
    wait_parm.1.id = (integer(kind=4) *) (integer(kind=8)) id;
    wait_parm.1.common.flags = 128;
    wait_parm.1.common.unit = 10;
    _gfortran_st_wait (&wait_parm.1);

where the type conversions are strange. The library then receives

(gdb) p *wtp
$1 = {common = {flags = 128, unit = 10, filename = 0x428d70 "wait.f90", line = 7, iomsg_len = 50, iomsg = 0x7fffffffdc90 "\377\377\377\377", 
    iostat = 0x7fffffffdc8c}, id = 0x0, id_len = 8}

so some adjustment of

typedef struct
{
  st_parameter_common common;
  CHARACTER1 (id);
}
st_parameter_wait;

is probably required.
Comment 37 Jerry DeLisle 2018-04-28 14:42:44 UTC
(In reply to Nicolas Koenig from comment #36)
> so some adjustment of
> 
> typedef struct
> {
>   st_parameter_common common;
>   CHARACTER1 (id);
> }
> st_parameter_wait;
> 
> is probably required.

If id is not a string, so should be:

 typedef struct
 {
   st_parameter_common common;
   GFC_IO_INT id;
 }
 st_parameter_wait;
Comment 38 Jerry DeLisle 2018-04-28 14:51:56 UTC
(In reply to Jerry DeLisle from comment #37)
> (In reply to Nicolas Koenig from comment #36)
> > so some adjustment of
> > 
> > typedef struct
> > {
> >   st_parameter_common common;
> >   CHARACTER1 (id);
> > }
> > st_parameter_wait;
> > 
> > is probably required.
> 
> If id is not a string, so should be:
> 
>  typedef struct
>  {
>    st_parameter_common common;
>    GFC_IO_INT id;
>  }
>  st_parameter_wait;

The funky cast of int 8 to an integer 4 in the front end is odd. I wonder if it is related to patches to try to get -fdefault-integer-8 to work. It looks horrible.
Comment 39 Jerry DeLisle 2018-04-28 15:06:43 UTC
Per definition in ioparm.def in frontend:

IOPARM (wait,    id,		1 << 7,  pint4)

id should be a pointer to an integer kind=4.

This means:

>  typedef struct
>  {
>    st_parameter_common common;
>    GFC_IO_INT id;
>  }
>  st_parameter_wait;

should be:

 typedef struct
 {
   st_parameter_common common;
   GFC_INTEGER_4 *id;
 }
 st_parameter_wait;
Comment 40 Nicolas Koenig 2018-05-09 22:43:39 UTC
Created attachment 44106 [details]
Next version of patch

This patch works for reading and writing, for simple data types and
for arrays.

Still missing are mixed synchronous/asynchronous statements, inquire,
flush, backspace, rewind etc  and error handling.

The reason why error handling is not implemented yet is that I do not
understand the standard, and I have not been able to find any
explanation for this:

9.7.1, paragraph 5:

If an error or end-of-file condition occurs during a wait operation for a unit, the processor performs a wait
19 operation for all pending data transfer operations for that unit.

What does that mean? Does it mean that all pending transfers should be
thrown away, or that they should still be performed? I think the second
option is probably the right one, but it seems to make little sense since
trying to flush after and error results in loads and loads of corrupt
data.
Comment 41 Nicolas Koenig 2018-05-20 18:48:25 UTC
Created attachment 44151 [details]
Next version of patch.

Yet another patch version.

Error handling is partially implemented, iostat and iomsg work for WAIT.

This patch drops all pending I/O requests when an error occurs. Given that trying to flush corrupted data almost always is a bad idea, this seems like the only sensible way.

Timing data:

With

program main
  implicit none
  integer, parameter :: n = 10**7
  character(3), parameter :: yes = "no"
  real, dimension(n) :: a,b,c

  call random_number(a)
  call random_number(b)
  call random_number(c)
  open (10, file="a.dat",asynchronous=yes)
  open (20, file="b.dat",asynchronous=yes)
  open (30, file="c.dat",asynchronous=yes)
  write (10,*,asynchronous=yes) a
  write (20,*,asynchronous=yes) b
  write (30,*,asynchronous=yes) c
  wait (10)
  wait (20)
  wait (30)
end program main

real    0m15.465s
user    0m15.313s
sys     0m0.152s

With the "no" replaced by "yes":

real    0m5.558s
user    0m16.253s
sys     0m0.152s

If you ask me, that's quite nice :)
Comment 42 Jerry DeLisle 2018-05-22 02:17:18 UTC
(In reply to Nicolas Koenig from comment #41)
> Created attachment 44151 [details]
> Next version of patch.
--- snip ---

> real    0m15.465s
> user    0m15.313s
> sys     0m0.152s
> 
> With the "no" replaced by "yes":
> 
> real    0m5.558s
> user    0m16.253s
> sys     0m0.152s
> 
> If you ask me, that's quite nice :)

Yes, very impressive.
Comment 43 Nicolas Koenig 2018-07-25 18:49:21 UTC
Author: koenigni
Date: Wed Jul 25 18:48:39 2018
New Revision: 262978

URL: https://gcc.gnu.org/viewcvs?rev=262978&root=gcc&view=rev
Log:
2018-07-25  Nicolas Koenig  <koenigni@gcc.gnu.org>
	Thomas Koenig <tkoenig@gcc.gnu.org>

	PR fortran/25829
	* gfortran.texi: Add description of asynchronous I/O.
	* trans-decl.c (gfc_finish_var_decl): Treat asynchronous variables
	as volatile.
	* trans-io.c (gfc_build_io_library_fndecls): Rename st_wait to
	st_wait_async and change argument spec from ".X" to ".w".
	(gfc_trans_wait): Pass ID argument via reference.

2018-07-25  Nicolas Koenig  <koenigni@gcc.gnu.org>
	Thomas Koenig <tkoenig@gcc.gnu.org>

	PR fortran/25829
	* gfortran.dg/f2003_inquire_1.f03: Add write statement.
	* gfortran.dg/f2003_io_1.f03: Add wait statement.

2018-07-25  Nicolas Koenig  <koenigni@gcc.gnu.org>
	Thomas Koenig <tkoenig@gcc.gnu.org>

	PR fortran/25829
	* Makefile.am: Add async.c to gfor_io_src.
	Add async.h to gfor_io_headers.
	* Makefile.in: Regenerated.
	* gfortran.map: Add _gfortran_st_wait_async.
	* io/async.c: New file.
	* io/async.h: New file.
	* io/close.c: Include async.h.
	(st_close): Call async_wait for an asynchronous unit.
	* io/file_pos.c (st_backspace): Likewise.
	(st_endfile): Likewise.
	(st_rewind): Likewise.
	(st_flush): Likewise.
	* io/inquire.c: Add handling for asynchronous PENDING
	and ID arguments.
	* io/io.h (st_parameter_dt): Add async bit.
	(st_parameter_wait): Correct.
	(gfc_unit): Add au pointer.
	(st_wait_async): Add prototype.
	(transfer_array_inner): Likewise.
	(st_write_done_worker): Likewise.
	* io/open.c: Include async.h.
	(new_unit): Initialize asynchronous unit.
	* io/transfer.c (async_opt): New struct.
	(wrap_scalar_transfer): New function.
	(transfer_integer): Call wrap_scalar_transfer to do the work.
	(transfer_real): Likewise.
	(transfer_real_write): Likewise.
	(transfer_character): Likewise.
	(transfer_character_wide): Likewise.
	(transfer_complex): Likewise.
	(transfer_array_inner): New function.
	(transfer_array): Call transfer_array_inner.
	(transfer_derived): Call wrap_scalar_transfer.
	(data_transfer_init): Check for asynchronous I/O.
	Perform a wait operation on any pending asynchronous I/O
	if the data transfer is synchronous. Copy PDT and enqueue
	thread for data transfer.
	(st_read_done_worker): New function.
	(st_read_done): Enqueue transfer or call st_read_done_worker.
	(st_write_done_worker): New function.
	(st_write_done): Enqueue transfer or call st_read_done_worker.
	(st_wait): Document as no-op for compatibility reasons.
	(st_wait_async): New function.
	* io/unit.c (insert_unit): Use macros LOCK, UNLOCK and TRYLOCK;
	add NOTE where necessary.
	(get_gfc_unit): Likewise.
	(init_units): Likewise.
	(close_unit_1): Likewise. Call async_close if asynchronous.
	(close_unit): Use macros LOCK and UNLOCK.
	(finish_last_advance_record): Likewise.
	(newunit_alloc): Likewise.
	* io/unix.c (find_file): Likewise.
	(flush_all_units_1): Likewise.
	(flush_all_units): Likewise.
	* libgfortran.h (generate_error_common): Add prototype.
	* runtime/error.c: Include io.h and async.h.
	(generate_error_common): New function.

2018-07-25  Nicolas Koenig  <koenigni@gcc.gnu.org>
	Thomas Koenig <tkoenig@gcc.gnu.org>

	PR fortran/25829
	* testsuite/libgomp.fortran/async_io_1.f90: New test.
	* testsuite/libgomp.fortran/async_io_2.f90: New test.
	* testsuite/libgomp.fortran/async_io_3.f90: New test.
	* testsuite/libgomp.fortran/async_io_4.f90: New test.
	* testsuite/libgomp.fortran/async_io_5.f90: New test.
	* testsuite/libgomp.fortran/async_io_6.f90: New test.
	* testsuite/libgomp.fortran/async_io_7.f90: New test.


Added:
    trunk/libgfortran/io/async.c
    trunk/libgfortran/io/async.h
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/gfortran.texi
    trunk/gcc/fortran/trans-decl.c
    trunk/gcc/fortran/trans-io.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gfortran.dg/f2003_inquire_1.f03
    trunk/gcc/testsuite/gfortran.dg/f2003_io_1.f03
    trunk/libgfortran/ChangeLog
    trunk/libgfortran/Makefile.am
    trunk/libgfortran/Makefile.in
    trunk/libgfortran/gfortran.map
    trunk/libgfortran/io/close.c
    trunk/libgfortran/io/file_pos.c
    trunk/libgfortran/io/inquire.c
    trunk/libgfortran/io/io.h
    trunk/libgfortran/io/open.c
    trunk/libgfortran/io/read.c
    trunk/libgfortran/io/transfer.c
    trunk/libgfortran/io/unit.c
    trunk/libgfortran/io/unix.c
    trunk/libgfortran/libgfortran.h
    trunk/libgfortran/runtime/error.c
    trunk/libgomp/ChangeLog
Comment 44 Dominique d'Humieres 2018-07-25 18:58:07 UTC
AFAICT this

2018-07-25  Nicolas Koenig  <koenigni@gcc.gnu.org>
        Thomas Koenig <tkoenig@gcc.gnu.org>

        PR fortran/25829
        * testsuite/libgomp.fortran/async_io_1.f90: New test.
        * testsuite/libgomp.fortran/async_io_2.f90: New test.
        * testsuite/libgomp.fortran/async_io_3.f90: New test.
        * testsuite/libgomp.fortran/async_io_4.f90: New test.
        * testsuite/libgomp.fortran/async_io_5.f90: New test.
        * testsuite/libgomp.fortran/async_io_6.f90: New test.
        * testsuite/libgomp.fortran/async_io_7.f90: New test.

has not been committed yet.
Comment 45 Nicolas Koenig 2018-07-25 19:35:05 UTC
Author: koenigni
Date: Wed Jul 25 19:34:33 2018
New Revision: 262979

URL: https://gcc.gnu.org/viewcvs?rev=262979&root=gcc&view=rev
Log:
2018-07-25  Nicolas Koenig  <koenigni@gcc.gnu.org>
	Thomas Koenig <tkoenig@gcc.gnu.org>

	PR fortran/25829
	* testsuite/libgomp.fortran/async_io_1.f90: Really commit.
	* testsuite/libgomp.fortran/async_io_2.f90: Really commit.
	* testsuite/libgomp.fortran/async_io_3.f90: Really commit.
	* testsuite/libgomp.fortran/async_io_4.f90: Really commit.
	* testsuite/libgomp.fortran/async_io_5.f90: Really commit.
	* testsuite/libgomp.fortran/async_io_6.f90: Really commit.
	* testsuite/libgomp.fortran/async_io_7.f90: Really commit.


Added:
    trunk/libgomp/testsuite/libgomp.fortran/async_io_1.f90
    trunk/libgomp/testsuite/libgomp.fortran/async_io_2.f90
    trunk/libgomp/testsuite/libgomp.fortran/async_io_3.f90
    trunk/libgomp/testsuite/libgomp.fortran/async_io_4.f90
    trunk/libgomp/testsuite/libgomp.fortran/async_io_5.f90
    trunk/libgomp/testsuite/libgomp.fortran/async_io_6.f90
    trunk/libgomp/testsuite/libgomp.fortran/async_io_7.f90
Comment 46 avieira 2018-07-31 08:42:53 UTC
Author: avieira
Date: Tue Jul 31 08:42:21 2018
New Revision: 263082

URL: https://gcc.gnu.org/viewcvs?rev=263082&root=gcc&view=rev
Log:
Reverting 'AsyncI/O patch committed' as it is breaking bare-metal builds.

2018-07-31  Andre Vieira  <andre.simoesdiasvieira@arm.com>

	Revert 'AsyncI/O patch committed'
	2018-07-25  Nicolas Koenig  <koenigni@gcc.gnu.org>
		Thomas Koenig <tkoenig@gcc.gnu.org>

	PR fortran/25829
	* gfortran.texi: Add description of asynchronous I/O.
	* trans-decl.c (gfc_finish_var_decl): Treat asynchronous variables
	as volatile.
	* trans-io.c (gfc_build_io_library_fndecls): Rename st_wait to
	st_wait_async and change argument spec from ".X" to ".w".
	(gfc_trans_wait): Pass ID argument via reference.

2018-07-31  Andre Vieira  <andre.simoesdiasvieira@arm.com>

	Revert 'AsyncI/O patch committed'
	2018-07-25  Nicolas Koenig  <koenigni@gcc.gnu.org>
		Thomas Koenig <tkoenig@gcc.gnu.org>

	PR fortran/25829
	* gfortran.dg/f2003_inquire_1.f03: Add write statement.
	* gfortran.dg/f2003_io_1.f03: Add wait statement.

2018-07-31  Andre Vieira  <andre.simoesdiasvieira@arm.com>

	Revert 'AsyncI/O patch committed'
	2018-07-25  Nicolas Koenig  <koenigni@gcc.gnu.org>
		Thomas Koenig <tkoenig@gcc.gnu.org>

	PR fortran/25829
	* Makefile.am: Add async.c to gfor_io_src.
	Add async.h to gfor_io_headers.
	* Makefile.in: Regenerated.
	* gfortran.map: Add _gfortran_st_wait_async.
	* io/async.c: New file.
	* io/async.h: New file.
	* io/close.c: Include async.h.
	(st_close): Call async_wait for an asynchronous unit.
	* io/file_pos.c (st_backspace): Likewise.
	(st_endfile): Likewise.
	(st_rewind): Likewise.
	(st_flush): Likewise.
	* io/inquire.c: Add handling for asynchronous PENDING
	and ID arguments.
	* io/io.h (st_parameter_dt): Add async bit.
	(st_parameter_wait): Correct.
	(gfc_unit): Add au pointer.
	(st_wait_async): Add prototype.
	(transfer_array_inner): Likewise.
	(st_write_done_worker): Likewise.
	* io/open.c: Include async.h.
	(new_unit): Initialize asynchronous unit.
	* io/transfer.c (async_opt): New struct.
	(wrap_scalar_transfer): New function.
	(transfer_integer): Call wrap_scalar_transfer to do the work.
	(transfer_real): Likewise.
	(transfer_real_write): Likewise.
	(transfer_character): Likewise.
	(transfer_character_wide): Likewise.
	(transfer_complex): Likewise.
	(transfer_array_inner): New function.
	(transfer_array): Call transfer_array_inner.
	(transfer_derived): Call wrap_scalar_transfer.
	(data_transfer_init): Check for asynchronous I/O.
	Perform a wait operation on any pending asynchronous I/O
	if the data transfer is synchronous. Copy PDT and enqueue
	thread for data transfer.
	(st_read_done_worker): New function.
	(st_read_done): Enqueue transfer or call st_read_done_worker.
	(st_write_done_worker): New function.
	(st_write_done): Enqueue transfer or call st_read_done_worker.
	(st_wait): Document as no-op for compatibility reasons.
	(st_wait_async): New function.
	* io/unit.c (insert_unit): Use macros LOCK, UNLOCK and TRYLOCK;
	add NOTE where necessary.
	(get_gfc_unit): Likewise.
	(init_units): Likewise.
	(close_unit_1): Likewise. Call async_close if asynchronous.
	(close_unit): Use macros LOCK and UNLOCK.
	(finish_last_advance_record): Likewise.
	(newunit_alloc): Likewise.
	* io/unix.c (find_file): Likewise.
	(flush_all_units_1): Likewise.
	(flush_all_units): Likewise.
	* libgfortran.h (generate_error_common): Add prototype.
	* runtime/error.c: Include io.h and async.h.
	(generate_error_common): New function.

2018-07-31  Andre Vieira  <andre.simoesdiasvieira@arm.com>

	Revert 'AsyncI/O patch committed'.
	2018-07-25  Nicolas Koenig  <koenigni@gcc.gnu.org>
		Thomas Koenig <tkoenig@gcc.gnu.org>

	PR fortran/25829
	* testsuite/libgomp.fortran/async_io_1.f90: New test.
	* testsuite/libgomp.fortran/async_io_2.f90: New test.
	* testsuite/libgomp.fortran/async_io_3.f90: New test.
	* testsuite/libgomp.fortran/async_io_4.f90: New test.
	* testsuite/libgomp.fortran/async_io_5.f90: New test.
	* testsuite/libgomp.fortran/async_io_6.f90: New test.
	* testsuite/libgomp.fortran/async_io_7.f90: New test.


Removed:
    trunk/libgfortran/io/async.c
    trunk/libgfortran/io/async.h
    trunk/libgomp/testsuite/libgomp.fortran/async_io_1.f90
    trunk/libgomp/testsuite/libgomp.fortran/async_io_2.f90
    trunk/libgomp/testsuite/libgomp.fortran/async_io_3.f90
    trunk/libgomp/testsuite/libgomp.fortran/async_io_4.f90
    trunk/libgomp/testsuite/libgomp.fortran/async_io_5.f90
    trunk/libgomp/testsuite/libgomp.fortran/async_io_6.f90
    trunk/libgomp/testsuite/libgomp.fortran/async_io_7.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/gfortran.texi
    trunk/gcc/fortran/trans-decl.c
    trunk/gcc/fortran/trans-io.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gfortran.dg/f2003_inquire_1.f03
    trunk/gcc/testsuite/gfortran.dg/f2003_io_1.f03
    trunk/libgfortran/ChangeLog
    trunk/libgfortran/Makefile.am
    trunk/libgfortran/Makefile.in
    trunk/libgfortran/gfortran.map
    trunk/libgfortran/io/close.c
    trunk/libgfortran/io/file_pos.c
    trunk/libgfortran/io/inquire.c
    trunk/libgfortran/io/io.h
    trunk/libgfortran/io/open.c
    trunk/libgfortran/io/read.c
    trunk/libgfortran/io/transfer.c
    trunk/libgfortran/io/unit.c
    trunk/libgfortran/io/unix.c
    trunk/libgfortran/libgfortran.h
    trunk/libgfortran/runtime/error.c
    trunk/libgomp/ChangeLog
Comment 47 Christophe Lyon 2018-07-31 12:24:40 UTC
Since Andre has just reverted the patch, the regression I noticed should be fixed, but here it is anyway:
On armeb-none-linux-gnueabihf
--with-mode arm
--with-cpu cortex-a9
--with-fpu neon-fp16
FAIL:    gfortran.dg/array_constructor_8.f90   -O3 -fomit-frame-pointer -funroll-loops -fpeel-loops -ftracer -finline-functions  execution test
FAIL:    gfortran.dg/array_constructor_8.f90   -O3 -g  execution test
Comment 48 Christophe Lyon 2018-08-06 11:20:35 UTC
I've reproduced the problem on armeb with the patch posted at:
https://gcc.gnu.org/ml/gcc-patches/2018-08/msg00208.html

The code generated for the testcase is the same with and without your patch, so I guess the different behavior is caused by different runtime libraries.

I've compiled the testscase with -static, and the results are attached: .exe files are the ELF binaries, .trace files are execution traces from QEMU, .dump files are the output of objdump -d on the ELF binaries.
".ko" are the ones that fail, ".ok" are the ones that succeed.
Comment 49 Christophe Lyon 2018-08-06 11:23:05 UTC
Created attachment 44507 [details]
objdump of OK ELF file
Comment 50 Christophe Lyon 2018-08-06 11:23:37 UTC
Created attachment 44508 [details]
objdump of KO ELF file
Comment 51 Christophe Lyon 2018-08-06 11:24:23 UTC
Created attachment 44509 [details]
execution trace of OK ELF file
Comment 52 Christophe Lyon 2018-08-06 11:25:35 UTC
Created attachment 44510 [details]
execution trace of KO ELF file
Comment 53 Christophe Lyon 2018-08-06 11:29:49 UTC
Sorry, .exe files are too large even after xz compression, I'm not allowed to attach them.
Comment 54 Thomas Koenig 2018-08-16 14:45:26 UTC
Grepping for IN in the execution traces and then running
a diff reveals interesting things:

 IN: __libc_start_main
 IN: __libc_start_main
 IN: _dl_discover_osversion
-IN: uname
-IN: uname
+IN: __uname
+IN: __uname
 IN: _dl_discover_osversion
 IN: _dl_discover_osversion
 IN: _dl_discover_osversion
@@ -53,18 +53,18 @@
 IN: __udivsi3
 IN: __udivsi3
 IN: __libc_setup_tls
-IN: sbrk
-IN: sbrk
+IN: __sbrk
+IN: __sbrk
 IN: __brk
 IN: __brk
 IN: __brk
-IN: sbrk
-IN: sbrk
-IN: sbrk
-IN: sbrk
-IN: sbrk
-IN: sbrk
-IN: sbrk
+IN: __sbrk
+IN: __sbrk
+IN: __sbrk
+IN: __sbrk
+IN: __sbrk
+IN: __sbrk
+IN: __sbrk

[...]

@@ -445,12 +446,13 @@
 IN: _gfortran_set_options
 IN: _gfortran_set_options
 IN: _gfortran_set_options
-IN: bsd_signal
-IN: bsd_signal
+IN: ssignal
+IN: ssignal
 IN: __bsd_signal.part.0
 IN: __bsd_signal.part.0
-IN: __sigaction
-IN: __sigaction
+IN: sigaction
+IN: sigaction
+IN: sigaction
 IN: __libc_sigaction
 IN: __libc_sigaction
 IN: memcpy

It seems that the test case is calling a different C library
version with and without the patch; especially, it is using
the bsd_signal function without the patch and ssignal with it.

This is strange, to say the least, and points towards a basic
problem with the OS, or the emulator...

I am a bit at a loss of how to proceed.
Comment 55 Nicolas Koenig 2018-08-21 18:49:31 UTC
Author: koenigni
Date: Tue Aug 21 18:48:59 2018
New Revision: 263750

URL: https://gcc.gnu.org/viewcvs?rev=263750&root=gcc&view=rev
Log:
2018-08-21  Nicolas Koenig  <koenigni@gcc.gnu.org>
	Thomas Koenig <tkoenig@gcc.gnu.org>

	PR fortran/25829
	* gfortran.texi: Add description of asynchronous I/O.
	* trans-decl.c (gfc_finish_var_decl): Treat asynchronous variables
	as volatile.
	* trans-io.c (gfc_build_io_library_fndecls): Rename st_wait to
	st_wait_async and change argument spec from ".X" to ".w".
	(gfc_trans_wait): Pass ID argument via reference.

2018-08-21  Nicolas Koenig  <koenigni@gcc.gnu.org>
	Thomas Koenig <tkoenig@gcc.gnu.org>

	PR fortran/25829
	* gfortran.dg/f2003_inquire_1.f03: Add write statement.
	* gfortran.dg/f2003_io_1.f03: Add wait statement.

2018-08-21  Nicolas Koenig  <koenigni@gcc.gnu.org>
	Thomas Koenig <tkoenig@gcc.gnu.org>

	PR fortran/25829
	* Makefile.am: Add async.c to gfor_io_src.
	Add async.h to gfor_io_headers.
	* Makefile.in: Regenerated.
	* gfortran.map: Add _gfortran_st_wait_async.
	* io/async.c: New file.
	* io/async.h: New file.
	* io/close.c: Include async.h.
	(st_close): Call async_wait for an asynchronous unit.
	* io/file_pos.c (st_backspace): Likewise.
	(st_endfile): Likewise.
	(st_rewind): Likewise.
	(st_flush): Likewise.
	* io/inquire.c: Add handling for asynchronous PENDING
	and ID arguments.
	* io/io.h (st_parameter_dt): Add async bit.
	(st_parameter_wait): Correct.
	(gfc_unit): Add au pointer.
	(st_wait_async): Add prototype.
	(transfer_array_inner): Likewise.
	(st_write_done_worker): Likewise.
	* io/open.c: Include async.h.
	(new_unit): Initialize asynchronous unit.
	* io/transfer.c (async_opt): New struct.
	(wrap_scalar_transfer): New function.
	(transfer_integer): Call wrap_scalar_transfer to do the work.
	(transfer_real): Likewise.
	(transfer_real_write): Likewise.
	(transfer_character): Likewise.
	(transfer_character_wide): Likewise.
	(transfer_complex): Likewise.
	(transfer_array_inner): New function.
	(transfer_array): Call transfer_array_inner.
	(transfer_derived): Call wrap_scalar_transfer.
	(data_transfer_init): Check for asynchronous I/O.
	Perform a wait operation on any pending asynchronous I/O
	if the data transfer is synchronous. Copy PDT and enqueue
	thread for data transfer.
	(st_read_done_worker): New function.
	(st_read_done): Enqueue transfer or call st_read_done_worker.
	(st_write_done_worker): New function.
	(st_write_done): Enqueue transfer or call st_read_done_worker.
	(st_wait): Document as no-op for compatibility reasons.
	(st_wait_async): New function.
	* io/unit.c (insert_unit): Use macros LOCK, UNLOCK and TRYLOCK;
	add NOTE where necessary.
	(get_gfc_unit): Likewise.
	(init_units): Likewise.
	(close_unit_1): Likewise. Call async_close if asynchronous.
	(close_unit): Use macros LOCK and UNLOCK.
	(finish_last_advance_record): Likewise.
	(newunit_alloc): Likewise.
	* io/unix.c (find_file): Likewise.
	(flush_all_units_1): Likewise.
	(flush_all_units): Likewise.
	* libgfortran.h (generate_error_common): Add prototype.
	* runtime/error.c: Include io.h and async.h.
	(generate_error_common): New function.

2018-08-21  Nicolas Koenig  <koenigni@gcc.gnu.org>
	Thomas Koenig <tkoenig@gcc.gnu.org>

	PR fortran/25829
	* testsuite/libgomp.fortran/async_io_1.f90: New test.
	* testsuite/libgomp.fortran/async_io_2.f90: New test.
	* testsuite/libgomp.fortran/async_io_3.f90: New test.
	* testsuite/libgomp.fortran/async_io_4.f90: New test.
	* testsuite/libgomp.fortran/async_io_5.f90: New test.
	* testsuite/libgomp.fortran/async_io_6.f90: New test.
	* testsuite/libgomp.fortran/async_io_7.f90: New test.


Added:
    trunk/libgfortran/io/async.c
    trunk/libgfortran/io/async.h
    trunk/libgomp/testsuite/libgomp.fortran/async_io_1.f90
    trunk/libgomp/testsuite/libgomp.fortran/async_io_2.f90
    trunk/libgomp/testsuite/libgomp.fortran/async_io_3.f90
    trunk/libgomp/testsuite/libgomp.fortran/async_io_4.f90
    trunk/libgomp/testsuite/libgomp.fortran/async_io_5.f90
    trunk/libgomp/testsuite/libgomp.fortran/async_io_6.f90
    trunk/libgomp/testsuite/libgomp.fortran/async_io_7.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/gfortran.texi
    trunk/gcc/fortran/trans-decl.c
    trunk/gcc/fortran/trans-io.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gfortran.dg/f2003_inquire_1.f03
    trunk/gcc/testsuite/gfortran.dg/f2003_io_1.f03
    trunk/libgfortran/ChangeLog
    trunk/libgfortran/Makefile.am
    trunk/libgfortran/Makefile.in
    trunk/libgfortran/gfortran.map
    trunk/libgfortran/io/close.c
    trunk/libgfortran/io/file_pos.c
    trunk/libgfortran/io/inquire.c
    trunk/libgfortran/io/io.h
    trunk/libgfortran/io/open.c
    trunk/libgfortran/io/read.c
    trunk/libgfortran/io/transfer.c
    trunk/libgfortran/io/unit.c
    trunk/libgfortran/io/unix.c
    trunk/libgfortran/libgfortran.h
    trunk/libgfortran/runtime/error.c
    trunk/libgomp/ChangeLog
Comment 56 Thomas Koenig 2018-09-19 16:36:29 UTC
I think we can close this one.

The armeb regression is tracked in PR87048.