diff options
author | William R. Otte <wotte@dre.vanderbilt.edu> | 2008-03-04 14:51:23 +0000 |
---|---|---|
committer | William R. Otte <wotte@dre.vanderbilt.edu> | 2008-03-04 14:51:23 +0000 |
commit | e60d54b4b03648afbb79382a1157238d4ffcc330 (patch) | |
tree | bda96bf8c3a4c2875a083d7b16720533c8ffeaf4 /ACE/m4/aio.m4 | |
parent | dab6095386e31ea8302e88bb53b4735c6304e8c5 (diff) | |
download | ATCD-e60d54b4b03648afbb79382a1157238d4ffcc330.tar.gz |
undoing accidental deletion
Diffstat (limited to 'ACE/m4/aio.m4')
-rw-r--r-- | ACE/m4/aio.m4 | 633 |
1 files changed, 633 insertions, 0 deletions
diff --git a/ACE/m4/aio.m4 b/ACE/m4/aio.m4 new file mode 100644 index 00000000000..aaa5622dd33 --- /dev/null +++ b/ACE/m4/aio.m4 @@ -0,0 +1,633 @@ +dnl ------------------------------------------------------------------------- +dnl $Id$ +dnl +dnl aio.m4 +dnl +dnl ACE M4 include file which contains ACE specific M4 macros +dnl that determine availablility of POSIX asynchronous IO +dnl support. +dnl +dnl ------------------------------------------------------------------------- + +dnl Copyright (C) 1998, 1999, 2002 Ossama Othman +dnl +dnl All Rights Reserved +dnl +dnl This library is free software; you can redistribute it and/or +dnl modify it under the current ACE distribution terms. +dnl +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +dnl Asynchronous IO check +dnl Use this macro to determine if asynchronous IO is working on a +dnl given platform. +dnl Usage: ACE_CHECK_ASYNCH_IO +AC_DEFUN([ACE_CHECK_ASYNCH_IO], +[ + AC_REQUIRE([AC_PROG_CXX]) + AC_REQUIRE([AC_PROG_CXXCPP]) + AC_LANG([C++]) + AC_REQUIRE([AC_LANG]) + AC_REQUIRE([ACE_CHECK_THREADS]) + + dnl In case a library with the asynchronous libraries is found but + dnl the asynchronous IO support is not functional then save a copy + dnl of the list of libraries before the asynch IO function library + dnl is added to the list so that we can revert the list to its + dnl pre-asynch-IO check state. + ace_save_LIBS="$LIBS" + + dnl Asynchronous IO library check + dnl Some platforms, such as Solaris puts aio_read in -lposix4, for example. + dnl In some cases, the thread library must be linked to in addition to the + dnl real-time support library. As such, make sure these checks are done + dnl after the thread library checks. + AC_SEARCH_LIBS([aio_read], [aio rt posix4], + [ace_has_aio_funcs=yes], [ace_has_aio_funcs=no]) + +if test "$ace_has_aio_funcs" = yes; then + ACE_CACHE_CHECK([for working asynchronous IO], + [ace_cv_feature_aio_calls], + [ + AC_RUN_IFELSE([AC_LANG_SOURCE([[ +#ifndef ACE_LACKS_UNISTD_H +#include <unistd.h> +#endif +#include <fcntl.h> +#ifndef ACE_LACKS_SYS_TYPES_H +# include <sys/types.h> +#endif +#include <sys/stat.h> +#include <signal.h> +#include <string.h> +#include <errno.h> +#include <stdio.h> +#include <iostream.h> + +#include <aio.h> + +class Test_Aio +{ +public: + Test_Aio (void); + // Default constructor. + + int init (void); + // Initting the output file and the buffer. + + int do_aio (void); + // Doing the testing stuff. + + ~Test_Aio (void); + // Destructor. +private: + int out_fd_; + // Output file descriptor. + + struct aiocb *aiocb_write_; + // For writing to the file. + + struct aiocb *aiocb_read_; + // Reading stuff from the file. + + char *buffer_write_; + // The buffer to be written to the out_fd. + + char *buffer_read_; + // The buffer to be read back from the file. +}; + +Test_Aio::Test_Aio (void) + : out_fd_ (0), + aiocb_write_ (new struct aiocb), + aiocb_read_ (new struct aiocb), + buffer_write_ (0), + buffer_read_ (0) +{ +} + +Test_Aio::~Test_Aio (void) +{ + if (close (this->out_fd_) != 0) + perror ("close"); + + delete aiocb_write_; + delete aiocb_read_; + delete [] buffer_write_; + delete [] buffer_read_; +} + +// Init the output file and init the buffer. +int +Test_Aio::init (void) +{ + // Open the output file. + this->out_fd_ = open ("test_aio.log", O_RDWR | O_CREAT | O_TRUNC, 0600); + if (this->out_fd_ == -1) + { + perror ("open"); + return -1; + } + + unlink ("test_aio.log"); // Unlink now so we don't have to do so later. + + const char message[] = "Welcome to the world of AIO... AIO Rules !!!"; + + // Init the buffers. + this->buffer_write_ = new char [sizeof (message) + 1]; + strcpy (this->buffer_write_, message); + // cout << "The buffer : " << this->buffer_write_ << endl; + this->buffer_read_ = new char [sizeof (message) + 1]; + + return 0; +} + +// Set the necessary things for the AIO stuff. +// Write the buffer asynchly.hmm Disable signals. +// Go on aio_suspend. Wait for completion. +// Print out the result. +int +Test_Aio::do_aio (void) +{ + // = Write to the file. + + // Setup AIOCB. + this->aiocb_write_->aio_fildes = this->out_fd_; + this->aiocb_write_->aio_offset = 0; + this->aiocb_write_->aio_buf = this->buffer_write_; + this->aiocb_write_->aio_nbytes = strlen (this->buffer_write_); + this->aiocb_write_->aio_reqprio = 0; + this->aiocb_write_->aio_sigevent.sigev_notify = SIGEV_NONE; + //this->this->aiocb_.aio_sigevent.sigev_signo = SIGRTMAX; + this->aiocb_write_->aio_sigevent.sigev_value.sival_ptr = + (void *) this->aiocb_write_; + + // Fire off the aio write. + if (aio_write (this->aiocb_write_) != 0) + { + perror ("aio_write"); + return -1; + } + + // = Read from that file. + + // Setup AIOCB. + this->aiocb_read_->aio_fildes = this->out_fd_; + this->aiocb_read_->aio_offset = 0; + this->aiocb_read_->aio_buf = this->buffer_read_; + this->aiocb_read_->aio_nbytes = strlen (this->buffer_write_); + this->aiocb_read_->aio_reqprio = 0; + this->aiocb_read_->aio_sigevent.sigev_notify = SIGEV_NONE; + //this->this->aiocb_.aio_sigevent.sigev_signo = SIGRTMAX; + this->aiocb_read_->aio_sigevent.sigev_value.sival_ptr = + (void *) this->aiocb_read_; + + // Fire off the aio write. If it doesnt get queued, carry on to get + // the completion for the first one. + if (aio_read (this->aiocb_read_) < 0) + perror ("aio_read"); + + // Wait for the completion on aio_suspend. + struct aiocb *list_aiocb[2]; + list_aiocb [0] = this->aiocb_write_; + list_aiocb [1] = this->aiocb_read_; + + // Do suspend till all the aiocbs in the list are done. + int done = 0; + while (!done) + { + if (aio_suspend (list_aiocb, 2, 0) != 0) + { + perror ("aio_suspend"); + return -1; + } + + // Analyze return and error values. + if (list_aiocb [0] != 0 && aio_error (list_aiocb [0]) != EINPROGRESS) + { + if (aio_return (list_aiocb [0]) == -1) + { + perror ("aio_return"); + return -1; + } + else + { + // Successful. Store the pointer somewhere and make the + // entry NULL in the list. + // @@ no need ----> this->aiocb_write_ = list_aiocb [0]; + list_aiocb [0] = 0; + } + } +// else +// cout << "AIO in progress" << endl; + + if (list_aiocb [1] != 0 && aio_error (list_aiocb [1]) != EINPROGRESS) + { + if (aio_return (list_aiocb [1]) == -1) + { + perror ("aio_return"); + return -1; + } + else + { + // Successful. Store the pointer somewhere and make the + // entry NULL in the list. + // @@ no need ----> this->aiocb_read_ = list_aiocb [1]; + list_aiocb [1] = 0; + } + } +// else +// cout << "AIO in progress" << endl; + + // Is it done? + if ((list_aiocb [0] == 0) && (list_aiocb [1] == 0)) + done = 1; + } + + //cout << "Both the AIO operations done." << endl; + //cout << "The buffer is :" << this->buffer_read_ << endl; + + return 0; +} + +int +main () +{ + Test_Aio test_aio; + + if (test_aio.init () != 0) + { + //printf ("AIOCB test failed:\n" + // "ACE_POSIX_AIOCB_PROACTOR may not work in this platform\n"); + return -1; + } + + if (test_aio.do_aio () != 0) + { + //printf ("AIOCB test failed:\n" + // "ACE_POSIX_AIOCB_PROACTOR may not work in this platform\n"); + return -1; + } + //printf ("AIOCB test successful:\n" + // "ACE_POSIX_AIOCB_PROACTOR should work in this platform\n"); + return 0; +} + ]])],[ + ace_cv_feature_aio_calls=yes + ],[ + ace_cv_feature_aio_calls=no + ],[ + dnl Asynchronous IO test for cross-compiled platforms + dnl This test is weaker than the above run-time tests but it will + dnl have to do. + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[ +#include <aio.h> + ]], + [[ + aiocb* aiocb_ptr (void); + ]])], + [ + ace_cv_feature_aio_calls=yes + ], + [ + ace_cv_feature_aio_calls=no + ]) + ]) + ],[AC_DEFINE([ACE_HAS_AIO_CALLS])],[LIBS="$ace_save_LIBS"]) +fi dnl test "$ace_has_aio_funcs" = yes + + +if test "$ace_cv_feature_aio_calls" = yes; then + ACE_CACHE_CHECK([for working POSIX realtime signals], + [ace_cv_feature_posix_rt_sigs], + [ + dnl Create a file for the test program to read. + cat > test_aiosig.txt <<EOF + +******************************************************* +FOO BAR FOO BAR FOO BAR FOO BAR FOO BAR FOO BAR FOO BAR +******************************************************* +EOF + + + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +extern "C" { +#include <signal.h> +} +#ifndef ACE_LACKS_UNISTD_H +#include <unistd.h> +#endif +#include <fcntl.h> +#ifndef ACE_LACKS_SYS_TYPES_H +# include <sys/types.h> +#endif +#include <sys/stat.h> +#include <pthread.h> +#include <string.h> +#include <errno.h> +#include <stdio.h> + +#include <limits.h> + +#include <aio.h> + +#ifdef __cplusplus +extern "C" +#endif +void null_handler (int /* signal_number */, + siginfo_t * /* info */, + void * /* context */); + +int file_handle = -1; +char mb1[BUFSIZ + 1]; +char mb2[BUFSIZ + 1]; +aiocb aiocb1, aiocb2; +sigset_t completion_signal; + +// Function prototypes. +int setup_signal_delivery (void); +int issue_aio_calls (void); +int query_aio_completions (void); +int test_aio_calls (void); +int setup_signal_handler (void); +int setup_signal_handler (int signal_number); + +int +setup_signal_delivery (void) +{ + // Make the sigset_t consisting of the completion signal. + if (sigemptyset (&completion_signal) == -1) + { + perror ("Error:Couldn't init the RT completion signal set\n"); + return -1; + } + + if (sigaddset (&completion_signal, SIGRTMIN) == -1) + { + perror ("Error:Couldn't init the RT completion signal set\n"); + return -1; + } + + // Mask them. + if (pthread_sigmask (SIG_BLOCK, &completion_signal, 0) == -1) + { + perror ("Error:Couldn't make the RT completion signals\n"); + return -1; + } + + return setup_signal_handler (SIGRTMIN); +} + +int +issue_aio_calls (void) +{ + // Setup AIOCB. + aiocb1.aio_fildes = file_handle; + aiocb1.aio_offset = 0; + aiocb1.aio_buf = mb1; + aiocb1.aio_nbytes = BUFSIZ; + aiocb1.aio_reqprio = 0; + aiocb1.aio_sigevent.sigev_notify = SIGEV_SIGNAL; + aiocb1.aio_sigevent.sigev_signo = SIGRTMIN; + aiocb1.aio_sigevent.sigev_value.sival_ptr = (void *) &aiocb1; + + // Fire off the aio write. + if (aio_read (&aiocb1) == -1) + { + // Queueing failed. + perror ("Error:Asynch_Read_Stream: aio_read queueing failed\n"); + return -1; + } + + // Setup AIOCB. + aiocb2.aio_fildes = file_handle; + aiocb2.aio_offset = BUFSIZ + 1; + aiocb2.aio_buf = mb2; + aiocb2.aio_nbytes = BUFSIZ; + aiocb2.aio_reqprio = 0; + aiocb2.aio_sigevent.sigev_notify = SIGEV_SIGNAL; + aiocb2.aio_sigevent.sigev_signo = SIGRTMIN; + aiocb2.aio_sigevent.sigev_value.sival_ptr = (void *) &aiocb2; + + // Fire off the aio write. + if (aio_read (&aiocb2) == -1) + { + // Queueing failed. + perror ("Error:Asynch_Read_Stream: aio_read queueing failed\n"); + return -1; + } + return 0; +} + +int +query_aio_completions (void) +{ + int result = 0; + size_t number_of_completions = 0; + for (number_of_completions = 0; + number_of_completions < 2; + number_of_completions++) + { + // Wait for <milli_seconds> amount of time. + // @@ Assigning <milli_seconds> to tv_sec. + timespec timeout; + timeout.tv_sec = 5; + timeout.tv_nsec = 0; + + // To get back the signal info. + siginfo_t sig_info; + + // Await the RT completion signal. + int sig_return = sigtimedwait (&completion_signal, + &sig_info, + &timeout); + + // Error case. + // If failure is coz of timeout, then return *0* but set + // errno appropriately. This is what the WinNT proactor + // does. + if (sig_return == -1) + { + perror ("Error:Error waiting for RT completion signals\n"); + return -1; + } + + // RT completion signals returned. + if (sig_return != SIGRTMIN) + { + //printf ("Unexpected signal (%d) has been received while waiting for RT Completion Signals\n", + // sig_return); + return -1; + } + + // @@ Debugging. + //printf ("Sig number found in the sig_info block : %d\n", + // sig_info.si_signo); + + // Is the signo returned consistent? + if (sig_info.si_signo != sig_return) + { + //printf ("Inconsistent signal number (%d) in the signal info block\n", + // sig_info.si_signo); + return -1; + } + + // @@ Debugging. + //printf ("Signal code for this signal delivery : %d\n", + // sig_info.si_code); + + // Is the signal code an aio completion one? + if ((sig_info.si_code != SI_ASYNCIO) && + (sig_info.si_code != SI_QUEUE)) + { + //printf ("Unexpected signal code (%d) returned on completion querying\n", + // sig_info.si_code); + return -1; + } + + // Retrive the aiocb. + aiocb* aiocb_ptr = (aiocb *) sig_info.si_value.sival_ptr; + + // Analyze error and return values. Return values are + // actually <errno>'s associated with the <aio_> call + // corresponding to aiocb_ptr. + int error_code = aio_error (aiocb_ptr); + if (error_code == -1) + { + perror ("Error:Invalid control block was sent to <aio_error> for compleion querying\n"); + return -1; + } + + if (error_code != 0) + { + // Error occurred in the <aio_>call. Return the errno + // corresponding to that <aio_> call. + //printf ("Error:An AIO call has failed:Error code = %d\n", + // error_code); + return -1; + } + + // No error occured in the AIO operation. + int nbytes = aio_return (aiocb_ptr); + if (nbytes == -1) + { + perror ("Error:Invalid control block was sent to <aio_return>\n"); + return -1; + } + + //if (number_of_completions == 0) + // Print the buffer. + //printf ("Number of bytes transferred : %d\n The buffer : %s \n", + // nbytes, + // mb1); + //else + // Print the buffer. + //printf ("Number of bytes transferred : %d\n The buffer : %s \n", + // nbytes, + // mb2); + } + return 0; +} + +int +test_aio_calls (void) +{ + // Set up the input file. + // Open file (in SEQUENTIAL_SCAN mode) + file_handle = open ("test_aiosig.txt", O_RDONLY); + + if (file_handle == -1) + { + perror ("open"); + return -1; + } + + unlink ("test_aiosig.txt"); // Unlink now so we don't have to do so later. + + if (setup_signal_delivery () < 0) + return -1; + + if (issue_aio_calls () < 0) + return -1; + + if (query_aio_completions () < 0) + return -1; + + if (close (file_handle) != 0) + { + perror ("close"); + return -1; + } + + return 0; +} + +int +setup_signal_handler (int signal_number) +{ + // Setting up the handler(!) for these signals. + struct sigaction reaction; + sigemptyset (&reaction.sa_mask); // Nothing else to mask. + reaction.sa_flags = SA_SIGINFO; // Realtime flag. +#if defined (SA_SIGACTION) + // Lynx says, it is better to set this bit to be portable. + reaction.sa_flags &= SA_SIGACTION; +#endif /* SA_SIGACTION */ + reaction.sa_sigaction = null_handler; // Null handler. + int sigaction_return = sigaction (SIGRTMIN, + &reaction, + 0); + if (sigaction_return == -1) + { + perror ("Error:Proactor couldn't do sigaction for the RT SIGNAL"); + return -1; + } + + return 0; +} + +void +null_handler (int /* signal_number */, + siginfo_t * /* info */, + void * /* context */) +{ +} + +int +main () +{ + if (test_aio_calls () == 0) + { + // printf ("RT SIG test successful:\n" + // "ACE_POSIX_SIG_PROACTOR should work in this platform\n"); + return 0; + } + + //printf ("RT SIG test failed:\n" + // "ACE_POSIX_SIG_PROACTOR may not work in this platform\n"); + return -1; + +} + ]])], + [ + ace_cv_feature_posix_rt_sigs=yes + ], + [ + ace_cv_feature_posix_rt_sigs=no + ], + [ + dnl Don't bother doing anything for cross-compiling here + dnl since the basic aio run-time test will prevent this + dnl rt sig run-time test from ever running when cross-compiling. + dnl We just put something in here to prevent autoconf + dnl from complaining. + ace_just_a_place_holder=ignoreme + ]) + ],[AC_DEFINE([ACE_HAS_POSIX_REALTIME_SIGNALS])],[]) +fi dnl test "$ace_cv_feature_aio_calls" = yes + +]) |