diff --git a/posix-aio-compat.c b/posix-aio-compat.c index f141cd9e1a..154b05118a 100644 --- a/posix-aio-compat.c +++ b/posix-aio-compat.c @@ -15,6 +15,9 @@ #include #include #include +#include +#include +#include #include "osdep.h" #include "posix-aio-compat.h" @@ -27,20 +30,64 @@ static int cur_threads = 0; static int idle_threads = 0; static TAILQ_HEAD(, qemu_paiocb) request_list; +static void die2(int err, const char *what) +{ + fprintf(stderr, "%s failed: %s\n", what, strerror(err)); + abort(); +} + +static void die(const char *what) +{ + die2(errno, what); +} + +static void mutex_lock(pthread_mutex_t *mutex) +{ + int ret = pthread_mutex_lock(mutex); + if (ret) die2(ret, "pthread_mutex_lock"); +} + +static void mutex_unlock(pthread_mutex_t *mutex) +{ + int ret = pthread_mutex_unlock(mutex); + if (ret) die2(ret, "pthread_mutex_unlock"); +} + +static int cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, + struct timespec *ts) +{ + int ret = pthread_cond_timedwait(cond, mutex, ts); + if (ret && ret != ETIMEDOUT) die2(ret, "pthread_cond_timedwait"); + return ret; +} + +static void cond_broadcast(pthread_cond_t *cond) +{ + int ret = pthread_cond_broadcast(cond); + if (ret) die2(ret, "pthread_cond_broadcast"); +} + +static void thread_create(pthread_t *thread, pthread_attr_t *attr, + void *(*start_routine)(void*), void *arg) +{ + int ret = pthread_create(thread, attr, start_routine, arg); + if (ret) die2(ret, "pthread_create"); +} + static void *aio_thread(void *unused) { sigset_t set; /* block all signals */ - sigfillset(&set); - sigprocmask(SIG_BLOCK, &set, NULL); + if (sigfillset(&set)) die("sigfillset"); + if (sigprocmask(SIG_BLOCK, &set, NULL)) die("sigprocmask"); while (1) { struct qemu_paiocb *aiocb; size_t offset; int ret = 0; - pthread_mutex_lock(&lock); + mutex_lock(&lock); while (TAILQ_EMPTY(&request_list) && !(ret == ETIMEDOUT)) { @@ -49,7 +96,7 @@ static void *aio_thread(void *unused) qemu_gettimeofday(&tv); ts.tv_sec = tv.tv_sec + 10; - ret = pthread_cond_timedwait(&cond, &lock, &ts); + ret = cond_timedwait(&cond, &lock, &ts); } if (ret == ETIMEDOUT) @@ -62,7 +109,7 @@ static void *aio_thread(void *unused) aiocb->active = 1; idle_threads--; - pthread_mutex_unlock(&lock); + mutex_unlock(&lock); while (offset < aiocb->aio_nbytes) { ssize_t len; @@ -89,35 +136,36 @@ static void *aio_thread(void *unused) offset += len; } - pthread_mutex_lock(&lock); + mutex_lock(&lock); aiocb->ret = offset; idle_threads++; - pthread_mutex_unlock(&lock); + mutex_unlock(&lock); - kill(getpid(), aiocb->ev_signo); + if (kill(getpid(), aiocb->ev_signo)) die("kill failed"); } idle_threads--; cur_threads--; - pthread_mutex_unlock(&lock); + mutex_unlock(&lock); return NULL; } -static int spawn_thread(void) +static void spawn_thread(void) { - pthread_attr_t attr; int ret; + pthread_attr_t attr; cur_threads++; idle_threads++; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - ret = pthread_create(&thread_id, &attr, aio_thread, NULL); - pthread_attr_destroy(&attr); - - return ret; + ret = pthread_attr_init(&attr); + if (ret) die2 (ret, "pthread_attr_init"); + ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + if (ret) die2 (ret, "pthread_attr_setdetachstate"); + thread_create(&thread_id, &attr, aio_thread, NULL); + ret = pthread_attr_destroy(&attr); + if (ret) die2 (ret, "pthread_attr_destroy"); } int qemu_paio_init(struct qemu_paioinit *aioinit) @@ -132,12 +180,12 @@ static int qemu_paio_submit(struct qemu_paiocb *aiocb, int is_write) aiocb->is_write = is_write; aiocb->ret = -EINPROGRESS; aiocb->active = 0; - pthread_mutex_lock(&lock); + mutex_lock(&lock); if (idle_threads == 0 && cur_threads < max_threads) spawn_thread(); TAILQ_INSERT_TAIL(&request_list, aiocb, node); - pthread_mutex_unlock(&lock); - pthread_cond_broadcast(&cond); + mutex_unlock(&lock); + cond_broadcast(&cond); return 0; } @@ -156,9 +204,9 @@ ssize_t qemu_paio_return(struct qemu_paiocb *aiocb) { ssize_t ret; - pthread_mutex_lock(&lock); + mutex_lock(&lock); ret = aiocb->ret; - pthread_mutex_unlock(&lock); + mutex_unlock(&lock); return ret; } @@ -179,7 +227,7 @@ int qemu_paio_cancel(int fd, struct qemu_paiocb *aiocb) { int ret; - pthread_mutex_lock(&lock); + mutex_lock(&lock); if (!aiocb->active) { TAILQ_REMOVE(&request_list, aiocb, node); aiocb->ret = -ECANCELED; @@ -188,7 +236,7 @@ int qemu_paio_cancel(int fd, struct qemu_paiocb *aiocb) ret = QEMU_PAIO_NOTCANCELED; else ret = QEMU_PAIO_ALLDONE; - pthread_mutex_unlock(&lock); + mutex_unlock(&lock); return ret; }