1*10465441SEvalZero /*
2*10465441SEvalZero * Copyright (c) 2006-2018, RT-Thread Development Team
3*10465441SEvalZero *
4*10465441SEvalZero * SPDX-License-Identifier: Apache-2.0
5*10465441SEvalZero *
6*10465441SEvalZero * Change Logs:
7*10465441SEvalZero * Date Author Notes
8*10465441SEvalZero * 2017/12/30 Bernard The first version.
9*10465441SEvalZero */
10*10465441SEvalZero
11*10465441SEvalZero #include <stdint.h>
12*10465441SEvalZero #include <stdio.h>
13*10465441SEvalZero
14*10465441SEvalZero #include <rthw.h>
15*10465441SEvalZero #include <rtdevice.h>
16*10465441SEvalZero #include <rtthread.h>
17*10465441SEvalZero
18*10465441SEvalZero #include <dfs_posix.h>
19*10465441SEvalZero
20*10465441SEvalZero #include "posix_aio.h"
21*10465441SEvalZero
22*10465441SEvalZero struct rt_workqueue* aio_queue = NULL;
23*10465441SEvalZero
24*10465441SEvalZero /**
25*10465441SEvalZero * The aio_cancel() function shall attempt to cancel one or more asynchronous I/O
26*10465441SEvalZero * requests currently outstanding against file descriptor fildes. The aiocbp
27*10465441SEvalZero * argument points to the asynchronous I/O control block for a particular request
28*10465441SEvalZero * to be canceled. If aiocbp is NULL, then all outstanding cancelable asynchronous
29*10465441SEvalZero * I/O requests against fildes shall be canceled.
30*10465441SEvalZero *
31*10465441SEvalZero * Normal asynchronous notification shall occur for asynchronous I/O operations
32*10465441SEvalZero * that are successfully canceled. If there are requests that cannot be canceled,
33*10465441SEvalZero * then the normal asynchronous completion process shall take place for those
34*10465441SEvalZero * requests when they are completed.
35*10465441SEvalZero *
36*10465441SEvalZero * For requested operations that are successfully canceled, the associated error
37*10465441SEvalZero * status shall be set to [ECANCELED] and the return status shall be -1. For
38*10465441SEvalZero * requested operations that are not successfully canceled, the aiocbp shall not
39*10465441SEvalZero * be modified by aio_cancel().
40*10465441SEvalZero *
41*10465441SEvalZero * If aiocbp is not NULL, then if fildes does not have the same value as the file
42*10465441SEvalZero * descriptor with which the asynchronous operation was initiated, unspecified results occur.
43*10465441SEvalZero *
44*10465441SEvalZero * Which operations are cancelable is implementation-defined.
45*10465441SEvalZero */
aio_cancel(int fd,struct aiocb * cb)46*10465441SEvalZero int aio_cancel(int fd, struct aiocb *cb)
47*10465441SEvalZero {
48*10465441SEvalZero rt_err_t ret;
49*10465441SEvalZero
50*10465441SEvalZero if (!cb) return -EINVAL;
51*10465441SEvalZero if (cb->aio_fildes != fd) return -EINVAL;
52*10465441SEvalZero
53*10465441SEvalZero ret = rt_workqueue_cancel_work_sync(aio_queue, &(cb->aio_work));
54*10465441SEvalZero if (ret == RT_EOK)
55*10465441SEvalZero {
56*10465441SEvalZero errno = -ECANCELED;
57*10465441SEvalZero return -1;
58*10465441SEvalZero }
59*10465441SEvalZero
60*10465441SEvalZero return 0;
61*10465441SEvalZero }
62*10465441SEvalZero
63*10465441SEvalZero /**
64*10465441SEvalZero * The aio_error() function shall return the error status associated with the
65*10465441SEvalZero * aiocb structure referenced by the aiocbp argument. The error status for an
66*10465441SEvalZero * asynchronous I/O operation is the errno value that would be set by the corresponding
67*10465441SEvalZero * read(), write(),
68*10465441SEvalZero */
aio_error(const struct aiocb * cb)69*10465441SEvalZero int aio_error (const struct aiocb *cb)
70*10465441SEvalZero {
71*10465441SEvalZero if (cb)
72*10465441SEvalZero {
73*10465441SEvalZero return cb->aio_result;
74*10465441SEvalZero }
75*10465441SEvalZero
76*10465441SEvalZero return -EINVAL;
77*10465441SEvalZero }
78*10465441SEvalZero
79*10465441SEvalZero /**
80*10465441SEvalZero * The aio_fsync() function shall asynchronously perform a file synchronization
81*10465441SEvalZero * operation, as specified by the op argument, for I/O operations associated with
82*10465441SEvalZero * the file indicated by the file descriptor aio_fildes member of the aiocb
83*10465441SEvalZero * structure referenced by the aiocbp argument and queued at the time of the
84*10465441SEvalZero * call to aio_fsync(). The function call shall return when the synchronization
85*10465441SEvalZero * request has been initiated or queued to the file or device (even when the data
86*10465441SEvalZero * cannot be synchronized immediately).
87*10465441SEvalZero *
88*10465441SEvalZero * option: If op is O_DSYNC, all currently queued I/O operations shall be completed
89*10465441SEvalZero * as if by a call to fdatasync(); that is, as defined for synchronized I/O data
90*10465441SEvalZero * integrity completion.
91*10465441SEvalZero *
92*10465441SEvalZero * option: If op is O_SYNC, all currently queued I/O operations shall be completed
93*10465441SEvalZero * as if by a call to fsync(); that is, as defined for synchronized I/O file integrity
94*10465441SEvalZero * completion. If the aio_fsync() function fails, or if the operation queued by
95*10465441SEvalZero * aio_fsync() fails, then outstanding I/O operations are not guaranteed to have
96*10465441SEvalZero * been completed.
97*10465441SEvalZero *
98*10465441SEvalZero * If aio_fsync() succeeds, then it is only the I/O that was queued at the time
99*10465441SEvalZero * of the call to aio_fsync() that is guaranteed to be forced to the relevant
100*10465441SEvalZero * completion state. The completion of subsequent I/O on the file descriptor is
101*10465441SEvalZero * not guaranteed to be completed in a synchronized fashion.
102*10465441SEvalZero *
103*10465441SEvalZero * The aiocbp argument refers to an asynchronous I/O control block. The aiocbp
104*10465441SEvalZero * value may be used as an argument to aio_error() and aio_return() in order to
105*10465441SEvalZero * determine the error status and return status, respectively, of the asynchronous
106*10465441SEvalZero * operation while it is proceeding. When the request is queued, the error status
107*10465441SEvalZero * for the operation is [EINPROGRESS]. When all data has been successfully transferred,
108*10465441SEvalZero * the error status shall be reset to reflect the success or failure of the operation.
109*10465441SEvalZero * If the operation does not complete successfully, the error status for the
110*10465441SEvalZero * operation shall be set to indicate the error. The aio_sigevent member determines
111*10465441SEvalZero * the asynchronous notification to occur as specified in Signal Generation and
112*10465441SEvalZero * Delivery when all operations have achieved synchronized I/O completion. All
113*10465441SEvalZero * other members of the structure referenced by aiocbp are ignored. If the control
114*10465441SEvalZero * block referenced by aiocbp becomes an illegal address prior to asynchronous
115*10465441SEvalZero * I/O completion, then the behavior is undefined.
116*10465441SEvalZero *
117*10465441SEvalZero * If the aio_fsync() function fails or aiocbp indicates an error condition,
118*10465441SEvalZero * data is not guaranteed to have been successfully transferred.
119*10465441SEvalZero */
aio_fync_work(struct rt_work * work,void * work_data)120*10465441SEvalZero static void aio_fync_work(struct rt_work* work, void* work_data)
121*10465441SEvalZero {
122*10465441SEvalZero int result;
123*10465441SEvalZero rt_ubase_t level;
124*10465441SEvalZero struct aiocb *cb = (struct aiocb*)work_data;
125*10465441SEvalZero
126*10465441SEvalZero RT_ASSERT(cb != RT_NULL);
127*10465441SEvalZero
128*10465441SEvalZero result = fsync(cb->aio_fildes);
129*10465441SEvalZero /* modify result */
130*10465441SEvalZero level = rt_hw_interrupt_disable();
131*10465441SEvalZero if (result < 0)
132*10465441SEvalZero cb->aio_result = errno;
133*10465441SEvalZero else
134*10465441SEvalZero cb->aio_result = 0;
135*10465441SEvalZero rt_hw_interrupt_enable(level);
136*10465441SEvalZero
137*10465441SEvalZero return ;
138*10465441SEvalZero }
139*10465441SEvalZero
aio_fsync(int op,struct aiocb * cb)140*10465441SEvalZero int aio_fsync(int op, struct aiocb *cb)
141*10465441SEvalZero {
142*10465441SEvalZero rt_ubase_t level;
143*10465441SEvalZero if (!cb) return -EINVAL;
144*10465441SEvalZero
145*10465441SEvalZero level = rt_hw_interrupt_disable();
146*10465441SEvalZero cb->aio_result = -EINPROGRESS;
147*10465441SEvalZero rt_hw_interrupt_enable(level);
148*10465441SEvalZero
149*10465441SEvalZero rt_work_init(&(cb->aio_work), aio_fync_work, cb);
150*10465441SEvalZero rt_workqueue_dowork(aio_queue, &(cb->aio_work));
151*10465441SEvalZero
152*10465441SEvalZero return 0;
153*10465441SEvalZero }
154*10465441SEvalZero
aio_read_work(struct rt_work * work,void * work_data)155*10465441SEvalZero static void aio_read_work(struct rt_work* work, void* work_data)
156*10465441SEvalZero {
157*10465441SEvalZero int len;
158*10465441SEvalZero rt_ubase_t level;
159*10465441SEvalZero uint8_t *buf_ptr;
160*10465441SEvalZero struct aiocb *cb = (struct aiocb*)work_data;
161*10465441SEvalZero
162*10465441SEvalZero buf_ptr = (uint8_t*)cb->aio_buf;
163*10465441SEvalZero
164*10465441SEvalZero /* seek to offset */
165*10465441SEvalZero lseek(cb->aio_fildes, cb->aio_offset, SEEK_SET);
166*10465441SEvalZero len = read(cb->aio_fildes, &buf_ptr[cb->aio_offset], cb->aio_nbytes);
167*10465441SEvalZero
168*10465441SEvalZero /* modify result */
169*10465441SEvalZero level = rt_hw_interrupt_disable();
170*10465441SEvalZero if (len <= 0)
171*10465441SEvalZero cb->aio_result = errno;
172*10465441SEvalZero else
173*10465441SEvalZero cb->aio_result = len;
174*10465441SEvalZero rt_hw_interrupt_enable(level);
175*10465441SEvalZero
176*10465441SEvalZero return ;
177*10465441SEvalZero }
178*10465441SEvalZero
179*10465441SEvalZero /**
180*10465441SEvalZero * The aio_read() function shall read aiocbp->aio_nbytes from the file associated
181*10465441SEvalZero * with aiocbp->aio_fildes into the buffer pointed to by aiocbp->aio_buf. The
182*10465441SEvalZero * function call shall return when the read request has been initiated or queued
183*10465441SEvalZero * to the file or device (even when the data cannot be delivered immediately).
184*10465441SEvalZero *
185*10465441SEvalZero * If prioritized I/O is supported for this file, then the asynchronous operation
186*10465441SEvalZero * shall be submitted at a priority equal to a base scheduling priority minus
187*10465441SEvalZero * aiocbp->aio_reqprio. If Thread Execution Scheduling is not supported, then
188*10465441SEvalZero * the base scheduling priority is that of the calling process;
189*10465441SEvalZero *
190*10465441SEvalZero * otherwise, the base scheduling priority is that of the calling thread.
191*10465441SEvalZero *
192*10465441SEvalZero * The aiocbp value may be used as an argument to aio_error() and aio_return()
193*10465441SEvalZero * in order to determine the error status and return status, respectively, of
194*10465441SEvalZero * the asynchronous operation while it is proceeding. If an error condition is
195*10465441SEvalZero * encountered during queuing, the function call shall return without having
196*10465441SEvalZero * initiated or queued the request. The requested operation takes place at the
197*10465441SEvalZero * absolute position in the file as given by aio_offset, as if lseek() were called
198*10465441SEvalZero * immediately prior to the operation with an offset equal to aio_offset and a
199*10465441SEvalZero * whence equal to SEEK_SET. After a successful call to enqueue an asynchronous
200*10465441SEvalZero * I/O operation, the value of the file offset for the file is unspecified.
201*10465441SEvalZero *
202*10465441SEvalZero * The aio_sigevent member specifies the notification which occurs when the
203*10465441SEvalZero * request is completed.
204*10465441SEvalZero *
205*10465441SEvalZero * The aiocbp->aio_lio_opcode field shall be ignored by aio_read().
206*10465441SEvalZero *
207*10465441SEvalZero * The aiocbp argument points to an aiocb structure. If the buffer pointed to by
208*10465441SEvalZero * aiocbp->aio_buf or the control block pointed to by aiocbp becomes an illegal
209*10465441SEvalZero * address prior to asynchronous I/O completion, then the behavior is undefined.
210*10465441SEvalZero *
211*10465441SEvalZero * Simultaneous asynchronous operations using the same aiocbp produce undefined
212*10465441SEvalZero * results.
213*10465441SEvalZero *
214*10465441SEvalZero * If synchronized I/O is enabled on the file associated with aiocbp->aio_fildes,
215*10465441SEvalZero * the behavior of this function shall be according to the definitions of synchronized
216*10465441SEvalZero * I/O data integrity completion and synchronized I/O file integrity completion.
217*10465441SEvalZero *
218*10465441SEvalZero * For any system action that changes the process memory space while an asynchronous
219*10465441SEvalZero * I/O is outstanding to the address range being changed, the result of that action
220*10465441SEvalZero * is undefined.
221*10465441SEvalZero *
222*10465441SEvalZero * For regular files, no data transfer shall occur past the offset maximum
223*10465441SEvalZero * established in the open file description associated with aiocbp->aio_fildes.
224*10465441SEvalZero *
225*10465441SEvalZero */
aio_read(struct aiocb * cb)226*10465441SEvalZero int aio_read(struct aiocb *cb)
227*10465441SEvalZero {
228*10465441SEvalZero rt_ubase_t level;
229*10465441SEvalZero
230*10465441SEvalZero if (!cb) return -EINVAL;
231*10465441SEvalZero if (cb->aio_offset < 0) return -EINVAL;
232*10465441SEvalZero
233*10465441SEvalZero level = rt_hw_interrupt_disable();
234*10465441SEvalZero cb->aio_result = -EINPROGRESS;
235*10465441SEvalZero rt_hw_interrupt_enable(level);
236*10465441SEvalZero
237*10465441SEvalZero /* en-queue read work */
238*10465441SEvalZero rt_work_init(&(cb->aio_work), aio_read_work, cb);
239*10465441SEvalZero rt_workqueue_dowork(aio_queue, &(cb->aio_work));
240*10465441SEvalZero
241*10465441SEvalZero return 0;
242*10465441SEvalZero }
243*10465441SEvalZero
244*10465441SEvalZero /**
245*10465441SEvalZero * The aio_return() function shall return the return status associated with the
246*10465441SEvalZero * aiocb structure referenced by the aiocbp argument. The return status for an
247*10465441SEvalZero * asynchronous I/O operation is the value that would be returned by the corresponding
248*10465441SEvalZero * read(), write(), or fsync() function call. If the error status for the operation
249*10465441SEvalZero * is equal to [EINPROGRESS], then the return status for the operation is undefined.
250*10465441SEvalZero * The aio_return() function may be called exactly once to retrieve the return
251*10465441SEvalZero * status of a given asynchronous operation; thereafter, if the same aiocb structure
252*10465441SEvalZero * is used in a call to aio_return() or aio_error(), an error may be returned.
253*10465441SEvalZero * When the aiocb structure referred to by aiocbp is used to submit another asynchronous
254*10465441SEvalZero * operation, then aio_return() may be successfully used to retrieve the return
255*10465441SEvalZero * status of that operation.
256*10465441SEvalZero */
aio_return(struct aiocb * cb)257*10465441SEvalZero ssize_t aio_return(struct aiocb *cb)
258*10465441SEvalZero {
259*10465441SEvalZero if (cb)
260*10465441SEvalZero {
261*10465441SEvalZero if (cb->aio_result < 0)
262*10465441SEvalZero rt_set_errno(cb->aio_result);
263*10465441SEvalZero
264*10465441SEvalZero return cb->aio_result;
265*10465441SEvalZero }
266*10465441SEvalZero
267*10465441SEvalZero return -EINVAL;
268*10465441SEvalZero }
269*10465441SEvalZero
270*10465441SEvalZero /**
271*10465441SEvalZero * The aio_suspend() function shall suspend the calling thread until at least
272*10465441SEvalZero * one of the asynchronous I/O operations referenced by the list argument has
273*10465441SEvalZero * completed, until a signal interrupts the function, or, if timeout is not NULL,
274*10465441SEvalZero * until the time interval specified by timeout has passed. If any of the aiocb
275*10465441SEvalZero * structures in the list correspond to completed asynchronous I/O operations
276*10465441SEvalZero * (that is, the error status for the operation is not equal to [EINPROGRESS])
277*10465441SEvalZero * at the time of the call, the function shall return without suspending the
278*10465441SEvalZero * calling thread. The list argument is an array of pointers to asynchronous I/O
279*10465441SEvalZero * control blocks. The nent argument indicates the number of elements in the
280*10465441SEvalZero * array. Each aiocb structure pointed to has been used in initiating an asynchronous
281*10465441SEvalZero * I/O request via aio_read(), aio_write(), or lio_listio(). This array may
282*10465441SEvalZero * contain null pointers, which are ignored. If this array contains pointers
283*10465441SEvalZero * that refer to aiocb structures that have not been used in submitting asynchronous
284*10465441SEvalZero * I/O, the effect is undefined.
285*10465441SEvalZero *
286*10465441SEvalZero * If the time interval indicated in the timespec structure pointed to by timeout
287*10465441SEvalZero * passes before any of the I/O operations referenced by list are completed, then
288*10465441SEvalZero * aio_suspend() shall return with an error.
289*10465441SEvalZero */
aio_suspend(const struct aiocb * const list[],int nent,const struct timespec * timeout)290*10465441SEvalZero int aio_suspend(const struct aiocb *const list[], int nent,
291*10465441SEvalZero const struct timespec *timeout)
292*10465441SEvalZero {
293*10465441SEvalZero return -ENOSYS;
294*10465441SEvalZero }
295*10465441SEvalZero
aio_write_work(struct rt_work * work,void * work_data)296*10465441SEvalZero static void aio_write_work(struct rt_work* work, void* work_data)
297*10465441SEvalZero {
298*10465441SEvalZero int len, oflags, level;
299*10465441SEvalZero uint8_t *buf_ptr;
300*10465441SEvalZero struct aiocb *cb = (struct aiocb*)work_data;
301*10465441SEvalZero
302*10465441SEvalZero buf_ptr = (uint8_t*)cb->aio_buf;
303*10465441SEvalZero
304*10465441SEvalZero /* whether seek offset */
305*10465441SEvalZero oflags = fcntl(cb->aio_fildes, F_GETFL, 0);
306*10465441SEvalZero if ((oflags & O_APPEND) == 0)
307*10465441SEvalZero {
308*10465441SEvalZero lseek(cb->aio_fildes, SEEK_SET, cb->aio_offset);
309*10465441SEvalZero }
310*10465441SEvalZero
311*10465441SEvalZero /* write data */
312*10465441SEvalZero len = write(cb->aio_fildes, buf_ptr, cb->aio_nbytes);
313*10465441SEvalZero
314*10465441SEvalZero /* modify result */
315*10465441SEvalZero level = rt_hw_interrupt_disable();
316*10465441SEvalZero if (len <= 0)
317*10465441SEvalZero cb->aio_result = errno;
318*10465441SEvalZero else
319*10465441SEvalZero cb->aio_result = len;
320*10465441SEvalZero rt_hw_interrupt_enable(level);
321*10465441SEvalZero
322*10465441SEvalZero return;
323*10465441SEvalZero }
324*10465441SEvalZero
325*10465441SEvalZero /**
326*10465441SEvalZero * The aio_write() function shall write aiocbp->aio_nbytes to the file associated
327*10465441SEvalZero * with aiocbp->aio_fildes from the buffer pointed to by aiocbp->aio_buf. The
328*10465441SEvalZero * function shall return when the write request has been initiated or, at a minimum,
329*10465441SEvalZero * queued to the file or device.
330*10465441SEvalZero *
331*10465441SEvalZero * The aiocbp argument may be used as an argument to aio_error() and aio_return()
332*10465441SEvalZero * in order to determine the error status and return status, respectively, of the
333*10465441SEvalZero * asynchronous operation while it is proceeding.
334*10465441SEvalZero *
335*10465441SEvalZero * The aiocbp argument points to an aiocb structure. If the buffer pointed to by
336*10465441SEvalZero * aiocbp->aio_buf or the control block pointed to by aiocbp becomes an illegal
337*10465441SEvalZero * address prior to asynchronous I/O completion, then the behavior is undefined.
338*10465441SEvalZero *
339*10465441SEvalZero * If O_APPEND is not set for the file descriptor aio_fildes, then the requested
340*10465441SEvalZero * operation shall take place at the absolute position in the file as given by
341*10465441SEvalZero * aio_offset, as if lseek() were called immediately prior to the operation with
342*10465441SEvalZero * an offset equal to aio_offset and a whence equal to SEEK_SET. If O_APPEND is
343*10465441SEvalZero * set for the file descriptor, or if aio_fildes is associated with a device that
344*10465441SEvalZero * is incapable of seeking, write operations append to the file in the same order
345*10465441SEvalZero * as the calls were made, except under circumstances described in Asynchronous
346*10465441SEvalZero * I/O. After a successful call to enqueue an asynchronous I/O operation, the value
347*10465441SEvalZero * of the file offset for the file is unspecified.
348*10465441SEvalZero *
349*10465441SEvalZero * The aio_sigevent member specifies the notification which occurs when the request
350*10465441SEvalZero * is completed.
351*10465441SEvalZero *
352*10465441SEvalZero * The aiocbp->aio_lio_opcode field shall be ignored by aio_write().
353*10465441SEvalZero *
354*10465441SEvalZero * Simultaneous asynchronous operations using the same aiocbp produce undefined
355*10465441SEvalZero * results.
356*10465441SEvalZero *
357*10465441SEvalZero * If synchronized I/O is enabled on the file associated with aiocbp->aio_fildes,
358*10465441SEvalZero * the behavior of this function shall be according to the definitions of synchronized
359*10465441SEvalZero * I/O data integrity completion, and synchronized I/O file integrity completion.
360*10465441SEvalZero *
361*10465441SEvalZero * For regular files, no data transfer shall occur past the offset maximum established
362*10465441SEvalZero * in the open file description associated with aiocbp->aio_fildes.
363*10465441SEvalZero */
aio_write(struct aiocb * cb)364*10465441SEvalZero int aio_write(struct aiocb *cb)
365*10465441SEvalZero {
366*10465441SEvalZero int oflags;
367*10465441SEvalZero rt_ubase_t level;
368*10465441SEvalZero
369*10465441SEvalZero if (!cb || (cb->aio_buf == NULL)) return -EINVAL;
370*10465441SEvalZero
371*10465441SEvalZero /* check access mode */
372*10465441SEvalZero oflags = fcntl(cb->aio_fildes, F_GETFL, 0);
373*10465441SEvalZero if ((oflags & O_ACCMODE) != O_WRONLY ||
374*10465441SEvalZero (oflags & O_ACCMODE) != O_RDWR)
375*10465441SEvalZero return -EINVAL;
376*10465441SEvalZero
377*10465441SEvalZero level = rt_hw_interrupt_disable();
378*10465441SEvalZero cb->aio_result = -EINPROGRESS;
379*10465441SEvalZero rt_hw_interrupt_enable(level);
380*10465441SEvalZero
381*10465441SEvalZero rt_work_init(&(cb->aio_work), aio_write_work, cb);
382*10465441SEvalZero rt_workqueue_dowork(aio_queue, &(cb->aio_work));
383*10465441SEvalZero
384*10465441SEvalZero return 0;
385*10465441SEvalZero }
386*10465441SEvalZero
387*10465441SEvalZero /**
388*10465441SEvalZero * The lio_listio() function shall initiate a list of I/O requests with a single
389*10465441SEvalZero * function call.
390*10465441SEvalZero *
391*10465441SEvalZero * The mode argument takes one of the values LIO_WAIT or LIO_NOWAIT declared in
392*10465441SEvalZero * <aio.h> and determines whether the function returns when the I/O operations
393*10465441SEvalZero * have been completed, or as soon as the operations have been queued. If the
394*10465441SEvalZero * mode argument is LIO_WAIT, the function shall wait until all I/O is complete
395*10465441SEvalZero * and the sig argument shall be ignored.
396*10465441SEvalZero *
397*10465441SEvalZero * If the mode argument is LIO_NOWAIT, the function shall return immediately, and
398*10465441SEvalZero * asynchronous notification shall occur, according to the sig argument, when all
399*10465441SEvalZero * the I/O operations complete. If sig is NULL, then no asynchronous notification
400*10465441SEvalZero * shall occur. If sig is not NULL, asynchronous notification occurs as specified
401*10465441SEvalZero * in Signal Generation and Delivery when all the requests in list have completed.
402*10465441SEvalZero *
403*10465441SEvalZero * The I/O requests enumerated by list are submitted in an unspecified order.
404*10465441SEvalZero *
405*10465441SEvalZero * The list argument is an array of pointers to aiocb structures. The array contains
406*10465441SEvalZero * nent elements. The array may contain NULL elements, which shall be ignored.
407*10465441SEvalZero *
408*10465441SEvalZero * If the buffer pointed to by list or the aiocb structures pointed to by the
409*10465441SEvalZero * elements of the array list become illegal addresses before all asynchronous I/O
410*10465441SEvalZero * completed and, if necessary, the notification is sent, then the behavior is
411*10465441SEvalZero * undefined. If the buffers pointed to by the aio_buf member of the aiocb structure
412*10465441SEvalZero * pointed to by the elements of the array list become illegal addresses prior to
413*10465441SEvalZero * the asynchronous I/O associated with that aiocb structure being completed, the
414*10465441SEvalZero * behavior is undefined.
415*10465441SEvalZero *
416*10465441SEvalZero * The aio_lio_opcode field of each aiocb structure specifies the operation to be
417*10465441SEvalZero * performed. The supported operations are LIO_READ, LIO_WRITE, and LIO_NOP; these
418*10465441SEvalZero * symbols are defined in <aio.h>. The LIO_NOP operation causes the list entry to
419*10465441SEvalZero * be ignored. If the aio_lio_opcode element is equal to LIO_READ, then an I/O operation
420*10465441SEvalZero * is submitted as if by a call to aio_read() with the aiocbp equal to the address
421*10465441SEvalZero * of the aiocb structure. If the aio_lio_opcode element is equal to LIO_WRITE, then
422*10465441SEvalZero * an I/O operation is submitted as if by a call to aio_write() with the aiocbp equal
423*10465441SEvalZero * to the address of the aiocb structure.
424*10465441SEvalZero *
425*10465441SEvalZero * The aio_fildes member specifies the file descriptor on which the operation is to
426*10465441SEvalZero * be performed.
427*10465441SEvalZero *
428*10465441SEvalZero * The aio_buf member specifies the address of the buffer to or from which the data
429*10465441SEvalZero * is transferred.
430*10465441SEvalZero *
431*10465441SEvalZero * The aio_nbytes member specifies the number of bytes of data to be transferred.
432*10465441SEvalZero *
433*10465441SEvalZero * The members of the aiocb structure further describe the I/O operation to be
434*10465441SEvalZero * performed, in a manner identical to that of the corresponding aiocb structure
435*10465441SEvalZero * when used by the aio_read() and aio_write() functions.
436*10465441SEvalZero *
437*10465441SEvalZero * The nent argument specifies how many elements are members of the list; that is,
438*10465441SEvalZero * the length of the array.
439*10465441SEvalZero *
440*10465441SEvalZero * The behavior of this function is altered according to the definitions of synchronized
441*10465441SEvalZero * I/O data integrity completion and synchronized I/O file integrity completion if
442*10465441SEvalZero * synchronized I/O is enabled on the file associated with aio_fildes.
443*10465441SEvalZero *
444*10465441SEvalZero * For regular files, no data transfer shall occur past the offset maximum established
445*10465441SEvalZero * in the open file description associated with aiocbp->aio_fildes.
446*10465441SEvalZero *
447*10465441SEvalZero * If sig->sigev_notify is SIGEV_THREAD and sig->sigev_notify_attributes is a
448*10465441SEvalZero * non-null pointer and the block pointed to by this pointer becomes an illegal
449*10465441SEvalZero * address prior to all asynchronous I/O being completed, then the behavior is
450*10465441SEvalZero * undefined.
451*10465441SEvalZero */
lio_listio(int mode,struct aiocb * const list[],int nent,struct sigevent * sig)452*10465441SEvalZero int lio_listio(int mode, struct aiocb * const list[], int nent,
453*10465441SEvalZero struct sigevent *sig)
454*10465441SEvalZero {
455*10465441SEvalZero return -ENOSYS;
456*10465441SEvalZero }
457*10465441SEvalZero
aio_system_init(void)458*10465441SEvalZero int aio_system_init(void)
459*10465441SEvalZero {
460*10465441SEvalZero aio_queue = rt_workqueue_create("aio", 2048, RT_THREAD_PRIORITY_MAX/2);
461*10465441SEvalZero RT_ASSERT(aio_queue != NULL);
462*10465441SEvalZero
463*10465441SEvalZero return 0;
464*10465441SEvalZero }
465*10465441SEvalZero INIT_COMPONENT_EXPORT(aio_system_init);
466