diff options
Diffstat (limited to 'rt')
-rw-r--r-- | rt/Makefile | 4 | ||||
-rw-r--r-- | rt/aio_misc.c | 26 | ||||
-rw-r--r-- | rt/aio_suspend.c | 53 | ||||
-rw-r--r-- | rt/lio_listio.c | 10 | ||||
-rw-r--r-- | rt/lio_listio64.c | 10 | ||||
-rw-r--r-- | rt/tst-aio.c | 142 |
6 files changed, 208 insertions, 37 deletions
diff --git a/rt/Makefile b/rt/Makefile index ef6e930..748050a 100644 --- a/rt/Makefile +++ b/rt/Makefile @@ -30,6 +30,8 @@ librt-routines := aio_cancel aio_error aio_fsync aio_misc aio_read \ librt-map := librt.map +tests := tst-aio + # Make sure that everything is distributed independent of configuration. distribute := aio_misc.h $(librt-routines:=.c) $(librt-map) @@ -48,3 +50,5 @@ include ../Rules # This ensures they will load libc.so for needed symbols if loaded by # a statically-linked program that hasn't already loaded it. $(objpfx)librt.so: $(common-objpfx)libc.so $(shared-thread-library) + +$(objpfx)tst-aio: $(objpfx)librt.so $(shared-thread-library) diff --git a/rt/aio_misc.c b/rt/aio_misc.c index 91c5544..030bef9 100644 --- a/rt/aio_misc.c +++ b/rt/aio_misc.c @@ -1,5 +1,5 @@ /* Handle general operations. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -27,7 +27,6 @@ #include "aio_misc.h" - /* Pool of request list entries. */ static struct requestlist **pool; @@ -273,7 +272,7 @@ __aio_enqueue_request (aiocb_union *aiocbp, int operation) /* The current file descriptor is worked on. It makes no sense to start another thread since this new thread would fight with the running thread for the resources. But we also cannot - say that the thread processing this desriptor shall imeediately + say that the thread processing this desriptor shall immediately after finishing the current job process this request if there are other threads in the running queue which have a higher priority. */ @@ -392,14 +391,18 @@ handle_fildes_io (void *arg) pthread_t self = pthread_self (); struct sched_param param; struct requestlist *runp = (struct requestlist *) arg; - aiocb_union *aiocbp = runp->aiocbp; + aiocb_union *aiocbp; int policy; - int fildes = runp->aiocbp->aiocb.aio_fildes; + int fildes; pthread_getschedparam (self, &policy, ¶m); do { + /* Update our variables. */ + aiocbp = runp->aiocbp; + fildes = aiocbp->aiocb.aio_fildes; + /* Change the priority to the requested value (if necessary). */ if (aiocbp->aiocb.__abs_prio != param.sched_priority || aiocbp->aiocb.__policy != policy) @@ -467,8 +470,8 @@ handle_fildes_io (void *arg) /* Now dequeue the current request. */ if (runp->next_prio == NULL) { - /* No outstanding request for this descriptor. Process the - runlist if necessary. */ + /* No outstanding request for this descriptor. Remove this + descriptor from the list. */ if (runp->next_fd != NULL) runp->next_fd->last_fd = runp->last_fd; if (runp->last_fd != NULL) @@ -488,15 +491,12 @@ handle_fildes_io (void *arg) /* Free the old element. */ __aio_free_request (runp); - runp = freelist; + runp = runlist; if (runp != NULL) { /* We must not run requests which are not marked `running'. */ if (runp->running == yes) - { - freelist = runp->next_run; - runp->running = allocated; - } + runlist = runp->next_run; else { struct requestlist *old; @@ -516,6 +516,8 @@ handle_fildes_io (void *arg) /* If no request to work on we will stop the thread. */ if (runp == NULL) --nthreads; + else + runp->running = allocated; /* Release the mutex. */ pthread_mutex_unlock (&__aio_requests_mutex); diff --git a/rt/aio_suspend.c b/rt/aio_suspend.c index 6123b7b..ca16342 100644 --- a/rt/aio_suspend.c +++ b/rt/aio_suspend.c @@ -1,5 +1,5 @@ /* Suspend until termination of a requests. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -40,40 +40,42 @@ aio_suspend (list, nent, timeout) int nent; const struct timespec *timeout; { - pthread_cond_t cond; struct waitlist waitlist[nent]; struct requestlist *requestlist[nent]; + pthread_cond_t cond; int cnt; int result = 0; + int dummy; + int none = 1; /* Request the mutex. */ pthread_mutex_lock (&__aio_requests_mutex); - /* First look whether there is already a terminated request. */ + /* 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) - break; + if (list[cnt] != NULL && list[cnt]->__error_code == EINPROGRESS) + { + requestlist[cnt] = __aio_find_req ((aiocb_union *) list[cnt]); + + if (requestlist[cnt] != NULL) + { + waitlist[cnt].cond = &cond; + waitlist[cnt].next = requestlist[cnt]->waiting; + waitlist[cnt].counterp = &dummy; + waitlist[cnt].sigevp = NULL; + requestlist[cnt]->waiting = &waitlist[cnt]; + none = 0; + } + } - if (cnt == nent) + /* If there is a not finished request wait for it. */ + if (!none) { int oldstate; - /* 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) - { - requestlist[cnt] = __aio_find_req ((aiocb_union *) list[cnt]); - - if (requestlist[cnt] != NULL) - { - waitlist[cnt].cond = &cond; - waitlist[cnt].next = requestlist[cnt]->waiting; - waitlist[cnt].counterp = NULL; - waitlist[cnt].sigevp = NULL; - requestlist[cnt]->waiting = &waitlist[cnt]; - } - } + /* Initialize the conditional variable. */ + pthread_cond_init (&cond, NULL); /* Since `pthread_cond_wait'/`pthread_cond_timedwait' are cancelation points we must be careful. We added entries to the waiting lists @@ -87,7 +89,7 @@ aio_suspend (list, nent, timeout) timeout); /* Now remove the entry in the waiting list for all requests - which didn't terminate */ + which didn't terminate. */ for (cnt = 0; cnt < nent; ++cnt) if (list[cnt] != NULL && list[cnt]->__error_code == EINPROGRESS && requestlist[cnt] != NULL) @@ -107,6 +109,11 @@ aio_suspend (list, nent, timeout) /* Now it's time to restore the cancelation state. */ pthread_setcancelstate (oldstate, NULL); + /* Release the conditional variable. */ + if (pthread_cond_destroy (&cond) != 0) + /* This must never happen. */ + abort (); + if (result != 0) { /* An error occurred. Possibly it's EINTR. We have to translate diff --git a/rt/lio_listio.c b/rt/lio_listio.c index b389c6a..07c8d3e 100644 --- a/rt/lio_listio.c +++ b/rt/lio_listio.c @@ -1,5 +1,5 @@ /* Enqueue and list of read or write requests. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -86,6 +86,9 @@ lio_listio (mode, list, nent, sig) struct waitlist waitlist[nent]; int oldstate; + /* Initialize the conditional variable. */ + pthread_cond_init (&cond, NULL); + total = 0; for (cnt = 0; cnt < nent; ++cnt) if (list[cnt] != NULL && list[cnt]->aio_lio_opcode != LIO_NOP @@ -110,6 +113,11 @@ lio_listio (mode, list, nent, sig) /* Now it's time to restore the cancelation state. */ pthread_setcancelstate (oldstate, NULL); + + /* Release the conditional variable. */ + if (pthread_cond_destroy (&cond) != 0) + /* This must never happen. */ + abort (); } else { diff --git a/rt/lio_listio64.c b/rt/lio_listio64.c index 19f56ad..69b78b7 100644 --- a/rt/lio_listio64.c +++ b/rt/lio_listio64.c @@ -1,5 +1,5 @@ /* Enqueue and list of read or write requests, 64bit offset version. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -86,6 +86,9 @@ lio_listio64 (mode, list, nent, sig) struct waitlist waitlist[nent]; int oldstate; + /* Initialize the conditional variable. */ + pthread_cond_init (&cond, NULL); + total = 0; for (cnt = 0; cnt < nent; ++cnt) if (list[cnt] != NULL && list[cnt]->aio_lio_opcode != LIO_NOP @@ -109,6 +112,11 @@ lio_listio64 (mode, list, nent, sig) /* Now it's time to restore the cancelation state. */ pthread_setcancelstate (oldstate, NULL); + + /* Release the conditional variable. */ + if (pthread_cond_destroy (&cond) != 0) + /* This must never happen. */ + abort (); } else { diff --git a/rt/tst-aio.c b/rt/tst-aio.c new file mode 100644 index 0000000..e319dea --- /dev/null +++ b/rt/tst-aio.c @@ -0,0 +1,142 @@ +/* Tests for AIO in librt. + Copyright (C) 1998 Free Software Foundation, Inc. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <aio.h> +#include <errno.h> +#include <error.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/stat.h> + + +/* prototype for our test function. */ +extern int do_test (int argc, char *argv[]); + + +/* We might need a bit longer timeout. */ +#define TIMEOUT 20 /* sec */ + +/* This defines the `main' function and some more. */ +#include <test-skeleton.c> + + +int +test_file (const void *buf, size_t size, int fd, const char *msg) +{ + struct stat st; + char tmp[size]; + + errno = 0; + if (fstat (fd, &st) < 0) + { + error (0, errno, "%s: failed stat", msg); + return 1; + } + + if (st.st_size != size) + { + error (0, errno, "%s: wrong size: %lu, should be %lu", + msg, (unsigned long int) st.st_size, (unsigned long int) size); + return 1; + } + + if (pread (fd, tmp, size, 0) != size) + { + error (0, errno, "%s: failed stat", msg); + return 1; + } + + if (memcmp (buf, tmp, size) != 0) + { + error (0, errno, "%s: failed comparison", msg); + return 1; + } + + if (ftruncate (fd, 0) < 0) + { + error (0, errno, "%s: failed truncate", msg); + return 1; + } + + return 0; +} + + +int +do_test (int argc, char *argv[]) +{ + char *name; + char name_len; + struct aiocb cbs[10]; + struct aiocb *cbp[10]; + char buf[1000]; + size_t cnt; + int fd; + int result = 0; + int go_on; + + name_len = strlen (test_dir); + name = malloc (name_len + sizeof ("/aioXXXXXX")); + mempcpy (mempcpy (name, test_dir, name_len), + "/aioXXXXXX", sizeof ("/aioXXXXXX")); + add_temp_file (name); + + /* Open our test file. */ + fd = mkstemp (name); + if (fd == -1) + error (EXIT_FAILURE, errno, "cannot open test file `%s'", name); + + /* Preparation. */ + for (cnt = 0; cnt < 10; ++cnt) + { + cbs[cnt].aio_fildes = fd; + cbs[cnt].aio_reqprio = 0; + cbs[cnt].aio_buf = memset (&buf[cnt * 100], '0' + cnt, 100); + cbs[cnt].aio_nbytes = 100; + cbs[cnt].aio_offset = cnt * 100; + cbs[cnt].aio_sigevent.sigev_notify = SIGEV_NONE; + + cbp[cnt] = &cbs[cnt]; + } + + /* First a simple test. */ + for (cnt = 10; cnt > 0; ) + aio_write (cbp[--cnt]); + /* Wait 'til the results are there. */ + do + { + aio_suspend ((const struct aiocb *const *) cbp, 10, NULL); + go_on = 0; + for (cnt = 0; cnt < 10; ++cnt) + if (cbp[cnt] != NULL && aio_error (cbp[cnt]) == EINPROGRESS) + go_on = 1; + else + { + if (cbp[cnt] != NULL) + printf ("request %d finished\n", cnt); + cbp[cnt] = NULL; + } + } + while (go_on); + /* Test this. */ + result |= test_file (buf, sizeof (buf), fd, "aio_write"); + + return result; +} |