* posix/include/aio.h: Add LIO_SYNC.
	* posix/include/rtems/posix/aio_misc.h: Add aio_request_queue,
	Cosmetics.
	* posix/src/aio_cancel.c, posix/src/aio_fsync.c, posix/src/aio_misc.c:
	Rework.
This commit is contained in:
Ralf Corsepius
2010-08-20 09:08:05 +00:00
parent b95e69d26c
commit a45e501813
6 changed files with 242 additions and 112 deletions

View File

@@ -1,3 +1,11 @@
2010-08-16 Alin Rus <alin.codejunkie@gmail.com>
* posix/include/aio.h: Add LIO_SYNC.
* posix/include/rtems/posix/aio_misc.h: Add aio_request_queue,
Cosmetics.
* posix/src/aio_cancel.c, posix/src/aio_fsync.c, posix/src/aio_misc.c:
Rework.
2010-08-19 Gedare Bloom <giddyup44@yahoo.com>
PR 1680/cpukit

View File

@@ -54,6 +54,7 @@ extern "C" {
#define LIO_READ 2 /* request a read() */
#define LIO_WRITE 3 /* request a write() */
#define LIO_NOP 4 /* no transfer is requested */
#define LIO_SYNC 5 /* needed by aio_fsync() */
/*
* 6.7.1.1 Asynchronous I/O Control Block, P1003.1b-1993, p. 151

View File

@@ -62,6 +62,8 @@ extern "C"
} rtems_aio_queue;
rtems_aio_queue aio_request_queue;
#define AIO_QUEUE_INITIALIZED 0xB00B
#ifndef AIO_MAX_THREADS
@@ -72,11 +74,17 @@ extern "C"
#define AIO_MAX_QUEUE_SIZE 30
#endif
extern int rtems_aio_init (void);
extern int rtems_aio_enqueue (rtems_aio_request * req);
extern rtems_aio_request_chain *rtems_aio_search_fd (rtems_chain_control *
chain, int fildes,
int create);
int rtems_aio_init (void);
int rtems_aio_enqueue (rtems_aio_request *req);
rtems_aio_request_chain *rtems_aio_search_fd
(
rtems_chain_control *chain,
int fildes,
int create
);
void rtems_aio_remove_fd (rtems_aio_request_chain *r_chain);
int rtems_aio_remove_req (rtems_chain_control *chain,
struct aiocb *aiocbp);
#ifdef RTEMS_DEBUG
#include <assert.h>

View File

@@ -1,14 +1,11 @@
/*
* 6.7.7 Cancel Asynchronous I/O Operation, P1003.1b-1993, p. 163
* Copyright 2010, Alin Rus <alin.codejunkie@gmail.com>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*
* COPYRIGHT (c) 1989-2007.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*
* $Id$
* $Id$
*/
#if HAVE_CONFIG_H
@@ -16,15 +13,112 @@
#endif
#include <aio.h>
#include <rtems/posix/aio_misc.h>
#include <errno.h>
#include <stdlib.h>
#include <rtems/system.h>
#include <rtems/seterr.h>
int aio_cancel(
int filedes __attribute__((unused)),
struct aiocb *aiocbp __attribute__((unused))
)
/*
* aio_cancel
*
* Cancel an asynchronous I/O request
*
* Input parameters:
* fildes - file descriptor
* aiocbp - asynchronous I/O control block
*
* Output parameters:
* AIO_CANCELED - if the requested operation(s)
* were canceled
* AIO_NOTCANCELED - if at least one of the requested
* operation(s) cannot be canceled
*/
int aio_cancel(int fildes, struct aiocb *aiocbp)
{
rtems_set_errno_and_return_minus_one( ENOSYS );
rtems_aio_request_chain *r_chain;
int result;
pthread_mutex_lock (&aio_request_queue.mutex);
if (aiocbp == NULL)
{
if (fcntl (fildes, F_GETFL) < 0)
rtems_set_errno_and_return_minus_one (EBADF);
r_chain = rtems_aio_search_fd (&aio_request_queue.work_req,
fildes,
0);
if (r_chain == NULL)
{
if (!rtems_chain_is_empty (&aio_request_queue.idle_req))
{
r_chain = rtems_aio_search_fd (&aio_request_queue.idle_req,
fildes,
0);
if (r_chain == NULL)
return AIO_ALLDONE;
rtems_chain_extract (&r_chain->next_fd);
rtems_aio_remove_fd (r_chain);
pthread_mutex_destroy (&r_chain->mutex);
pthread_cond_destroy (&r_chain->mutex);
free (r_chain);
pthread_mutex_unlock (&aio_request_queue.mutex);
return AIO_CANCELED;
}
pthread_mutex_unlock (&aio_request_queue.mutex);
return AIO_ALLDONE;
}
pthread_mutex_lock (&r_chain->mutex);
rtems_chain_extract (&r_chain->next_fd);
rtems_aio_remove_fd (r_chain);
pthread_mutex_unlock (&r_chain->mutex);
pthread_mutex_unlock (&aio_request_queue.mutex);
return AIO_CANCELED;
}
else
{
if (aiocbp->aio_fildes != fildes)
{
pthread_mutex_unlock (&aio_request_queue.mutex);
rtems_set_errno_and_return_minus_one (EINVAL);
}
r_chain = rtems_aio_search_fd (&aio_request_queue.work_req,
fildes,
0);
if (r_chain == NULL)
if (!rtems_chain_is_empty (&aio_request_queue.idle_req))
{
r_chain = rtems_aio_search_fd (&aio_request_queue.idle_req,
fildes,
0);
if (r_chain == NULL)
{
pthread_mutex_unlock (&aio_request_queue.mutex);
rtems_set_errno_and_return_minus_one (EINVAL);
}
result = rtems_aio_remove_req (&r_chain->next_fd, aiocbp);
pthread_mutex_unlock (&aio_request_queue.mutex);
return result;
}
pthread_mutex_lock (&r_chain->mutex);
result = rtems_aio_remove_req (&r_chain->next_fd, aiocbp);
pthread_mutex_unlock (&r_chain->mutex);
pthread_mutex_unlock (&aio_request_queue.mutex);
return result;
}
return AIO_ALLDONE;
}

View File

@@ -1,14 +1,11 @@
/*
* 6.7.9 Asynchronous File Synchronization, P1003.1b-1993, p. 166
* Copyright 2010, Alin Rus <alin.codejunkie@gmail.com>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*
* COPYRIGHT (c) 1989-2007.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*
* $Id$
* $Id$
*/
#if HAVE_CONFIG_H
@@ -17,14 +14,50 @@
#include <aio.h>
#include <errno.h>
#include <stdlib.h>
#include <rtems/posix/aio_misc.h>
#include <rtems/system.h>
#include <rtems/seterr.h>
/*
* aio_fsync
*
* Asynchronous file synchronization
*
* Input parameters:
* op - O_SYNC
* aiocbp - asynchronous I/O control block
*
* Output parameters:
* -1 - request could not pe enqueued
* - FD not opened for write
* - not enough memory
* - op is not O_SYNC
* 0 - otherwise
*/
int aio_fsync(
int op __attribute__((unused)),
struct aiocb *aiocbp __attribute__((unused))
int op,
struct aiocb *aiocbp
)
{
rtems_set_errno_and_return_minus_one( ENOSYS );
rtems_aio_request *req;
int mode;
if (op != O_SYNC)
rtems_aio_set_errno_return_minus_one (EINVAL, aiocbp);
mode = fcntl (aiocbp->aio_fildes, F_GETFL);
if (!(((mode & O_ACCMODE) == O_WRONLY) || ((mode & O_ACCMODE) == O_RDWR)))
rtems_aio_set_errno_return_minus_one (EBADF, aiocbp);
req = malloc (sizeof (rtems_aio_request));
if (req == NULL)
rtems_aio_set_errno_return_minus_one (EAGAIN, aiocbp);
req->aiocbp = aiocbp;
req->aiocbp->aio_lio_opcode = LIO_SYNC;
return rtems_aio_enqueue (req);
}

View File

@@ -10,13 +10,10 @@
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <rtems/posix/aio_misc.h>
rtems_aio_queue aio_request_queue;
static void *rtems_aio_handle (void *arg);
/*
@@ -90,7 +87,7 @@ rtems_aio_init (void)
*/
rtems_aio_request_chain *
rtems_aio_search_fd (rtems_chain_control * chain, int fildes, int create)
rtems_aio_search_fd (rtems_chain_control *chain, int fildes, int create)
{
rtems_aio_request_chain *r_chain;
rtems_chain_node *node;
@@ -138,7 +135,7 @@ rtems_aio_search_fd (rtems_chain_control * chain, int fildes, int create)
*/
void
rtems_aio_insert_prio (rtems_chain_control * chain, rtems_aio_request * req)
rtems_aio_insert_prio (rtems_chain_control *chain, rtems_aio_request *req)
{
rtems_chain_node *node;
@@ -248,7 +245,7 @@ int rtems_aio_remove_req (rtems_chain_control *chain, struct aiocb *aiocbp)
*/
int
rtems_aio_enqueue (rtems_aio_request * req)
rtems_aio_enqueue (rtems_aio_request *req)
{
rtems_aio_request_chain *r_chain;
@@ -266,9 +263,6 @@ rtems_aio_enqueue (rtems_aio_request * req)
return result;
}
/* used to check if we can create more threads */
int chain_type;
/* _POSIX_PRIORITIZED_IO and _POSIX_PRIORITY_SCHEDULING are defined,
we can use aio_reqprio to lower the priority of the request */
pthread_getschedparam (pthread_self(), &policy, &param);
@@ -279,81 +273,69 @@ rtems_aio_enqueue (rtems_aio_request * req)
req->aiocbp->error_code = EINPROGRESS;
req->aiocbp->return_value = 0;
if (AIO_MAX_THREADS >
(aio_request_queue.active_threads + aio_request_queue.idle_threads)) {
chain_type = 0;
chain = &aio_request_queue.work_req;
} else {
chain = &aio_request_queue.idle_req;
chain_type = 1;
}
/* we still have empty places on the active_threads chain */
if (chain_type == 0) {
r_chain = rtems_aio_search_fd (chain, req->aiocbp->aio_fildes, 1);
if (r_chain->new_fd == 1) {
rtems_chain_prepend (&r_chain->perfd, &req->next_prio);
r_chain->new_fd = 0;
pthread_mutex_init (&r_chain->mutex, NULL);
pthread_cond_init (&r_chain->cond, NULL);
/* if there are idle threads and this is a new fd chain
there's no need to create another thread */
if (aio_request_queue.idle_threads > 0) {
result = pthread_cond_signal (&aio_request_queue.new_req);
if (result != 0) {
pthread_mutex_unlock (&aio_request_queue.mutex);
return result;
}
} else {
/* if this is a new fd chain and no threads are idle create
new thread */
AIO_printf ("New thread");
result = pthread_create (&thid, &aio_request_queue.attr,
rtems_aio_handle, (void *) r_chain);
if (result != 0) {
pthread_mutex_unlock (&aio_request_queue.mutex);
return result;
}
++aio_request_queue.active_threads;
if ((aio_request_queue.idle_threads == 0) &&
aio_request_queue.active_threads < AIO_MAX_THREADS)
/* we still have empty places on the active_threads chain */
{
chain = &aio_request_queue.work_req;
r_chain = rtems_aio_search_fd (chain, req->aiocbp->aio_fildes, 1);
if (r_chain->new_fd == 1) {
rtems_chain_prepend (&r_chain->perfd, &req->next_prio);
r_chain->new_fd = 0;
pthread_mutex_init (&r_chain->mutex, NULL);
pthread_cond_init (&r_chain->cond, NULL);
AIO_printf ("New thread");
result = pthread_create (&thid, &aio_request_queue.attr,
rtems_aio_handle, (void *) r_chain);
if (result != 0) {
pthread_mutex_unlock (&aio_request_queue.mutex);
return result;
}
++aio_request_queue.active_threads;
}
} else {
/* put request in the fd chain it belongs to */
pthread_mutex_lock (&r_chain->mutex);
rtems_aio_insert_prio (&r_chain->perfd, req);
pthread_cond_signal (&r_chain->cond);
pthread_mutex_unlock (&r_chain->mutex);
}
} else {
/* the maximum number of threads has been already created
even though some of them might be idle.
The request belongs to one of the active fd chain */
r_chain = rtems_aio_search_fd (&aio_request_queue.work_req,
req->aiocbp->aio_fildes, 0);
if (r_chain != NULL)
{
else {
/* put request in the fd chain it belongs to */
pthread_mutex_lock (&r_chain->mutex);
rtems_aio_insert_prio (&r_chain->perfd, req);
pthread_cond_signal (&r_chain->cond);
pthread_mutex_unlock (&r_chain->mutex);
} else {
/* or to the idle chain */
r_chain = rtems_aio_search_fd (chain, req->aiocbp->aio_fildes, 1);
if (r_chain->new_fd == 1) {
/* If this is a new fd chain we signal the idle threads that
might be waiting for requests */
rtems_chain_prepend (&r_chain->perfd, &req->next_prio);
pthread_cond_signal (&aio_request_queue.new_req);
} else
/* just insert the request in the existing fd chain */
rtems_aio_insert_prio (&r_chain->perfd, req);
}
}
else
{
/* the maximum number of threads has been already created
even though some of them might be idle.
The request belongs to one of the active fd chain */
r_chain = rtems_aio_search_fd (&aio_request_queue.work_req,
req->aiocbp->aio_fildes, 0);
if (r_chain != NULL)
{
pthread_mutex_lock (&r_chain->mutex);
rtems_aio_insert_prio (&r_chain->perfd, req);
pthread_cond_signal (&r_chain->cond);
pthread_mutex_unlock (&r_chain->mutex);
} else {
/* or to the idle chain */
chain = &aio_request_queue.idle_req;
r_chain = rtems_aio_search_fd (chain, req->aiocbp->aio_fildes, 1);
if (r_chain->new_fd == 1) {
/* If this is a new fd chain we signal the idle threads that
might be waiting for requests */
rtems_chain_prepend (&r_chain->perfd, &req->next_prio);
r_chain->new_fd = 0;
pthread_mutex_init (&r_chain->mutex, NULL);
pthread_cond_init (&r_chain->cond, NULL);
pthread_cond_signal (&aio_request_queue.new_req);
} else
/* just insert the request in the existing fd chain */
rtems_aio_insert_prio (&r_chain->perfd, req);
}
}
}
pthread_mutex_unlock (&aio_request_queue.mutex);
return 0;
@@ -428,6 +410,10 @@ rtems_aio_handle (void *arg)
(void *) req->aiocbp->aio_buf,
req->aiocbp->aio_nbytes, req->aiocbp->aio_offset);
break;
case LIO_SYNC:
result = fsync (req->aiocbp->aio_fildes);
break;
default:
result = -1;