This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
[patch] aio_*() posix compliance
- From: Amos Waterland <apw at us dot ibm dot com>
- To: libc-alpha at sources dot redhat dot com
- Date: Mon, 17 Jun 2002 12:38:35 -0500
- Subject: [patch] aio_*() posix compliance
I have converted the code to the GNU coding standards, removed checks
for null pointers, and removed checks for problems that the standard
allows to be detected asynchronously. I grouped the remaining changes
into a single patch, which does the following.
aio_cancel()
- detect bad file descriptor
aio_error()
- no changes
aio_fsync()
- detect bad file descriptor
- detect fd not open for writing
aio_read()
- no changes
aio_return()
- no changes
aio_suspend()
- detect completed element(s) and do not suspend thread
aio_write()
- no changes
lio_listio()
- no changes (see comment below)
I believe that glibc with this patch is fully compliant, with the
possible exception of this issue: the standard says for lio_listio()
(http://www.opengroup.org/onlinepubs/007904975/functions/lio_listio.html):
The lio_listio() function shall fail if:
[EAGAIN] The number of entries indicated by nent would cause the
system-wide limit {AIO_MAX} to be exceeded.
[EINVAL] The mode argument is not a proper value, or the value of
nent was greater than {AIO_LISTIO_MAX}.
Glibc does not seem to define AIO_MAX and AIO_LISTIO_MAX, and because of
the way sysconf() conditionally compiles, it returns -1 for both (see
below for test0024.c):
% ./test0024
+ _POSIX_ASYNCHRONOUS_IO
+ _POSIX_ASYNC_IO
- AIO_LISTIO_MAX
- AIO_MAX
(-1) _SC_AIO_LISTIO_MAX
(-1) _SC_AIO_MAX
The lio_listio() function does not check for nent exceeding the
constants of concern. I know that there might be a simple answer to
this, so I wanted to ask you all about it before I added definitions to
unistd.h and patched lio_listio.c.
Here is the patch.
---- Begin patch ----
Index: sysdeps/pthread/aio_cancel.c
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/pthread/aio_cancel.c,v
retrieving revision 1.2
diff -u -r1.2 aio_cancel.c
--- sysdeps/pthread/aio_cancel.c 6 Jul 2001 04:56:02 -0000 1.2
+++ sysdeps/pthread/aio_cancel.c 16 Jun 2002 01:16:34 -0000
@@ -43,6 +43,13 @@
struct requestlist *req = NULL;
int result = AIO_ALLDONE;
+ /* If fildes is invalid, error. */
+ if (fcntl (fildes, F_GETFL) < 0)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+
/* Request the mutex. */
pthread_mutex_lock (&__aio_requests_mutex);
Index: sysdeps/pthread/aio_fsync.c
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/pthread/aio_fsync.c,v
retrieving revision 1.2
diff -u -r1.2 aio_fsync.c
--- sysdeps/pthread/aio_fsync.c 6 Jul 2001 04:56:02 -0000 1.2
+++ sysdeps/pthread/aio_fsync.c 16 Jun 2002 01:16:34 -0000
@@ -36,15 +36,23 @@
int
aio_fsync (int op, struct aiocb *aiocbp)
{
- if (op != O_DSYNC && op != O_SYNC)
+ int flags;
+
+ if ((flags = fcntl (aiocbp->aio_fildes, F_GETFL)) >= 0
+ && (flags & (O_RDWR | O_WRONLY)))
{
- __set_errno (EINVAL);
- return -1;
+ if (op != O_DSYNC && op != O_SYNC)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ return (__aio_enqueue_request ((aiocb_union *) aiocbp,
+ op == O_SYNC ? LIO_SYNC : LIO_DSYNC) == NULL ? -1 : 0);
}
- return (__aio_enqueue_request ((aiocb_union *) aiocbp,
- op == O_SYNC ? LIO_SYNC : LIO_DSYNC) == NULL
- ? -1 : 0);
+ __set_errno (EBADF);
+ return -1;
}
weak_alias (aio_fsync, aio_fsync64)
Index: sysdeps/pthread/aio_suspend.c
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/pthread/aio_suspend.c,v
retrieving revision 1.2
diff -u -r1.2 aio_suspend.c
--- sysdeps/pthread/aio_suspend.c 6 Jul 2001 04:56:02 -0000 1.2
+++ sysdeps/pthread/aio_suspend.c 16 Jun 2002 01:16:34 -0000
@@ -49,6 +49,7 @@
int result = 0;
int dummy;
int none = 1;
+ int do_not_suspend = 0;
/* Request the mutex. */
pthread_mutex_lock (&__aio_requests_mutex);
@@ -56,8 +57,15 @@
/* There is not yet a finished request. Signal the request that
we are working for it. */
for (cnt = 0; cnt < nent; ++cnt)
- if (list[cnt] != NULL && list[cnt]->__error_code == EINPROGRESS)
+ if (list[cnt] != NULL)
{
+ /* This element has already completed, so we must not suspend thread. */
+ if (list[cnt]->__error_code != EINPROGRESS)
+ {
+ do_not_suspend = 1;
+ continue;
+ }
+
requestlist[cnt] = __aio_find_req ((aiocb_union *) list[cnt]);
if (requestlist[cnt] != NULL)
@@ -83,7 +91,10 @@
pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &oldstate);
if (timeout == NULL)
- result = pthread_cond_wait (&cond, &__aio_requests_mutex);
+ if (do_not_suspend)
+ result = 0;
+ else
+ result = pthread_cond_wait (&cond, &__aio_requests_mutex);
else
{
/* We have to convert the relative timeout value into an
@@ -100,8 +111,11 @@
abstime.tv_sec += 1;
}
- result = pthread_cond_timedwait (&cond, &__aio_requests_mutex,
- &abstime);
+ if (do_not_suspend)
+ result = 0;
+ else
+ result = pthread_cond_timedwait (&cond, &__aio_requests_mutex,
+ &abstime);
}
/* Now remove the entry in the waiting list for all requests
---- End patch ----
---- Begin test0024.c ----
/* Check some AIO options.
* Amos Waterland <apw@us.ibm.com>
* 13 June 02
*/
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <unistd.h>
int main( int argc, char *argv[] )
{
#ifdef _POSIX_ASYNCHRONOUS_IO
printf( "+ _POSIX_ASYNCHRONOUS_IO\n" );
#else
printf( "- _POSIX_ASYNCHRONOUS_IO\n" );
#endif
#ifdef _POSIX_ASYNC_IO
printf( "+ _POSIX_ASYNC_IO\n" );
#else
printf( "- _POSIX_ASYNC_IO\n" );
#endif
#ifdef AIO_LISTIO_MAX
printf( "+ AIO_LISTIO_MAX\n" );
#else
printf( "- AIO_LISTIO_MAX\n" );
#endif
#ifdef AIO_MAX
printf( "+ AIO_MAX\n" );
#else
printf( "- AIO_MAX\n" );
#endif
printf( "(%li) _SC_AIO_LISTIO_MAX\n", sysconf( _SC_AIO_LISTIO_MAX ) );
printf( "(%li) _SC_AIO_MAX\n", sysconf( _SC_AIO_MAX ) );
return 0;
}
---- End test0024.c ----