* blocked permanently.
*/
-struct aio_args {
- struct aiocb *cb;
- int op;
- int err;
- sem_t sem;
-};
-
struct aio_thread {
pthread_t td;
struct aiocb *cb;
struct aio_thread *head;
};
+struct aio_args {
+ struct aiocb *cb;
+ struct aio_queue *q;
+ int op;
+ sem_t sem;
+};
+
static pthread_rwlock_t maplock = PTHREAD_RWLOCK_INITIALIZER;
static struct aio_queue *****map;
static volatile int aio_fd_cnt;
static struct aio_queue *__aio_get_queue(int fd, int need)
{
- if (fd < 0) return 0;
+ if (fd < 0) {
+ errno = EBADF;
+ return 0;
+ }
int a=fd>>24;
unsigned char b=fd>>16, c=fd>>8, d=fd;
struct aio_queue *q = 0;
pthread_rwlock_rdlock(&maplock);
if ((!map || !map[a] || !map[a][b] || !map[a][b][c] || !(q=map[a][b][c][d])) && need) {
pthread_rwlock_unlock(&maplock);
+ if (fcntl(fd, F_GETFD) < 0) return 0;
pthread_rwlock_wrlock(&maplock);
if (!map) map = calloc(sizeof *map, (-1U/2+1)>>24);
if (!map) goto out;
size_t len = cb->aio_nbytes;
off_t off = cb->aio_offset;
- struct aio_queue *q = __aio_get_queue(fd, 1);
+ struct aio_queue *q = args->q;
ssize_t ret;
- args->err = q ? 0 : EAGAIN;
+ pthread_mutex_lock(&q->lock);
sem_post(&args->sem);
- if (!q) return 0;
at.op = op;
at.running = 1;
at.prev = 0;
if ((at.next = q->head)) at.next->prev = &at;
q->head = &at;
- q->ref++;
if (!q->init) {
int seekable = lseek(fd, 0, SEEK_CUR) >= 0;
pthread_attr_t a;
sigset_t allmask, origmask;
pthread_t td;
- struct aio_args args = { .cb = cb, .op = op };
+ struct aio_queue *q = __aio_get_queue(cb->aio_fildes, 1);
+ struct aio_args args = { .cb = cb, .op = op, .q = q };
sem_init(&args.sem, 0, 0);
+ if (!q) {
+ if (errno != EBADF) errno = EAGAIN;
+ cb->__ret = -1;
+ cb->__err = errno;
+ return -1;
+ }
+ q->ref++;
+ pthread_mutex_unlock(&q->lock);
+
if (cb->aio_sigevent.sigev_notify == SIGEV_THREAD) {
if (cb->aio_sigevent.sigev_notify_attributes)
a = *cb->aio_sigevent.sigev_notify_attributes;
pthread_sigmask(SIG_BLOCK, &allmask, &origmask);
cb->__err = EINPROGRESS;
if (pthread_create(&td, &a, io_thread_func, &args)) {
- errno = EAGAIN;
- ret = -1;
+ pthread_mutex_lock(&q->lock);
+ __aio_unref_queue(q);
+ cb->__err = errno = EAGAIN;
+ cb->__ret = ret = -1;
}
pthread_sigmask(SIG_SETMASK, &origmask, 0);
if (!ret) {
while (sem_wait(&args.sem));
- if (args.err) {
- errno = args.err;
- ret = -1;
- }
}
return ret;
sigfillset(&allmask);
pthread_sigmask(SIG_BLOCK, &allmask, &origmask);
+ errno = ENOENT;
if (!(q = __aio_get_queue(fd, 0))) {
- if (fcntl(fd, F_GETFD) < 0) ret = -1;
+ if (errno == EBADF) ret = -1;
goto done;
}