00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "fennel/common/CommonPreamble.h"
00025
00026 #ifdef USE_AIO_H
00027
00028 #include "fennel/device/RandomAccessDevice.h"
00029 #include "fennel/device/AioSignalScheduler.h"
00030 #include "fennel/device/DeviceAccessSchedulerParams.h"
00031 #include "fennel/synch/Thread.h"
00032
00033 #include <errno.h>
00034 #include <sys/signal.h>
00035
00036 FENNEL_BEGIN_CPPFILE("$Id: //open/dev/fennel/device/AioSignalScheduler.cpp#11 $");
00037
00038 class AioSignalHandlerThread : public Thread
00039 {
00040 AioSignalScheduler &scheduler;
00041 public:
00042 AioSignalHandlerThread(AioSignalScheduler &schedulerInit)
00043 : scheduler(schedulerInit)
00044 {
00045 }
00046 virtual void run();
00047 };
00048
00049 static void aio_handler(int,siginfo_t *pSiginfo,void *)
00050 {
00051 assert(pSiginfo->si_code == SI_ASYNCIO);
00052 RandomAccessRequestBinding *pBinding =
00053 static_cast<RandomAccessRequestBinding *>(pSiginfo->si_value.sival_ptr);
00054
00055
00056
00057
00058 aiocb *lpBinding = static_cast<aiocb *>(pBinding);
00059
00060 int rc = aio_error(lpBinding);
00061 if (rc != EINPROGRESS) {
00062 rc = aio_return(lpBinding);
00063 pBinding->notifyTransferCompletion(rc >= 0);
00064 }
00065
00066 }
00067
00068 AioSignalScheduler::AioSignalScheduler(
00069 DeviceAccessSchedulerParams const ¶ms)
00070 {
00071
00072
00073
00074
00075 int rc;
00076 sigset_t mask;
00077 sigemptyset(&mask);
00078 sigaddset(&mask,SIGRTMIN);
00079 rc = pthread_sigmask(SIG_BLOCK,&mask,NULL);
00080 assert(!rc);
00081
00082
00083
00084
00085 struct sigaction sa;
00086 sa.sa_flags = SA_SIGINFO;
00087 sa.sa_sigaction = aio_handler;
00088 sigemptyset(&(sa.sa_mask));
00089 rc = sigaction(SIGRTMIN,&sa,&saOld);
00090 assert(!rc);
00091
00092 quit = false;
00093 for (uint i = 0; i < params.nThreads; ++i) {
00094 AioSignalHandlerThread *pThread = new AioSignalHandlerThread(*this);
00095 pThread->start();
00096 threads.push_back(pThread);
00097 }
00098 }
00099
00100 AioSignalScheduler::~AioSignalScheduler()
00101 {
00102 assert(!isStarted());
00103 }
00104
00105 bool AioSignalScheduler::schedule(RandomAccessRequest &request)
00106 {
00107 assert(isStarted());
00108
00109 int rc;
00110
00111
00112
00113 request.pDevice->prepareTransfer(request);
00114 RandomAccessRequest::BindingListMutator bindingMutator(request.bindingList);
00115 while (bindingMutator) {
00116 RandomAccessRequestBinding *pBinding = bindingMutator.detach();
00117 pBinding->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
00118 pBinding->aio_sigevent.sigev_signo = SIGRTMIN;
00119 pBinding->aio_sigevent.sigev_value.sival_ptr = pBinding;
00120
00121
00122
00123
00124 aiocb *lpBinding = static_cast<aiocb *>(pBinding);
00125
00126 if (request.type == RandomAccessRequest::READ) {
00127 rc = aio_read(lpBinding);
00128 } else {
00129 rc = aio_write(lpBinding);
00130 }
00131 assert(!rc);
00132 }
00133
00134 return true;
00135 }
00136
00137 void AioSignalScheduler::stop()
00138 {
00139 assert(isStarted());
00140
00141 StrictMutexGuard guard(mutex);
00142 quit = true;
00143 quitCondition.notify_all();
00144 guard.unlock();
00145
00146 for (uint i = 0; i < threads.size(); ++i) {
00147 threads[i]->join();
00148 deleteAndNullify(threads[i]);
00149 }
00150 threads.clear();
00151
00152 int rc = sigaction(SIGRTMIN,&saOld,NULL);
00153 assert(!rc);
00154 }
00155
00156 void AioSignalHandlerThread::run()
00157 {
00158 int rc;
00159
00160
00161 sigset_t mask;
00162 sigemptyset(&mask);
00163 sigaddset(&mask,SIGRTMIN);
00164 rc = pthread_sigmask(SIG_UNBLOCK,&mask,NULL);
00165 assert(!rc);
00166
00167
00168
00169 #ifdef sun
00170 int policy;
00171 sched_param param;
00172 rc = pthread_getschedparam(pthread_self(),&policy,¶m);
00173 assert(!rc);
00174 param.sched_priority++;
00175 rc = pthread_setschedparam(pthread_self(),SCHED_RR,¶m);
00176 assert(!rc);
00177 #endif
00178
00179
00180
00181 while (!scheduler.quit) {
00182 sleep(1);
00183 }
00184 }
00185
00186 FENNEL_END_CPPFILE("$Id: //open/dev/fennel/device/AioSignalScheduler.cpp#11 $");
00187
00188 #endif
00189
00190