diff --git a/src/XrdSys/XrdSysIOEvents.cc b/src/XrdSys/XrdSysIOEvents.cc index 3e07c66548f..7610d937bc7 100644 --- a/src/XrdSys/XrdSysIOEvents.cc +++ b/src/XrdSys/XrdSysIOEvents.cc @@ -66,6 +66,26 @@ #define ISPOLLER XrdSysThread::Same(XrdSysThread::ID(),pollTid) +#define BOOLNAME(x) (x ? "true" : "false") + +#define DO_TRACE(x,fd,y) \ + {PollerInit::traceMTX.Lock(); \ + cerr <<"IOE fd " <GetFD(), "Init() returned " <(reMod); + else curev = static_cast(chEvents); + // Calculate new event mask // - curev = static_cast(chEvents); events &= allEvents; newev = curev & ~events; @@ -313,6 +343,9 @@ bool XrdSys::IOEvents::Channel::Disable(int events, const char **eText) if (newev != curev) {chEvents = newev; retval = chPoller->Modify(this, eNum, eText, isLocked); + TRACE_MOD(Disable,chFD,newev,curev); + } else { + TRACE_NOD(Disable,chFD,newev); } if (isLocked) chMutex.UnLock(); @@ -330,18 +363,27 @@ bool XrdSys::IOEvents::Channel::Enable(int events, int timeout, const char **eText) { time_t newDL; - int eNum, newev, curev = static_cast(chEvents); + int eNum, newev, curev; bool retval, isLocked = true, setTO = false; +// Trace this entry +// + IF_TRACE(Enable,chFD,"->Enable(" <(reMod); + else curev = static_cast(chEvents); + // Establish events that should be enabled // events &= allEvents; newev = (curev ^ events) & events; - chEvents |= events; + chEvents = curev | events; // Handle timeout changes now // @@ -369,7 +411,7 @@ bool XrdSys::IOEvents::Channel::Enable(int events, int timeout, // Check if we have to reset the timeout. We need to hold the channel lock here. // - if (setTO && (chPoller == &pollInit || chPoller != &pollErr1)) + if (setTO && chPoller != &pollErr1) setTO = chPollXQ->TmoAdd(this); else setTO = false; @@ -379,7 +421,13 @@ bool XrdSys::IOEvents::Channel::Enable(int events, int timeout, // not unlock here is because we must ensure the channel doesn't change while // we call modify. We let modify determine what to do. // - retval = (newev ? chPoller->Modify(this, eNum, eText, isLocked) : true); + if (newev) + {retval = chPoller->Modify(this, eNum, eText, isLocked); + TRACE_MOD(Enable,chFD,(curev | events),curev); + } else { + retval = true; + TRACE_NOD(Enable,chFD,(curev | events)); + } // We need to notify the poller thread if the added deadline is the first in the // queue and the poller is waiting. We also optimize for the case where the @@ -560,7 +608,19 @@ bool XrdSys::IOEvents::Poller::CbkXeq(XrdSys::IOEvents::Channel *cP, int events, XrdSysMutexHelper cbkMHelp(cP->chMutex); char oldEvents; int isRead = 0, isWrite = 0; - bool cbok, isLocked = true; + bool cbok, retval, isLocked = true; + +// Perform any required tracing +// + if (TRACING) + {const char *cbtype = (cP->chPoller == cP->chPollXQ ? "norm" : + (cP->chPoller == &pollInit ? "init" : + (cP->chPoller == &pollWait ? "wait" : "err"))); + DO_TRACE(CbkXeq,cP->chFD,"callback events=" <chCB ? "present" : "missing") + <<" poller=" <chEvents; cP->chEvents = 0; - Modify(cP, eNum, 0, isLocked); + retval = cP->chPoller->Modify(cP, eNum, 0, isLocked); + TRACE_MOD(CbkXeq,cP->chFD,0,oldEvents); if (!isLocked) cP->chMutex.Lock(); cP->chEvents = oldEvents; return true; @@ -618,7 +679,9 @@ bool XrdSys::IOEvents::Poller::CbkXeq(XrdSys::IOEvents::Channel *cP, int events, cP->chStat = Channel::isCBMode; chDead = false; cbkMHelp.UnLock(); + IF_TRACE(CbkXeq,cP->chFD,"invoking callback; events=" <chCB->Event(cP,cP->chCBA, events); + IF_TRACE(CbkXeq,cP->chFD,"callback returned " <chPoller == &pollWait) + {cP->reMod = cP->chEvents; + cP->chEvents = 0; + IF_TRACE(Init,cP->chFD,"defer events=" <reMod); + return true; + } + +// Trace this entry +// + IF_TRACE(Init,cP->chFD,"begin events=" <chEvents)); // If no events are enabled at this point, just return // @@ -815,31 +892,28 @@ bool XrdSys::IOEvents::Poller::Init(XrdSys::IOEvents::Channel *cP, int &eNum, return false; } -// If we are already in progress then indicate to the other thread that it -// needs to remodify this channel w.r.t. to the poller (this is very rare). -// - if (cP->chPoller == &pollWait) - {cP->reMod = 1; - return true; - } - -// So, now we can include the channel in the poll set, enable it, and if -// successful, point it to a functioning poller. +// So, now we can include the channel in the poll set. We will include it +// with no events enabled to prevent callbacks prior to completion here. // - cP->chPoller = &pollWait; oldEv = cP->chEvents; + cP->chPoller = &pollWait; cP->reMod = cP->chEvents; cP->chEvents = 0; retval = cP->chPollXQ->Include(cP, eNum, eTxt, isLocked); + IF_TRACE(Init,cP->chFD,"Include() returned " <chMutex.Lock(); isLocked = true;} -// Determine what future poller to use and whether something happened should we -// have lost control of the channel. If something meaningful did happen then -// we need to redo it at this point as the other thread didn't want to wait. +// Determine what future poller to use. If we can use the regular poller then +// set the correct event mask for the channel. Note that we could have lost +// control but the correct events will be reflected in the "reMod" member. // if (!retval) {cP->chPoller = &pollErr1; cP->chFault = eNum;} else {cP->chPoller = cP->chPollXQ; cP->inPSet = 1; - if (cP->reMod && cP->chEvents != oldEv) - {retval = cP->chPoller->Modify(cP, eNum, eTxt, isLocked); + if (cP->reMod) + {cP->chEvents = cP->reMod; + retval = cP->chPoller->Modify(cP, eNum, eTxt, isLocked); + TRACE_MOD(Init,cP->chFD,int(cP->reMod),0); if (!isLocked) {cP->chMutex.Lock(); isLocked = true;} + } else { + TRACE_NOD(Init,cP->chFD,0); } } diff --git a/src/XrdSys/XrdSysIOEvents.hh b/src/XrdSys/XrdSysIOEvents.hh index 5bd92cce862..7179565fcd6 100644 --- a/src/XrdSys/XrdSysIOEvents.hh +++ b/src/XrdSys/XrdSysIOEvents.hh @@ -496,7 +496,7 @@ void WakeUp(); static Poller *newPoller(int pFD[2], int &eNum, const char **eTxt); XrdSysMutex adMutex; // Mutex for adding & detaching channels -XrdSysRecMutex toMutex; // Mutex for handling the timeout list +XrdSysMutex toMutex; // Mutex for handling the timeout list }; }; };