From a45e501813f1a3f81212d2705da05ed41776e52c Mon Sep 17 00:00:00 2001 From: Ralf Corsepius Date: Fri, 20 Aug 2010 09:08:05 +0000 Subject: 2010-08-16 Alin Rus * 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. --- cpukit/ChangeLog | 8 ++ cpukit/posix/include/aio.h | 1 + cpukit/posix/include/rtems/posix/aio_misc.h | 18 +++- cpukit/posix/src/aio_cancel.c | 124 +++++++++++++++++++++--- cpukit/posix/src/aio_fsync.c | 59 +++++++++--- cpukit/posix/src/aio_misc.c | 140 +++++++++++++--------------- 6 files changed, 240 insertions(+), 110 deletions(-) diff --git a/cpukit/ChangeLog b/cpukit/ChangeLog index 2def407921..de9c43380a 100644 --- a/cpukit/ChangeLog +++ b/cpukit/ChangeLog @@ -1,3 +1,11 @@ +2010-08-16 Alin Rus + + * 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 PR 1680/cpukit diff --git a/cpukit/posix/include/aio.h b/cpukit/posix/include/aio.h index bc74126287..2700dac19e 100644 --- a/cpukit/posix/include/aio.h +++ b/cpukit/posix/include/aio.h @@ -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 diff --git a/cpukit/posix/include/rtems/posix/aio_misc.h b/cpukit/posix/include/rtems/posix/aio_misc.h index 7d2d1294bd..095d507a1c 100644 --- a/cpukit/posix/include/rtems/posix/aio_misc.h +++ b/cpukit/posix/include/rtems/posix/aio_misc.h @@ -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 diff --git a/cpukit/posix/src/aio_cancel.c b/cpukit/posix/src/aio_cancel.c index b4e589d8ff..d9a982cf31 100644 --- a/cpukit/posix/src/aio_cancel.c +++ b/cpukit/posix/src/aio_cancel.c @@ -1,14 +1,11 @@ /* - * 6.7.7 Cancel Asynchronous I/O Operation, P1003.1b-1993, p. 163 + * Copyright 2010, Alin Rus + * + * 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 +#include #include - +#include #include #include -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; + } diff --git a/cpukit/posix/src/aio_fsync.c b/cpukit/posix/src/aio_fsync.c index 0aca7ad9bd..4a28b194b5 100644 --- a/cpukit/posix/src/aio_fsync.c +++ b/cpukit/posix/src/aio_fsync.c @@ -1,14 +1,11 @@ /* - * 6.7.9 Asynchronous File Synchronization, P1003.1b-1993, p. 166 + * Copyright 2010, Alin Rus + * + * 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 #include - +#include +#include #include #include +/* + * 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); + } diff --git a/cpukit/posix/src/aio_misc.c b/cpukit/posix/src/aio_misc.c index f21b8883d5..52f732f287 100644 --- a/cpukit/posix/src/aio_misc.c +++ b/cpukit/posix/src/aio_misc.c @@ -10,13 +10,10 @@ #include #include +#include #include #include - - -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 + { + /* 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 { - } else { - - /* or to the idle chain */ - r_chain = rtems_aio_search_fd (chain, req->aiocbp->aio_fildes, 1); + /* 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); - 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); + 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; -- cgit v1.2.3