Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:21

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup POSIXAPI
0007  *
0008  * @brief Function Initiates a List of I/O Requests with Single Function Call 
0009  */
0010 
0011 /*
0012  *  6.7.4 List Directed I/O, P1003.1b-1993, p. 158
0013  *
0014  *  COPYRIGHT (c) 1989-2007.
0015  *  On-Line Applications Research Corporation (OAR).
0016  *
0017  * Redistribution and use in source and binary forms, with or without
0018  * modification, are permitted provided that the following conditions
0019  * are met:
0020  * 1. Redistributions of source code must retain the above copyright
0021  *    notice, this list of conditions and the following disclaimer.
0022  * 2. Redistributions in binary form must reproduce the above copyright
0023  *    notice, this list of conditions and the following disclaimer in the
0024  *    documentation and/or other materials provided with the distribution.
0025  *
0026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0027  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0028  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0029  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0030  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0031  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0032  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0033  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0034  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0035  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0036  * POSSIBILITY OF SUCH DAMAGE.
0037  */
0038 
0039 #ifdef HAVE_CONFIG_H
0040 #include "config.h"
0041 #endif
0042 
0043 #include <aio.h>
0044 #include <errno.h>
0045 #include <fcntl.h>
0046 #include <rtems/posix/aio_misc.h>
0047 #include <rtems/seterr.h>
0048 #include <stdlib.h>
0049 #include <pthread.h>
0050 #include <rtems/score/basedefs.h>
0051 #include <rtems/seterr.h>
0052 
0053 int lio_listio(
0054   int              mode,
0055   struct aiocb    *__restrict const  list[__restrict],
0056   int              nent,
0057   struct sigevent *__restrict sig
0058 )
0059 {
0060 #ifdef RTEMS_POSIX_API 
0061   int result, error;
0062   listcb *listcbp;
0063   rtems_aio_request *req;
0064 
0065   /* Errors on parameters */
0066   if ( list == NULL ) {
0067     rtems_set_errno_and_return_minus_one( EINVAL );
0068   }
0069 
0070   if ( mode != LIO_WAIT && mode != LIO_NOWAIT ) {
0071     rtems_set_errno_and_return_minus_one( EINVAL );
0072   }
0073 
0074   if ( nent < 1 || nent > AIO_LISTIO_MAX ) {
0075     rtems_set_errno_and_return_minus_one( EINVAL );
0076   }
0077 
0078   if ( nent + atomic_load( &aio_request_queue.queued_requests ) > RTEMS_AIO_MAX ) {
0079     rtems_set_errno_and_return_minus_one( EINVAL );
0080   }
0081 
0082   /* Initialize list control block */
0083   listcbp = malloc( sizeof( listcb ) );
0084   if ( listcbp == NULL ) {
0085     rtems_set_errno_and_return_minus_one( EAGAIN );
0086   }
0087 
0088   result = pthread_mutex_init( &listcbp->mutex, NULL );
0089   if ( result != 0 ) {
0090     free( listcbp );
0091     rtems_set_errno_and_return_minus_one( EAGAIN );
0092   }
0093 
0094   listcbp->requests_left = 1;
0095 
0096   /* Set up notification for list completion (wait or no wait) */
0097   if ( mode == LIO_WAIT ) {
0098     listcbp->notification_type = AIO_LIO_EVENT;
0099     listcbp->lio_notification.task_id = rtems_task_self();
0100 
0101   } else if ( mode == LIO_NOWAIT ) {
0102 
0103     if ( sig == NULL ) {
0104       listcbp->notification_type = AIO_LIO_NO_NOTIFY;
0105     } else {
0106       if ( rtems_aio_check_sigevent( sig ) == 0 ) {
0107         free( listcbp );
0108         rtems_set_errno_and_return_minus_one( EINVAL );
0109       }
0110 
0111       listcbp->notification_type = AIO_LIO_SIGEV;
0112       listcbp->lio_notification.sigp = sig;
0113     }
0114   }
0115   
0116   /* Initialize and enqueue each request */
0117   error = 0;
0118 
0119   for( int i = 0; i < nent; i++ ) { 
0120     if ( list[i] == NULL ) {
0121       continue;
0122     }
0123 
0124     switch ( list[i]->aio_lio_opcode ) {
0125       case LIO_READ:
0126         req = init_read_req( list[i] );
0127         if ( req == NULL ) {
0128           error = 1;
0129           list[i]->return_value = -1;
0130           list[i]->error_code = errno;
0131           list[i]->return_status = AIO_NOTRETURNED;
0132           break;
0133         }
0134 
0135         req->listcbp = listcbp;
0136         result = rtems_aio_enqueue( req );
0137         if ( result != 0 ) {
0138           error = 1;
0139           list[i]->return_value = -1;
0140           list[i]->error_code = EAGAIN;
0141           list[i]->return_status = AIO_NOTRETURNED;
0142           break;
0143         }
0144 
0145         listcbp->requests_left++;
0146         break;
0147 
0148       case LIO_WRITE:
0149         req = init_write_req( list[i] );
0150         if ( req == NULL ) {
0151           error = 1;
0152           list[i]->error_code = errno;
0153           list[i]->return_value = -1;
0154           list[i]->return_status = AIO_NOTRETURNED;
0155           break;
0156         }
0157         
0158         req->listcbp = listcbp;
0159         result = rtems_aio_enqueue( req );
0160         if ( result != 0 ) {
0161           error = 1;
0162           list[i]->return_value = -1;
0163           list[i]->error_code = EAGAIN;
0164           list[i]->return_status = AIO_NOTRETURNED;
0165           break;
0166         }
0167 
0168         listcbp->requests_left++;
0169         break;
0170     }
0171   }
0172   rtems_aio_completed_list_op( listcbp );
0173 
0174   if ( mode == LIO_NOWAIT ) {
0175     if ( error == 1 ) {
0176       rtems_set_errno_and_return_minus_one( EIO ); 
0177     }
0178   } else if ( mode == LIO_WAIT ) {
0179     rtems_event_set event_out; 
0180     rtems_event_system_receive(
0181       RTEMS_EVENT_SYSTEM_LIO_LIST_COMPLETED,
0182       RTEMS_DEFAULT_OPTIONS,
0183       RTEMS_NO_TIMEOUT,
0184       &event_out
0185     );
0186 
0187     for ( int i = 0; i < nent; i++ ) { 
0188       if ( list[i] != NULL ) {
0189         if (
0190           list[i]->aio_lio_opcode == LIO_READ ||
0191           list[i]->aio_lio_opcode == LIO_WRITE 
0192         ) {
0193           switch ( list[i]->error_code ) {
0194             case 0:
0195               break;
0196             case EINPROGRESS:
0197               rtems_set_errno_and_return_minus_one( EINTR );
0198               break;
0199             default:
0200               rtems_set_errno_and_return_minus_one( EIO );
0201           }
0202         }
0203       }
0204     }
0205   }
0206 
0207   return 0;
0208 #else
0209   rtems_set_errno_and_return_minus_one( ENOSYS );
0210 #endif
0211 }
0212