forked from Imagelibrary/rtems
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.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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, ¶m);
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user