summaryrefslogtreecommitdiff
path: root/rtkaio/sysdeps/unix/sysv/linux/kaio_misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'rtkaio/sysdeps/unix/sysv/linux/kaio_misc.c')
-rw-r--r--rtkaio/sysdeps/unix/sysv/linux/kaio_misc.c90
1 files changed, 63 insertions, 27 deletions
diff --git a/rtkaio/sysdeps/unix/sysv/linux/kaio_misc.c b/rtkaio/sysdeps/unix/sysv/linux/kaio_misc.c
index 77c55b3e8b..76e0c430b7 100644
--- a/rtkaio/sysdeps/unix/sysv/linux/kaio_misc.c
+++ b/rtkaio/sysdeps/unix/sysv/linux/kaio_misc.c
@@ -1,5 +1,5 @@
/* Handle general operations.
- Copyright (C) 1997,1998,1999,2000,2001,2002,2003
+ Copyright (C) 1997,1998,1999,2000,2001,2002,2003,2006
Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
@@ -27,6 +27,7 @@
#include <aio.h>
#include <assert.h>
+#include <atomic.h>
#include <errno.h>
#include <limits.h>
#include <pthread.h>
@@ -34,6 +35,28 @@
#include <unistd.h>
#include <sys/stat.h>
#include <sys/time.h>
+#include <sys/sysmacros.h>
+
+#ifndef aio_create_helper_thread
+# define aio_create_helper_thread __aio_create_helper_thread
+
+extern inline int
+__aio_create_helper_thread (pthread_t *threadp, void *(*tf) (void *), void *arg)
+{
+ pthread_attr_t attr;
+
+ /* Make sure the thread is created detached. */
+ pthread_attr_init (&attr);
+ pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
+
+ int ret = pthread_create (threadp, &attr, tf, arg);
+
+ (void) pthread_attr_destroy (&attr);
+ return ret;
+}
+
+#endif
+
static void add_request_to_runlist (struct requestlist *newrequest)
internal_function;
@@ -359,14 +382,16 @@ static void
kernel_callback (kctx_t ctx, struct kiocb *kiocb, long res, long res2)
{
struct requestlist *req = (struct requestlist *)kiocb;
+ long errcode = 0;
- req->aiocbp->aiocb.__error_code = 0;
- req->aiocbp->aiocb.__return_value = res;
if (res < 0 && res > -1000)
{
- req->aiocbp->aiocb.__error_code = -res;
- req->aiocbp->aiocb.__return_value = -1;
+ errcode = -res;
+ res = -1;
}
+ req->aiocbp->aiocb.__return_value = res;
+ atomic_write_barrier ();
+ req->aiocbp->aiocb.__error_code = errcode;
__aio_notify (req);
assert (req->running == allocated);
req->running = done;
@@ -421,7 +446,7 @@ __aio_wait_for_events (kctx_t kctx, const struct timespec *timespec)
ts.tv_nsec = 0;
do
{
- ret = INTERNAL_SYSCALL (io_getevents, err, 5, kctx, 0, 10, ev,
+ ret = INTERNAL_SYSCALL (io_getevents, err, 5, kctx, 1, 10, ev,
timespec);
if (INTERNAL_SYSCALL_ERROR_P (ret, err) || ret == 0)
break;
@@ -453,16 +478,11 @@ internal_function
__aio_create_kernel_thread (void)
{
pthread_t thid;
- pthread_attr_t attr;
if (__kernel_thread_started)
return 0;
- /* Make sure the thread is created detached. */
- pthread_attr_init (&attr);
- pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
-
- if (pthread_create (&thid, &attr, handle_kernel_aio, NULL) != 0)
+ if (aio_create_helper_thread (&thid, handle_kernel_aio, NULL) != 0)
return -1;
__kernel_thread_started = 1;
return 0;
@@ -477,7 +497,7 @@ handle_kernel_aio (void *arg __attribute__((unused)))
for (;;)
{
- ret = INTERNAL_SYSCALL (io_getevents, err, 5, __aio_kioctx, 0, 10, ev,
+ ret = INTERNAL_SYSCALL (io_getevents, err, 5, __aio_kioctx, 1, 10, ev,
NULL);
if (INTERNAL_SYSCALL_ERROR_P (ret, err) || ret == 0)
continue;
@@ -593,16 +613,11 @@ __aio_enqueue_user_request (struct requestlist *newp)
if (nthreads < optim.aio_threads && idle_thread_count == 0)
{
pthread_t thid;
- pthread_attr_t attr;
-
- /* Make sure the thread is created detached. */
- pthread_attr_init (&attr);
- pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
running = newp->running = allocated;
/* Now try to start a thread. */
- if (pthread_create (&thid, &attr, handle_fildes_io, newp) == 0)
+ if (aio_create_helper_thread (&thid, handle_fildes_io, newp) == 0)
/* We managed to enqueue the request. All errors which can
happen now can be recognized by calls to `aio_return' and
`aio_error'. */
@@ -653,6 +668,7 @@ __aio_enqueue_request_ctx (aiocb_union *aiocbp, int operation, kctx_t kctx)
aiocbp->aiocb.aio_reqprio = 0;
/* FIXME: Kernel doesn't support sync yet. */
operation &= ~LIO_KTHREAD;
+ kctx = KCTX_NONE;
}
else if (aiocbp->aiocb.aio_reqprio < 0
|| aiocbp->aiocb.aio_reqprio > AIO_PRIO_DELTA_MAX)
@@ -664,6 +680,23 @@ __aio_enqueue_request_ctx (aiocb_union *aiocbp, int operation, kctx_t kctx)
return NULL;
}
+ if ((operation & LIO_KTHREAD) || kctx != KCTX_NONE)
+ {
+ /* io_* is only really asynchronous for O_DIRECT or /dev/raw*. */
+ int fl = __fcntl (aiocbp->aiocb.aio_fildes, F_GETFL);
+ if (fl < 0 || (fl & O_DIRECT) == 0)
+ {
+ struct stat64 st;
+ if (__fxstat64 (_STAT_VER, aiocbp->aiocb.aio_fildes, &st) < 0
+ || ! S_ISCHR (st.st_mode)
+ || major (st.st_rdev) != 162)
+ {
+ operation &= ~LIO_KTHREAD;
+ kctx = KCTX_NONE;
+ }
+ }
+ }
+
/* Compute priority for this request. */
pthread_getschedparam (pthread_self (), &policy, &param);
prio = param.sched_priority - aiocbp->aiocb.aio_reqprio;
@@ -799,7 +832,9 @@ wait_for_kernel_requests (int fildes)
return -1;
}
+#ifndef DONT_NEED_AIO_MISC_COND
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+#endif
struct waitlist waitlist[nent];
int cnt = 0;
@@ -807,7 +842,10 @@ wait_for_kernel_requests (int fildes)
{
if (kreq->running == allocated)
{
+#ifndef DONT_NEED_AIO_MISC_COND
waitlist[cnt].cond = &cond;
+#endif
+ waitlist[cnt].result = NULL;
waitlist[cnt].next = kreq->waiting;
waitlist[cnt].counterp = &nent;
waitlist[cnt].sigevp = NULL;
@@ -819,11 +857,15 @@ wait_for_kernel_requests (int fildes)
kreq = kreq->next_prio;
}
+#ifdef DONT_NEED_AIO_MISC_COND
+ AIO_MISC_WAIT (ret, nent, NULL, 0);
+#else
do
pthread_cond_wait (&cond, &__aio_requests_mutex);
while (nent);
pthread_cond_destroy (&cond);
+#endif
}
pthread_mutex_unlock (&__aio_requests_mutex);
@@ -832,7 +874,6 @@ wait_for_kernel_requests (int fildes)
static void *
-__attribute__ ((noreturn))
handle_fildes_io (void *arg)
{
pthread_t self = pthread_self ();
@@ -1026,16 +1067,11 @@ handle_fildes_io (void *arg)
else if (nthreads < optim.aio_threads)
{
pthread_t thid;
- pthread_attr_t attr;
-
- /* Make sure the thread is created detached. */
- pthread_attr_init (&attr);
- pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
/* Now try to start a thread. If we fail, no big deal,
because we know that there is at least one thread (us)
that is working on AIO operations. */
- if (pthread_create (&thid, &attr, handle_fildes_io, NULL)
+ if (aio_create_helper_thread (&thid, handle_fildes_io, NULL)
== 0)
++nthreads;
}
@@ -1047,7 +1083,7 @@ handle_fildes_io (void *arg)
}
while (runp != NULL);
- pthread_exit (NULL);
+ return NULL;
}