1*b1e83836Smrg /* Copyright (C) 2018-2022 Free Software Foundation, Inc.
2181254a7Smrg Contributed by Nicolas Koenig
3181254a7Smrg
4181254a7Smrg This file is part of the GNU Fortran runtime library (libgfortran).
5181254a7Smrg
6181254a7Smrg Libgfortran is free software; you can redistribute it and/or modify
7181254a7Smrg it under the terms of the GNU General Public License as published by
8181254a7Smrg the Free Software Foundation; either version 3, or (at your option)
9181254a7Smrg any later version.
10181254a7Smrg
11181254a7Smrg Libgfortran is distributed in the hope that it will be useful,
12181254a7Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
13181254a7Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14181254a7Smrg GNU General Public License for more details.
15181254a7Smrg
16181254a7Smrg Under Section 7 of GPL version 3, you are granted additional
17181254a7Smrg permissions described in the GCC Runtime Library Exception, version
18181254a7Smrg 3.1, as published by the Free Software Foundation.
19181254a7Smrg
20181254a7Smrg You should have received a copy of the GNU General Public License and
21181254a7Smrg a copy of the GCC Runtime Library Exception along with this program;
22181254a7Smrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23181254a7Smrg <http://www.gnu.org/licenses/>. */
24181254a7Smrg
25181254a7Smrg #include "libgfortran.h"
26181254a7Smrg
27181254a7Smrg #define _GTHREAD_USE_COND_INIT_FUNC
28181254a7Smrg #include "../../libgcc/gthr.h"
29181254a7Smrg #include "io.h"
30181254a7Smrg #include "fbuf.h"
31181254a7Smrg #include "format.h"
32181254a7Smrg #include "unix.h"
33181254a7Smrg #include <string.h>
34181254a7Smrg #include <assert.h>
35181254a7Smrg
36181254a7Smrg #include <sys/types.h>
37181254a7Smrg
38181254a7Smrg #include "async.h"
39181254a7Smrg #if ASYNC_IO
40181254a7Smrg
41181254a7Smrg DEBUG_LINE (__thread const char *aio_prefix = MPREFIX);
42181254a7Smrg
43181254a7Smrg DEBUG_LINE (__gthread_mutex_t debug_queue_lock = __GTHREAD_MUTEX_INIT;)
44181254a7Smrg DEBUG_LINE (aio_lock_debug *aio_debug_head = NULL;)
45181254a7Smrg
46181254a7Smrg /* Current unit for asynchronous I/O. Needed for error reporting. */
47181254a7Smrg
48181254a7Smrg __thread gfc_unit *thread_unit = NULL;
49181254a7Smrg
50181254a7Smrg /* Queue entry for the asynchronous I/O entry. */
51181254a7Smrg typedef struct transfer_queue
52181254a7Smrg {
53181254a7Smrg enum aio_do type;
54181254a7Smrg struct transfer_queue *next;
55181254a7Smrg struct st_parameter_dt *new_pdt;
56181254a7Smrg transfer_args arg;
57181254a7Smrg _Bool has_id;
58181254a7Smrg int read_flag;
59181254a7Smrg } transfer_queue;
60181254a7Smrg
61181254a7Smrg struct error {
62181254a7Smrg st_parameter_dt *dtp;
63181254a7Smrg int id;
64181254a7Smrg };
65181254a7Smrg
66181254a7Smrg /* Helper function to exchange the old vs. a new PDT. */
67181254a7Smrg
68181254a7Smrg static void
update_pdt(st_parameter_dt ** old,st_parameter_dt * new)69181254a7Smrg update_pdt (st_parameter_dt **old, st_parameter_dt *new) {
70181254a7Smrg st_parameter_dt *temp;
71181254a7Smrg NOTE ("Changing pdts, current_unit = %p", (void *) (new->u.p.current_unit));
72181254a7Smrg temp = *old;
73181254a7Smrg *old = new;
74181254a7Smrg if (temp)
75181254a7Smrg free (temp);
76181254a7Smrg }
77181254a7Smrg
78181254a7Smrg /* Destroy an adv_cond structure. */
79181254a7Smrg
80181254a7Smrg static void
destroy_adv_cond(struct adv_cond * ac)81181254a7Smrg destroy_adv_cond (struct adv_cond *ac)
82181254a7Smrg {
83181254a7Smrg T_ERROR (__gthread_cond_destroy, &ac->signal);
84181254a7Smrg }
85181254a7Smrg
86181254a7Smrg /* Function invoked as start routine for a new asynchronous I/O unit.
87181254a7Smrg Contains the main loop for accepting requests and handling them. */
88181254a7Smrg
89181254a7Smrg static void *
async_io(void * arg)90181254a7Smrg async_io (void *arg)
91181254a7Smrg {
92181254a7Smrg DEBUG_LINE (aio_prefix = TPREFIX);
93181254a7Smrg transfer_queue *ctq = NULL, *prev = NULL;
94181254a7Smrg gfc_unit *u = (gfc_unit *) arg;
95181254a7Smrg async_unit *au = u->au;
96181254a7Smrg LOCK (&au->lock);
97181254a7Smrg thread_unit = u;
98181254a7Smrg au->thread = __gthread_self ();
99181254a7Smrg while (true)
100181254a7Smrg {
101181254a7Smrg /* Main loop. At this point, au->lock is always held. */
102181254a7Smrg WAIT_SIGNAL_MUTEX (&au->work, au->tail != NULL, &au->lock);
103181254a7Smrg LOCK (&au->lock);
104181254a7Smrg ctq = au->head;
105181254a7Smrg prev = NULL;
106181254a7Smrg /* Loop over the queue entries until they are finished. */
107181254a7Smrg while (ctq)
108181254a7Smrg {
109181254a7Smrg if (prev)
110181254a7Smrg free (prev);
111181254a7Smrg prev = ctq;
112181254a7Smrg if (!au->error.has_error)
113181254a7Smrg {
114181254a7Smrg UNLOCK (&au->lock);
115181254a7Smrg
116181254a7Smrg switch (ctq->type)
117181254a7Smrg {
118181254a7Smrg case AIO_WRITE_DONE:
119181254a7Smrg NOTE ("Finalizing write");
120*b1e83836Smrg st_write_done_worker (au->pdt, false);
121181254a7Smrg UNLOCK (&au->io_lock);
122181254a7Smrg break;
123181254a7Smrg
124181254a7Smrg case AIO_READ_DONE:
125181254a7Smrg NOTE ("Finalizing read");
126*b1e83836Smrg st_read_done_worker (au->pdt, false);
127181254a7Smrg UNLOCK (&au->io_lock);
128181254a7Smrg break;
129181254a7Smrg
130181254a7Smrg case AIO_DATA_TRANSFER_INIT:
131181254a7Smrg NOTE ("Data transfer init");
132181254a7Smrg LOCK (&au->io_lock);
133181254a7Smrg update_pdt (&au->pdt, ctq->new_pdt);
134181254a7Smrg data_transfer_init_worker (au->pdt, ctq->read_flag);
135181254a7Smrg break;
136181254a7Smrg
137181254a7Smrg case AIO_TRANSFER_SCALAR:
138181254a7Smrg NOTE ("Starting scalar transfer");
139181254a7Smrg ctq->arg.scalar.transfer (au->pdt, ctq->arg.scalar.arg_bt,
140181254a7Smrg ctq->arg.scalar.data,
141181254a7Smrg ctq->arg.scalar.i,
142181254a7Smrg ctq->arg.scalar.s1,
143181254a7Smrg ctq->arg.scalar.s2);
144181254a7Smrg break;
145181254a7Smrg
146181254a7Smrg case AIO_TRANSFER_ARRAY:
147181254a7Smrg NOTE ("Starting array transfer");
148181254a7Smrg NOTE ("ctq->arg.array.desc = %p",
149181254a7Smrg (void *) (ctq->arg.array.desc));
150181254a7Smrg transfer_array_inner (au->pdt, ctq->arg.array.desc,
151181254a7Smrg ctq->arg.array.kind,
152181254a7Smrg ctq->arg.array.charlen);
153181254a7Smrg free (ctq->arg.array.desc);
154181254a7Smrg break;
155181254a7Smrg
156181254a7Smrg case AIO_CLOSE:
157181254a7Smrg NOTE ("Received AIO_CLOSE");
158181254a7Smrg LOCK (&au->lock);
159181254a7Smrg goto finish_thread;
160181254a7Smrg
161181254a7Smrg default:
162181254a7Smrg internal_error (NULL, "Invalid queue type");
163181254a7Smrg break;
164181254a7Smrg }
165181254a7Smrg LOCK (&au->lock);
166181254a7Smrg if (unlikely (au->error.has_error))
167181254a7Smrg au->error.last_good_id = au->id.low - 1;
168181254a7Smrg }
169181254a7Smrg else
170181254a7Smrg {
171181254a7Smrg if (ctq->type == AIO_WRITE_DONE || ctq->type == AIO_READ_DONE)
172181254a7Smrg {
173181254a7Smrg UNLOCK (&au->io_lock);
174181254a7Smrg }
175181254a7Smrg else if (ctq->type == AIO_CLOSE)
176181254a7Smrg {
177181254a7Smrg NOTE ("Received AIO_CLOSE during error condition");
178181254a7Smrg goto finish_thread;
179181254a7Smrg }
180181254a7Smrg }
181181254a7Smrg
182181254a7Smrg NOTE ("Next ctq, current id: %d", au->id.low);
183181254a7Smrg if (ctq->has_id && au->id.waiting == au->id.low++)
184181254a7Smrg SIGNAL (&au->id.done);
185181254a7Smrg
186181254a7Smrg ctq = ctq->next;
187181254a7Smrg }
188181254a7Smrg au->tail = NULL;
189181254a7Smrg au->head = NULL;
190181254a7Smrg au->empty = 1;
191181254a7Smrg SIGNAL (&au->emptysignal);
192181254a7Smrg }
193181254a7Smrg finish_thread:
194181254a7Smrg au->tail = NULL;
195181254a7Smrg au->head = NULL;
196181254a7Smrg au->empty = 1;
197181254a7Smrg SIGNAL (&au->emptysignal);
198181254a7Smrg free (ctq);
199181254a7Smrg UNLOCK (&au->lock);
200181254a7Smrg return NULL;
201181254a7Smrg }
202181254a7Smrg
203181254a7Smrg /* Free an asynchronous unit. */
204181254a7Smrg
205181254a7Smrg static void
free_async_unit(async_unit * au)206181254a7Smrg free_async_unit (async_unit *au)
207181254a7Smrg {
208181254a7Smrg if (au->tail)
209181254a7Smrg internal_error (NULL, "Trying to free nonempty asynchronous unit");
210181254a7Smrg
211181254a7Smrg destroy_adv_cond (&au->work);
212181254a7Smrg destroy_adv_cond (&au->emptysignal);
213181254a7Smrg destroy_adv_cond (&au->id.done);
214181254a7Smrg T_ERROR (__gthread_mutex_destroy, &au->lock);
215181254a7Smrg free (au);
216181254a7Smrg }
217181254a7Smrg
218181254a7Smrg /* Initialize an adv_cond structure. */
219181254a7Smrg
220181254a7Smrg static void
init_adv_cond(struct adv_cond * ac)221181254a7Smrg init_adv_cond (struct adv_cond *ac)
222181254a7Smrg {
223181254a7Smrg ac->pending = 0;
224181254a7Smrg __GTHREAD_COND_INIT_FUNCTION (&ac->signal);
225181254a7Smrg }
226181254a7Smrg
227181254a7Smrg /* Initialize an asyncronous unit, returning zero on success,
228181254a7Smrg nonzero on failure. It also sets u->au. */
229181254a7Smrg
230181254a7Smrg void
init_async_unit(gfc_unit * u)231181254a7Smrg init_async_unit (gfc_unit *u)
232181254a7Smrg {
233181254a7Smrg async_unit *au;
234181254a7Smrg if (!__gthread_active_p ())
235181254a7Smrg {
236181254a7Smrg u->au = NULL;
237181254a7Smrg return;
238181254a7Smrg }
239181254a7Smrg
240181254a7Smrg au = (async_unit *) xmalloc (sizeof (async_unit));
241181254a7Smrg u->au = au;
242181254a7Smrg init_adv_cond (&au->work);
243181254a7Smrg init_adv_cond (&au->emptysignal);
244181254a7Smrg __GTHREAD_MUTEX_INIT_FUNCTION (&au->lock);
245181254a7Smrg __GTHREAD_MUTEX_INIT_FUNCTION (&au->io_lock);
246181254a7Smrg LOCK (&au->lock);
247181254a7Smrg T_ERROR (__gthread_create, &au->thread, &async_io, (void *) u);
248181254a7Smrg au->pdt = NULL;
249181254a7Smrg au->head = NULL;
250181254a7Smrg au->tail = NULL;
251181254a7Smrg au->empty = true;
252181254a7Smrg au->id.waiting = -1;
253181254a7Smrg au->id.low = 0;
254181254a7Smrg au->id.high = 0;
255181254a7Smrg au->error.fatal_error = 0;
256181254a7Smrg au->error.has_error = 0;
257181254a7Smrg au->error.last_good_id = 0;
258181254a7Smrg init_adv_cond (&au->id.done);
259181254a7Smrg UNLOCK (&au->lock);
260181254a7Smrg }
261181254a7Smrg
262181254a7Smrg /* Enqueue a transfer statement. */
263181254a7Smrg
264181254a7Smrg void
enqueue_transfer(async_unit * au,transfer_args * arg,enum aio_do type)265181254a7Smrg enqueue_transfer (async_unit *au, transfer_args *arg, enum aio_do type)
266181254a7Smrg {
267181254a7Smrg transfer_queue *tq = calloc (sizeof (transfer_queue), 1);
268181254a7Smrg tq->arg = *arg;
269181254a7Smrg tq->type = type;
270181254a7Smrg tq->has_id = 0;
271181254a7Smrg LOCK (&au->lock);
272181254a7Smrg if (!au->tail)
273181254a7Smrg au->head = tq;
274181254a7Smrg else
275181254a7Smrg au->tail->next = tq;
276181254a7Smrg au->tail = tq;
277181254a7Smrg REVOKE_SIGNAL (&(au->emptysignal));
278181254a7Smrg au->empty = false;
279181254a7Smrg SIGNAL (&au->work);
280181254a7Smrg UNLOCK (&au->lock);
281181254a7Smrg }
282181254a7Smrg
283181254a7Smrg /* Enqueue an st_write_done or st_read_done which contains an ID. */
284181254a7Smrg
285181254a7Smrg int
enqueue_done_id(async_unit * au,enum aio_do type)286181254a7Smrg enqueue_done_id (async_unit *au, enum aio_do type)
287181254a7Smrg {
288181254a7Smrg int ret;
289181254a7Smrg transfer_queue *tq = calloc (sizeof (transfer_queue), 1);
290181254a7Smrg
291181254a7Smrg tq->type = type;
292181254a7Smrg tq->has_id = 1;
293181254a7Smrg LOCK (&au->lock);
294181254a7Smrg if (!au->tail)
295181254a7Smrg au->head = tq;
296181254a7Smrg else
297181254a7Smrg au->tail->next = tq;
298181254a7Smrg au->tail = tq;
299181254a7Smrg REVOKE_SIGNAL (&(au->emptysignal));
300181254a7Smrg au->empty = false;
301181254a7Smrg ret = au->id.high++;
302181254a7Smrg NOTE ("Enqueue id: %d", ret);
303181254a7Smrg SIGNAL (&au->work);
304181254a7Smrg UNLOCK (&au->lock);
305181254a7Smrg return ret;
306181254a7Smrg }
307181254a7Smrg
308181254a7Smrg /* Enqueue an st_write_done or st_read_done without an ID. */
309181254a7Smrg
310181254a7Smrg void
enqueue_done(async_unit * au,enum aio_do type)311181254a7Smrg enqueue_done (async_unit *au, enum aio_do type)
312181254a7Smrg {
313181254a7Smrg transfer_queue *tq = calloc (sizeof (transfer_queue), 1);
314181254a7Smrg tq->type = type;
315181254a7Smrg tq->has_id = 0;
316181254a7Smrg LOCK (&au->lock);
317181254a7Smrg if (!au->tail)
318181254a7Smrg au->head = tq;
319181254a7Smrg else
320181254a7Smrg au->tail->next = tq;
321181254a7Smrg au->tail = tq;
322181254a7Smrg REVOKE_SIGNAL (&(au->emptysignal));
323181254a7Smrg au->empty = false;
324181254a7Smrg SIGNAL (&au->work);
325181254a7Smrg UNLOCK (&au->lock);
326181254a7Smrg }
327181254a7Smrg
328181254a7Smrg /* Enqueue a CLOSE statement. */
329181254a7Smrg
330181254a7Smrg void
enqueue_close(async_unit * au)331181254a7Smrg enqueue_close (async_unit *au)
332181254a7Smrg {
333181254a7Smrg transfer_queue *tq = calloc (sizeof (transfer_queue), 1);
334181254a7Smrg
335181254a7Smrg tq->type = AIO_CLOSE;
336181254a7Smrg LOCK (&au->lock);
337181254a7Smrg if (!au->tail)
338181254a7Smrg au->head = tq;
339181254a7Smrg else
340181254a7Smrg au->tail->next = tq;
341181254a7Smrg au->tail = tq;
342181254a7Smrg REVOKE_SIGNAL (&(au->emptysignal));
343181254a7Smrg au->empty = false;
344181254a7Smrg SIGNAL (&au->work);
345181254a7Smrg UNLOCK (&au->lock);
346181254a7Smrg }
347181254a7Smrg
348181254a7Smrg /* The asynchronous unit keeps the currently active PDT around.
349181254a7Smrg This function changes that to the current one. */
350181254a7Smrg
351181254a7Smrg void
enqueue_data_transfer_init(async_unit * au,st_parameter_dt * dt,int read_flag)352181254a7Smrg enqueue_data_transfer_init (async_unit *au, st_parameter_dt *dt, int read_flag)
353181254a7Smrg {
354181254a7Smrg st_parameter_dt *new = xmalloc (sizeof (st_parameter_dt));
355181254a7Smrg transfer_queue *tq = xmalloc (sizeof (transfer_queue));
356181254a7Smrg
357181254a7Smrg memcpy ((void *) new, (void *) dt, sizeof (st_parameter_dt));
358181254a7Smrg
359181254a7Smrg NOTE ("dt->internal_unit_desc = %p", dt->internal_unit_desc);
360181254a7Smrg NOTE ("common.flags & mask = %d", dt->common.flags & IOPARM_LIBRETURN_MASK);
361181254a7Smrg tq->next = NULL;
362181254a7Smrg tq->type = AIO_DATA_TRANSFER_INIT;
363181254a7Smrg tq->read_flag = read_flag;
364181254a7Smrg tq->has_id = 0;
365181254a7Smrg tq->new_pdt = new;
366181254a7Smrg LOCK (&au->lock);
367181254a7Smrg
368181254a7Smrg if (!au->tail)
369181254a7Smrg au->head = tq;
370181254a7Smrg else
371181254a7Smrg au->tail->next = tq;
372181254a7Smrg au->tail = tq;
373181254a7Smrg REVOKE_SIGNAL (&(au->emptysignal));
374181254a7Smrg au->empty = false;
375181254a7Smrg SIGNAL (&au->work);
376181254a7Smrg UNLOCK (&au->lock);
377181254a7Smrg }
378181254a7Smrg
379181254a7Smrg /* Collect the errors that may have happened asynchronously. Return true if
380181254a7Smrg an error has been encountered. */
381181254a7Smrg
382181254a7Smrg bool
collect_async_errors(st_parameter_common * cmp,async_unit * au)383181254a7Smrg collect_async_errors (st_parameter_common *cmp, async_unit *au)
384181254a7Smrg {
385181254a7Smrg bool has_error = au->error.has_error;
386181254a7Smrg
387181254a7Smrg if (has_error)
388181254a7Smrg {
389181254a7Smrg if (generate_error_common (cmp, au->error.family, au->error.message))
390181254a7Smrg {
391181254a7Smrg au->error.has_error = 0;
392181254a7Smrg au->error.cmp = NULL;
393181254a7Smrg }
394181254a7Smrg else
395181254a7Smrg {
396181254a7Smrg /* The program will exit later. */
397181254a7Smrg au->error.fatal_error = true;
398181254a7Smrg }
399181254a7Smrg }
400181254a7Smrg return has_error;
401181254a7Smrg }
402181254a7Smrg
403181254a7Smrg /* Perform a wait operation on an asynchronous unit with an ID specified,
404181254a7Smrg which means collecting the errors that may have happened asynchronously.
405181254a7Smrg Return true if an error has been encountered. */
406181254a7Smrg
407181254a7Smrg bool
async_wait_id(st_parameter_common * cmp,async_unit * au,int i)408181254a7Smrg async_wait_id (st_parameter_common *cmp, async_unit *au, int i)
409181254a7Smrg {
410181254a7Smrg bool ret;
411181254a7Smrg
412181254a7Smrg if (au == NULL)
413181254a7Smrg return false;
414181254a7Smrg
415181254a7Smrg if (cmp == NULL)
416181254a7Smrg cmp = au->error.cmp;
417181254a7Smrg
418181254a7Smrg if (au->error.has_error)
419181254a7Smrg {
420181254a7Smrg if (i <= au->error.last_good_id)
421181254a7Smrg return false;
422181254a7Smrg
423181254a7Smrg return collect_async_errors (cmp, au);
424181254a7Smrg }
425181254a7Smrg
426181254a7Smrg LOCK (&au->lock);
427fb8a8121Smrg if (i > au->id.high)
428fb8a8121Smrg {
429fb8a8121Smrg generate_error_common (cmp, LIBERROR_BAD_WAIT_ID, NULL);
430fb8a8121Smrg UNLOCK (&au->lock);
431fb8a8121Smrg return true;
432fb8a8121Smrg }
433fb8a8121Smrg
434181254a7Smrg NOTE ("Waiting for id %d", i);
435181254a7Smrg if (au->id.waiting < i)
436181254a7Smrg au->id.waiting = i;
437181254a7Smrg SIGNAL (&(au->work));
438181254a7Smrg WAIT_SIGNAL_MUTEX (&(au->id.done),
439181254a7Smrg (au->id.low >= au->id.waiting || au->empty), &au->lock);
440181254a7Smrg LOCK (&au->lock);
441181254a7Smrg ret = collect_async_errors (cmp, au);
442181254a7Smrg UNLOCK (&au->lock);
443181254a7Smrg return ret;
444181254a7Smrg }
445181254a7Smrg
446181254a7Smrg /* Perform a wait operation an an asynchronous unit without an ID. */
447181254a7Smrg
448181254a7Smrg bool
async_wait(st_parameter_common * cmp,async_unit * au)449181254a7Smrg async_wait (st_parameter_common *cmp, async_unit *au)
450181254a7Smrg {
451181254a7Smrg bool ret;
452181254a7Smrg
453181254a7Smrg if (au == NULL)
454181254a7Smrg return false;
455181254a7Smrg
456181254a7Smrg if (cmp == NULL)
457181254a7Smrg cmp = au->error.cmp;
458181254a7Smrg
459181254a7Smrg LOCK (&(au->lock));
460181254a7Smrg SIGNAL (&(au->work));
461181254a7Smrg
462181254a7Smrg if (au->empty)
463181254a7Smrg {
464181254a7Smrg ret = collect_async_errors (cmp, au);
465181254a7Smrg UNLOCK (&au->lock);
466181254a7Smrg return ret;
467181254a7Smrg }
468181254a7Smrg
469181254a7Smrg WAIT_SIGNAL_MUTEX (&(au->emptysignal), (au->empty), &au->lock);
470181254a7Smrg ret = collect_async_errors (cmp, au);
471181254a7Smrg return ret;
472181254a7Smrg }
473181254a7Smrg
474181254a7Smrg /* Close an asynchronous unit. */
475181254a7Smrg
476181254a7Smrg void
async_close(async_unit * au)477181254a7Smrg async_close (async_unit *au)
478181254a7Smrg {
479181254a7Smrg if (au == NULL)
480181254a7Smrg return;
481181254a7Smrg
482181254a7Smrg NOTE ("Closing async unit");
483181254a7Smrg enqueue_close (au);
484181254a7Smrg T_ERROR (__gthread_join, au->thread, NULL);
485181254a7Smrg free_async_unit (au);
486181254a7Smrg }
487181254a7Smrg
488181254a7Smrg #else
489181254a7Smrg
490181254a7Smrg /* Only set u->au to NULL so no async I/O will happen. */
491181254a7Smrg
492181254a7Smrg void
init_async_unit(gfc_unit * u)493181254a7Smrg init_async_unit (gfc_unit *u)
494181254a7Smrg {
495181254a7Smrg u->au = NULL;
496181254a7Smrg return;
497181254a7Smrg }
498181254a7Smrg
499181254a7Smrg /* Do-nothing function, which will not be called. */
500181254a7Smrg
501181254a7Smrg void
enqueue_transfer(async_unit * au,transfer_args * arg,enum aio_do type)502181254a7Smrg enqueue_transfer (async_unit *au, transfer_args *arg, enum aio_do type)
503181254a7Smrg {
504181254a7Smrg return;
505181254a7Smrg }
506181254a7Smrg
507181254a7Smrg /* Do-nothing function, which will not be called. */
508181254a7Smrg
509181254a7Smrg int
enqueue_done_id(async_unit * au,enum aio_do type)510181254a7Smrg enqueue_done_id (async_unit *au, enum aio_do type)
511181254a7Smrg {
512181254a7Smrg return 0;
513181254a7Smrg }
514181254a7Smrg
515181254a7Smrg /* Do-nothing function, which will not be called. */
516181254a7Smrg
517181254a7Smrg void
enqueue_done(async_unit * au,enum aio_do type)518181254a7Smrg enqueue_done (async_unit *au, enum aio_do type)
519181254a7Smrg {
520181254a7Smrg return;
521181254a7Smrg }
522181254a7Smrg
523181254a7Smrg /* Do-nothing function, which will not be called. */
524181254a7Smrg
525181254a7Smrg void
enqueue_close(async_unit * au)526181254a7Smrg enqueue_close (async_unit *au)
527181254a7Smrg {
528181254a7Smrg return;
529181254a7Smrg }
530181254a7Smrg
531181254a7Smrg /* Do-nothing function, which will not be called. */
532181254a7Smrg
533181254a7Smrg void
enqueue_data_transfer_init(async_unit * au,st_parameter_dt * dt,int read_flag)534181254a7Smrg enqueue_data_transfer_init (async_unit *au, st_parameter_dt *dt, int read_flag)
535181254a7Smrg {
536181254a7Smrg return;
537181254a7Smrg }
538181254a7Smrg
539181254a7Smrg /* Do-nothing function, which will not be called. */
540181254a7Smrg
541181254a7Smrg bool
collect_async_errors(st_parameter_common * cmp,async_unit * au)542181254a7Smrg collect_async_errors (st_parameter_common *cmp, async_unit *au)
543181254a7Smrg {
544181254a7Smrg return false;
545181254a7Smrg }
546181254a7Smrg
547181254a7Smrg /* Do-nothing function, which will not be called. */
548181254a7Smrg
549181254a7Smrg bool
async_wait_id(st_parameter_common * cmp,async_unit * au,int i)550181254a7Smrg async_wait_id (st_parameter_common *cmp, async_unit *au, int i)
551181254a7Smrg {
552181254a7Smrg return false;
553181254a7Smrg }
554181254a7Smrg
555181254a7Smrg /* Do-nothing function, which will not be called. */
556181254a7Smrg
557181254a7Smrg bool
async_wait(st_parameter_common * cmp,async_unit * au)558181254a7Smrg async_wait (st_parameter_common *cmp, async_unit *au)
559181254a7Smrg {
560181254a7Smrg return false;
561181254a7Smrg }
562181254a7Smrg
563181254a7Smrg /* Do-nothing function, which will not be called. */
564181254a7Smrg
565181254a7Smrg void
async_close(async_unit * au)566181254a7Smrg async_close (async_unit *au)
567181254a7Smrg {
568181254a7Smrg return;
569181254a7Smrg }
570181254a7Smrg
571181254a7Smrg #endif
572