root/plugin/ipc/event/eventwrappers.cpp

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. poll
  2. pselect
  3. select
  4. signalfd
  5. eventfd
  6. epoll_create
  7. epoll_create1
  8. epoll_ctl
  9. epoll_wait
  10. inotify_init
  11. inotify_init1
  12. inotify_init
  13. inotify_init1
  14. inotify_add_watch
  15. inotify_rm_watch

   1 /****************************************************************************
   2  *   Copyright (C) 2012 by Kapil Arya, Gene Cooperman, and Rohan Garg       *
   3  *   kapil@ccs.neu.edu, gene@ccs.neu.edu, rohgarg@ccs.neu.edu               *
   4  *                                                                          *
   5  *   This file is part of the dmtcp/src module of DMTCP (DMTCP:dmtcp/src).  *
   6  *                                                                          *
   7  *  DMTCP:dmtcp/src is free software: you can redistribute it and/or        *
   8  *  modify it under the terms of the GNU Lesser General Public License as   *
   9  *  published by the Free Software Foundation, either version 3 of the      *
  10  *  License, or (at your option) any later version.                         *
  11  *                                                                          *
  12  *  DMTCP:dmtcp/src is distributed in the hope that it will be useful,      *
  13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of          *
  14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
  15  *  GNU Lesser General Public License for more details.                     *
  16  *                                                                          *
  17  *  You should have received a copy of the GNU Lesser General Public        *
  18  *  License along with DMTCP:dmtcp/src.  If not, see                        *
  19  *  <http://www.gnu.org/licenses/>.                                         *
  20  ****************************************************************************/
  21 
  22 #include <poll.h>
  23 #include <sys/select.h>
  24 /* According to POSIX.1-2001 */
  25 #include <sys/select.h>
  26 /* Next three according to earlier standards */
  27 #include <sys/time.h>
  28 #include <sys/types.h>
  29 #include <unistd.h>
  30 #include "dmtcpalloc.h"
  31 #include "eventwrappers.h"
  32 #include "eventconnection.h"
  33 #include "eventconnlist.h"
  34 #include "jassert.h"
  35 
  36 using namespace dmtcp;
  37 /* 'man 7 signal' says the following are not restarted after ckpt signal
  38  * even though the SA_RESTART option was used.  If we wrap these, we must
  39  * restart them when they are interrupted by a checkpoint signal.
  40  * python-2.7{socketmodule.c,signalmodule.c} assume no unknown signal
  41  *   handlers such as DMTCP checkpoint signal.  So, Python needs this.
  42  *
  43  * + Socket interfaces, when a timeout has been  set  on  the  socket
  44  *   using   setsockopt(2):   accept(2),  recv(2),  recvfrom(2),  and
  45  *   recvmsg(2), if a receive timeout (SO_RCVTIMEO)  has  been  set;
  46  *   connect(2),  send(2), sendto(2), and sendmsg(2), if a send timeout
  47  *   (SO_SNDTIMEO) has been set.
  48  *
  49  * + Interfaces used to wait for  signals:  pause(2),  sigsuspend(2),
  50  *   sigtimedwait(2), and sigwaitinfo(2).
  51  *
  52  * + File    descriptor   multiplexing   interfaces:   epoll_wait(2),
  53  *   epoll_pwait(2), poll(2), ppoll(2), select(2), and pselect(2).
  54  *
  55  * + System V IPC interfaces:  msgrcv(2),  msgsnd(2),  semop(2),  and
  56  *   semtimedop(2).
  57  *
  58  * + Sleep interfaces:  clock_nanosleep(2), nanosleep(2), and usleep(3).
  59  *
  60  * + read(2) from an inotify(7) file descriptor.
  61  *
  62  * + io_getevents(2).
  63  */
  64 
  65 // TODO(kapil): A better way to fix this is to lookup the stack to check if we
  66 // are in the middle of a poll/select/pselect call and set some global variable
  67 // and restart the syscall only if that variable is set.
  68 
  69 /* Poll wrapper forces poll to restart after ckpt/resume or ckpt/restart */
  70 extern "C" int poll(struct pollfd *fds, nfds_t nfds, int timeout)
  71 {
  72   int rc;
  73   while (1) {
  74     uint32_t orig_generation = dmtcp_get_generation();
  75     rc = _real_poll(fds, nfds, timeout);
  76     if (rc == -1 && errno == EINTR &&
  77          dmtcp_get_generation() > orig_generation) {
  78       continue;  // This was a restart or resume after checkpoint.
  79     } else {
  80       break;  // The signal interrupting us was not our checkpoint signal.
  81     }
  82   }
  83   return rc;
  84 }
  85 
  86 
  87 // pselect wrapper forces pselect to restart after ckpt/resume or ckpt/restart
  88 extern "C" int pselect(int nfds, fd_set *readfds, fd_set *writefds,
  89                        fd_set *exceptfds, const struct timespec *timeout,
  90                        const sigset_t *sigmask)
  91 {
  92   int rc;
  93   while (1) {
  94     uint32_t orig_generation = dmtcp_get_generation();
  95     rc = _real_pselect(nfds, readfds, writefds, exceptfds, timeout, sigmask);
  96     if (rc == -1 && errno == EINTR &&
  97          dmtcp_get_generation() > orig_generation) {
  98       continue;  // This was a restart or resume after checkpoint.
  99     } else {
 100       break;  // The signal interrupting us was not our checkpoint signal.
 101     }
 102   }
 103   return rc;
 104 }
 105 
 106 
 107 extern "C" int select(int nfds, fd_set *readfds, fd_set *writefds,
 108                        fd_set *exceptfds, struct timeval *timeout)
 109 {
 110   int rc;
 111   while (1) {
 112     uint32_t orig_generation = dmtcp_get_generation();
 113     rc = _real_select(nfds, readfds, writefds, exceptfds, timeout);
 114     if (rc == -1 && errno == EINTR &&
 115          dmtcp_get_generation() > orig_generation) {
 116       continue;  // This was a restart or resume after checkpoint.
 117     } else {
 118       break;  // The signal interrupting us was not our checkpoint signal.
 119     }
 120   }
 121   return rc;
 122 }
 123 
 124 
 125 /****************************************************************************
 126  ****************************************************************************/
 127 
 128 #ifdef HAVE_SYS_SIGNALFD_H
 129 extern "C" int signalfd(int fd, const sigset_t *mask, int flags)
 130 {
 131   DMTCP_PLUGIN_DISABLE_CKPT();
 132   int ret = _real_signalfd(fd, mask, flags);
 133   if (ret != -1) {
 134     JTRACE("signalfd created") (fd) (flags);
 135     EventConnList::instance().add(ret, new SignalFdConnection(fd, mask, flags));
 136   }
 137   DMTCP_PLUGIN_ENABLE_CKPT();
 138   return ret;
 139 }
 140 #endif
 141 
 142 #ifdef HAVE_SYS_EVENTFD_H
 143 extern "C" int eventfd(EVENTFD_VAL_TYPE initval, int flags)
 144 {
 145   DMTCP_PLUGIN_DISABLE_CKPT();
 146   int ret = _real_eventfd(initval, flags);
 147   if (ret != -1) {
 148     JTRACE("eventfd created") (ret) (initval) (flags);
 149     EventConnList::instance().add(ret, new EventFdConnection(initval, flags));
 150   }
 151   DMTCP_PLUGIN_ENABLE_CKPT();
 152   return ret;
 153 }
 154 #endif
 155 
 156 #ifdef HAVE_SYS_EPOLL_H
 157 extern "C" int epoll_create(int size)
 158 {
 159   DMTCP_PLUGIN_DISABLE_CKPT();
 160   int ret = _real_epoll_create(size);
 161   if (ret != -1) {
 162     JTRACE("epoll fd created") (ret) (size);
 163     EventConnList::instance().add(ret, new EpollConnection(size));
 164   }
 165   DMTCP_PLUGIN_ENABLE_CKPT();
 166   return ret;
 167 }
 168 
 169 extern "C" int epoll_create1(int flags)
 170 {
 171   DMTCP_PLUGIN_DISABLE_CKPT();
 172   int ret = _real_epoll_create1(flags);
 173   if (ret != -1) {
 174     JTRACE("epoll fd created1") (ret) (flags);
 175     EventConnList::instance().add(ret, new EpollConnection(flags));
 176   }
 177   DMTCP_PLUGIN_ENABLE_CKPT();
 178   return ret;
 179 }
 180 
 181 extern "C" int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
 182 {
 183   DMTCP_PLUGIN_DISABLE_CKPT();
 184   int ret = _real_epoll_ctl(epfd, op, fd, event);
 185   if (ret != -1) {
 186     //JTRACE("epoll fd CTL") (ret) (epfd) (fd) (op);
 187     EpollConnection *con =
 188       (EpollConnection*) EventConnList::instance().getConnection(epfd);
 189     con->onCTL(op, fd, event);
 190   }
 191   DMTCP_PLUGIN_ENABLE_CKPT();
 192   return ret;
 193 }
 194 
 195 extern "C" int epoll_wait(int epfd, struct epoll_event *events, int maxevents,
 196                           int timeout)
 197 {
 198   int readyFds = 0;
 199   int timeLeft = timeout;
 200   int mytime;
 201 //  JTRACE("Starting to do wait on epoll fd");
 202 
 203   if (timeout >= 0 && timeout < 1000) {
 204     // Short time intervals
 205     DMTCP_PLUGIN_DISABLE_CKPT();
 206     readyFds = _real_epoll_wait(epfd, events, maxevents, timeout);
 207     DMTCP_PLUGIN_ENABLE_CKPT();
 208     return readyFds;
 209   } else if (timeout >= 1000) {
 210     mytime = 1000; // wait time quanta: 1000 ms
 211   } else {
 212     // In case of indefinite timeout, start with 0 and increment by 1ms.
 213     mytime = 0;
 214   }
 215 
 216   do {
 217     DMTCP_PLUGIN_DISABLE_CKPT();
 218     readyFds = _real_epoll_wait(epfd, events, maxevents, mytime);
 219     DMTCP_PLUGIN_ENABLE_CKPT();
 220     if (timeout < 0 && mytime <= 100) {
 221       // Increase timeout if we are going to wait forever.
 222       mytime += 1;
 223     } else {
 224       timeLeft -= mytime;
 225     }
 226   } while ((timeLeft > 0 || timeout < 0) && readyFds == 0);
 227   return readyFds;
 228 }
 229 #endif
 230 
 231 
 232 #ifdef HAVE_SYS_INOTIFY_H
 233 #ifndef DMTCP_USE_INOTIFY
 234 EXTERNC int inotify_init()
 235 {
 236   JWARNING(false) .Text("Inotify not yet supported by DMTCP");
 237   errno = ENOMEM;
 238   return -1;
 239 }
 240 
 241 EXTERNC int inotify_init1(int flags)
 242 {
 243   JWARNING(false) .Text("Inotify not yet supported by DMTCP");
 244   errno = ENOMEM;
 245   return -1;
 246 }
 247 #else
 248 /******************************************************************
 249  * function name: inotify_init()
 250  *
 251  * description:   monitors file system events
 252  *
 253  * para:          none
 254  * return:        fd (inotify instance)
 255  ******************************************************************/
 256 EXTERNC int inotify_init()
 257 {
 258   int fd;
 259   DMTCP_PLUGIN_DISABLE_CKPT();
 260   JTRACE("Starting to create an inotify fd.");
 261   fd = _real_inotify_init();
 262   if (fd > 0) {
 263     JTRACE ( "inotify fd created" ) ( ret );
 264     //create the inotify object
 265     Connection *con = new InotifyConnection(0);
 266     EventConnList::instance().add(ret, con);
 267   }
 268   DMTCP_PLUGIN_ENABLE_CKPT();
 269   return fd;
 270 }
 271 
 272 /******************************************************************
 273  * function name: inotify_init1()
 274  *
 275  * description:   monitors file system events
 276  *
 277  * para:          flags
 278  * return:        fd (inotify instance)
 279  ******************************************************************/
 280 EXTERNC int inotify_init1(int flags)
 281 {
 282   DMTCP_PLUGIN_DISABLE_CKPT();
 283   int ret = _real_inotify_init1(flags);
 284   if (ret != -1) {
 285     JTRACE("inotify1 fd created") (ret) (flags);
 286     Connection *con = new InotifyConnection(flags);
 287     EventConnList::instance().add(ret, flags);
 288   }
 289   DMTCP_PLUGIN_ENABLE_CKPT();
 290   return ret;
 291 }
 292 
 293 /******************************************************************
 294  * function name: inotify_add_watch()
 295  *
 296  * description:   adds a directory or file to be watched
 297  *
 298  * para:          fd        - inotify instance
 299  * para:          pathname  - directory or file
 300  * para:          mask      - events to be monitored on pathname
 301  * return:        watch descriptor (wd) on success, -1 on failure
 302  ******************************************************************/
 303 EXTERNC int inotify_add_watch(int fd, const char *pathname, uint32_t mask)
 304 {
 305   DMTCP_PLUGIN_DISABLE_CKPT();
 306   int ret = _real_inotify_add_watch(fd, pathname, mask);
 307   if (ret != -1) {
 308     JTRACE("calling inotify class methods");
 309     InotifyConnection& inotify_con =
 310       (InotifyConnection*) EventConnList::instance().getConnection(fd);
 311 
 312     inotify_con->add_watch_descriptors(ret, fd, pathname, mask);
 313     /*temp_pathname = pathname;
 314       inotify_con.map_inotify_fd_to_wd ( fd, ret);
 315       inotify_con.map_wd_to_pathname(ret, temp_pathname);
 316       inotify_con.map_pathname_to_mask(temp_pathname, mask);*/
 317   }
 318   DMTCP_PLUGIN_ENABLE_CKPT();
 319   return ret;
 320 }
 321 
 322 /******************************************************************
 323  * function name: inotify_rm_watch()
 324  *
 325  * description:   removes the watch descriptor associated with
 326  *                the inotify instance
 327  *
 328  * para:          fd        - inotify instance
 329  * para:          wd        - watch descriptor to be removed
 330  * return:        0 on success, -1 on failure
 331  ******************************************************************/
 332 EXTERNC int inotify_rm_watch(int fd, int wd)
 333 {
 334   DMTCP_PLUGIN_DISABLE_CKPT(); // The lock is released inside the macro.
 335   int ret = _real_inotify_rm_watch(fd, wd);
 336   if (ret != -1) {
 337     JTRACE("remove inotify mapping from dmtcp") (ret) (fd) (wd);
 338     InotifyConnection& inotify_con =
 339       (InotifyConnection*) EventConnList::instance().getConnection(fd);
 340     //inotify_con.remove_mappings(fd, wd);
 341     inotify_con->remove_watch_descriptors(wd);
 342   }
 343   DMTCP_PLUGIN_ENABLE_CKPT();
 344   return ret;
 345 }
 346 #endif
 347 #endif

/* [<][>][^][v][top][bottom][index][help] */