XRootD
XrdSys::IOEvents::PollPoll Class Reference
+ Inheritance diagram for XrdSys::IOEvents::PollPoll:
+ Collaboration diagram for XrdSys::IOEvents::PollPoll:

Public Member Functions

 PollPoll (int &rc, int numfd, int pFD[2])
 
 ~PollPoll ()
 
- Public Member Functions inherited from XrdSys::IOEvents::Poller
 Poller (int cFD, int rFD)
 
virtual ~Poller ()
 Destructor. Stop() is effecively called when this object is deleted. More...
 
void Stop ()
 

Protected Member Functions

void Begin (XrdSysSemaphore *syncp, int &rc, const char **eMsg)
 
void Exclude (Channel *cP, bool &isLocked, bool dover=1)
 
bool Include (Channel *cP, int &eNum, const char **eTxt, bool &isLocked)
 
bool Modify (Channel *cP, int &eNum, const char **eTxt, bool &isLocked)
 
void Shutdown ()
 
- Protected Member Functions inherited from XrdSys::IOEvents::Poller
void CbkTMO ()
 
bool CbkXeq (Channel *cP, int events, int eNum, const char *eTxt)
 
 CPP_ATOMIC_TYPE (bool) wakePend
 
int GetFault (Channel *cP)
 
int GetPollEnt (Channel *cP)
 
int GetRequest ()
 
bool Init (Channel *cP, int &eNum, const char **eTxt, bool &isLockd)
 
void LockChannel (Channel *cP)
 
int Poll2Enum (short events)
 
int SendCmd (PipeData &cmd)
 
void SetPollEnt (Channel *cP, int ptEnt)
 
bool TmoAdd (Channel *cP, int tmoSet)
 
void TmoDel (Channel *cP)
 
int TmoGet ()
 
void UnLockChannel (Channel *cP)
 

Additional Inherited Members

- Public Types inherited from XrdSys::IOEvents::Poller
enum  CreateOpts { optTOM }
 
- Static Public Member Functions inherited from XrdSys::IOEvents::Poller
static PollerCreate (int &eNum, const char **eTxt=0, int crOpts=0)
 
- Protected Attributes inherited from XrdSys::IOEvents::Poller
ChannelattBase
 
bool chDead
 
int cmdFD
 
int pipeBlen
 
char * pipeBuff
 
struct pollfd pipePoll
 
pthread_t pollTid
 
PipeData reqBuff
 
int reqFD
 
ChanneltmoBase
 
unsigned char tmoMask
 
- Static Protected Attributes inherited from XrdSys::IOEvents::Poller
static time_t maxTime = (sizeof(time_t) == 8 ? 0x7fffffffffffffffLL : 0x7fffffff)
 
static pid_t parentPID = getpid()
 

Detailed Description

Definition at line 49 of file XrdSysIOEventsPollPoll.icc.

Constructor & Destructor Documentation

◆ PollPoll()

XrdSys::IOEvents::PollPoll::PollPoll ( int &  rc,
int  numfd,
int  pFD[2] 
)

Definition at line 122 of file XrdSysIOEventsPollPoll.icc.

123  : Poller(pFD[0], pFD[1])
124 {
125  int i;
126 
127 // Allocate initial poll table
128 //
129  if (!(pollTab = (struct pollfd *)malloc(numfd*sizeof(struct pollfd))))
130  {rc = errno; return;}
131 
132 // Initialize it
133 //
134  for (i = 1; i < numfd; i++)
135  {pollTab[i].fd = -1; pollTab[i].events = 0; pollTab[i].revents = 0;}
136 
137 // The first element of the poll tab is the communications pipe
138 //
139  pollTab[0].fd = pFD[0];
140  pollTab[0].events = POLLIN | POLLRDNORM;
141  pollTab[0].revents = 0;
142 
143 // Initialize remaining poll data
144 //
145  pollNum = 1;
146  pollMax = numfd;
147  pnewTab = 0;
148 
149 // Allocate initial channel table
150 //
151  if (!(chnlTab = (Channel **)malloc(numfd*sizeof(Channel *))))
152  {rc = errno; return;}
153 
154 // Initialize it
155 //
156  memset(chnlTab, 0, numfd*sizeof(Channel *));
157  chnlMax = numfd;
158  chnlNum = 1;
159 
160 // All done
161 //
162  rc = 0;
163 }
Poller(int cFD, int rFD)

◆ ~PollPoll()

XrdSys::IOEvents::PollPoll::~PollPoll ( )
inline

Definition at line 54 of file XrdSysIOEventsPollPoll.icc.

References XrdSys::IOEvents::Poller::Stop().

+ Here is the call graph for this function:

Member Function Documentation

◆ Begin()

void XrdSys::IOEvents::PollPoll::Begin ( XrdSysSemaphore syncp,
int &  rc,
const char **  eTxt 
)
protectedvirtual

Start the polling event loop. An implementation must be supplied. Begin() is called via the internal BootStrap class from a new thread.

Implements XrdSys::IOEvents::Poller.

Definition at line 169 of file XrdSysIOEventsPollPoll.icc.

172 {
173  int i, num2poll, numpolled;
174 
175 // Indicate to the starting thread that all went well
176 //
177  retcode = 0;
178  *eTxt = 0;
179  syncsem->Post();
180 
181 // Now start dispatching channels that are ready. We use the wakePend flag to
182 // keep the chatter down when we actually wakeup.
183 //
184  pollMutex.Lock();
185  do {num2poll = pollNum;
186  pollMutex.UnLock();
187  do {numpolled = poll(pollTab, num2poll, TmoGet());}
188  while(numpolled < 0 && (errno == EAGAIN || errno == EINTR));
189  pollMutex.Lock();
190  wakePend = true;
191 
192  if (pnewTab)
193  {memcpy(pnewTab, pollTab, pollMax*sizeof(struct pollfd));
194  free(pollTab); pollTab = pnewTab; pnewTab = 0; pollMax = chnlMax;
195  }
196 
197  if (numpolled == 0) CbkTMO();
198  else if (numpolled < 0)
199  {int rc = errno;
200  //--------------------------------------------------------------
201  // If we are in a child process and the poll file descriptor
202  // has been closed, there is an immense chance the fork will be
203  // followed by an exec, in which case we don't want to abort
204  //--------------------------------------------------------------
205  if( rc == EBADF && parentPID != getpid() ) return;
206  std::cerr <<"PPoll: "<<XrdSysE2T(rc)<<" polling for events"<<std::endl;
207  abort();
208  }
209  else{if (pollTab[0].revents) numpolled--;
210  for (i = 1; i < num2poll && numpolled; i++)
211  {if (pollTab[i].revents)
212  {numpolled--;
213  Dispatch(i, pollTab[i].revents);
214  }
215  }
216  if (pollTab[0].revents && !Process()) return;
217  }
218  } while(1);
219 }
const char * XrdSysE2T(int errcode)
Definition: XrdSysE2T.cc:104

References XrdSysSemaphore::Post(), and XrdSysE2T().

+ Here is the call graph for this function:

◆ Exclude()

void XrdSys::IOEvents::PollPoll::Exclude ( Channel cP,
bool &  isLocked,
bool  dover = 1 
)
protectedvirtual

Remove a channel to the poll set. An implementation must be supplied. The channel is locked when this method is called but must be unlocked by the method if a command is sent to the poller thread and isLocked set to false.

Implements XrdSys::IOEvents::Poller.

Definition at line 264 of file XrdSysIOEventsPollPoll.icc.

266 {
267  int ctnum;
268 
269 // Verify that this channel is assigned.
270 //
271  ctnum = GetPollEnt(cP);
272  pollMutex.Lock();
273  if (chnlTab[ctnum] != cP) {pollMutex.UnLock(); return;}
274  pollMutex.UnLock();
275 
276 // If we are the poller thread then we can remove this now. Note that we will
277 // still have the poll mutex because the caller would have it as well.
278 // Otherwise, send a message to the poller to do this. We will need to release
279 // the channel lock to prevent deadlocks. The caller will relock as needed.
280 // This message always synchronizes with the poller.
281 //
282  if (ISPOLLER)
283  {FDRem(ctnum);
284  return;
285  } else {
286  PipeData cmdbuff((char)PipeData::RmFD,0,(short)ctnum,cP->GetFD());
287  if (isLocked) {isLocked = false; UnLockChannel(cP);}
288  SendCmd(cmdbuff);
289  }
290 }
#define ISPOLLER
int GetPollEnt(Channel *cP)
int SendCmd(PipeData &cmd)
void UnLockChannel(Channel *cP)

References XrdSys::IOEvents::Channel::GetFD(), and ISPOLLER.

+ Here is the call graph for this function:

◆ Include()

bool XrdSys::IOEvents::PollPoll::Include ( Channel cP,
int &  eNum,
const char **  eTxt,
bool &  isLocked 
)
protectedvirtual

Add a channel to the poll set. An implementation must be supplied. The channel is locked when this method is called but must be unlocked by the method if a command is sent to the poller thread and isLocked set to false.

Implements XrdSys::IOEvents::Poller.

Definition at line 367 of file XrdSysIOEventsPollPoll.icc.

371 {
372  static const int incVal = 256;
373  static const int cpSz = sizeof(Channel *);
374  static const int ptSz = sizeof(struct pollfd);
375  int fd, ctnum;
376 
377 // Validate the file descriptor
378 //
379  fd = cP->GetFD();
380  if (fd & 0xffff0000)
381  {eNum = EBADF;
382  if (eTxt) *eTxt = "adding channel";
383  return false;
384  }
385 
386 // Make sure this channel is not already assigned to this poller
387 //
388  if (GetPollEnt(cP))
389  {eNum = EEXIST;
390  if (eTxt) *eTxt = "adding channel";
391  return false;
392  }
393 
394 // Get the next channel table entry to be used
395 //
396  pollMutex.Lock();
397  ctnum = 1;
398  while((ctnum < chnlMax) && (chnlTab[ctnum] != 0)) ctnum++;
399 
400 // Reallocate channel table if we don't have enough space. We also pre-allocate
401 // a new poll table so that we can reflect failure to the caller as the poller
402 // can't do that. The poller will swap the new one for the old one.
403 //
404  if (ctnum >= chnlMax)
405  {Channel **cnewTab = (Channel **)realloc(chnlTab,(chnlMax+incVal)*cpSz);
406  if (pnewTab) free(pnewTab);
407  pnewTab = (struct pollfd *)malloc((chnlMax+incVal)*ptSz);
408  if (!cnewTab || !pnewTab)
409  {pollMutex.UnLock();
410  eNum = ENOMEM;
411  if (eTxt) *eTxt = "adding channel";
412  if (cnewTab) free(cnewTab);
413  if (pnewTab) free(pnewTab);
414  return false;
415  }
416  memset(&cnewTab[ctnum], 0, incVal*cpSz);
417  memset(&pnewTab[ctnum],-1, incVal*ptSz);
418  chnlTab = cnewTab; chnlMax += incVal; chnlNum = ctnum+1;
419  } else if (ctnum > chnlNum) chnlNum = ctnum;
420 
421 // Record the poll table entry in the channel
422 //
423  chnlTab[ctnum] = cP;
424  SetPollEnt(cP, ctnum);
425  pollMutex.UnLock();
426 
427 // If we are the poller thread, then enable the poll entry in-line. Note that
428 // we will still be holding the poll mutex because the caller also has it.
429 // Otherwise, send a message to the poller to do this. We will need to release
430 // the channel lock to prevent deadlocks. The caller will relock as needed.
431 //
432  if (ISPOLLER)
433  {FDMod(ctnum, fd, cP->GetEvents());
434  return true;
435  } else {
436  PipeData cmdbuff((char)PipeData::MiFD, (char)cP->GetEvents(),
437  (short)ctnum, fd, 0);
438  if (isLocked) {isLocked = false; UnLockChannel(cP);}
439  SendCmd(cmdbuff);
440  }
441 
442 // All done
443 //
444  return true;
445 }
void SetPollEnt(Channel *cP, int ptEnt)

References XrdSys::IOEvents::Channel::GetEvents(), XrdSys::IOEvents::Channel::GetFD(), and ISPOLLER.

+ Here is the call graph for this function:

◆ Modify()

bool XrdSys::IOEvents::PollPoll::Modify ( Channel cP,
int &  eNum,
const char **  eTxt,
bool &  isLocked 
)
protectedvirtual

Modify the event status of a channel. An implementation must be supplied. The channel is locked when this method is called but must be unlocked by the method if a command is sent to the poller thread and isLocked set to false.

Implements XrdSys::IOEvents::Poller.

Definition at line 451 of file XrdSysIOEventsPollPoll.icc.

455 {
456 
457 // If we are the poller thread, then modify the poll entry in-line. Otherwise,
458 // send a modification message to the poller. This requires that we unlock the
459 // channel to prevent any deadlocks. The caller will relock it as needed.
460 //
461  if (ISPOLLER)
462  {FDMod(GetPollEnt(cP), cP->GetFD(), cP->GetEvents());
463  return true;
464  } else {
465  PipeData cmdbuff((char)PipeData::MdFD, (char)cP->GetEvents(),
466  (short)GetPollEnt(cP), cP->GetFD(), 0);
467  if (isLocked) {isLocked = false; UnLockChannel(cP);}
468  SendCmd(cmdbuff);
469  }
470 
471 // All done
472 //
473  return true;
474 }

References XrdSys::IOEvents::Channel::GetEvents(), XrdSys::IOEvents::Channel::GetFD(), and ISPOLLER.

+ Here is the call graph for this function:

◆ Shutdown()

void XrdSys::IOEvents::PollPoll::Shutdown ( )
protectedvirtual

Shutdown the poller. An implementation must be supplied. The shutdown method must release any allocated storage and close private file descriptors. The polling thread will have already been terminated and x-thread pipe closed. Warning: the derived destructor must call Stop() and do nothing else!

Implements XrdSys::IOEvents::Poller.

Definition at line 513 of file XrdSysIOEventsPollPoll.icc.

514 {
515  static XrdSysMutex shutMutex;
516 
517 // To avoid race conditions, we serialize this code
518 //
519  shutMutex.Lock();
520 
521 // Release the appendages
522 //
523  if (pollTab) {free(pollTab); pollTab = 0;}
524  if (pnewTab) {free(pnewTab); pnewTab = 0;}
525  if (chnlTab) {free(chnlTab); chnlTab = 0;}
526 
527 // All done
528 //
529  shutMutex.UnLock();
530 }

References XrdSysMutex::Lock(), and XrdSysMutex::UnLock().

+ Here is the call graph for this function:

The documentation for this class was generated from the following file: