Changeset 04aaf954817d7e85e9daf2feb52c9411d1acb30f

Show
Ignore:
Timestamp:
12/04/08 22:19:49 (6 years ago)
Author:
Theo Schlossnagle <jesus@omniti.com>
git-committer:
Theo Schlossnagle <jesus@omniti.com> 1228429189 +0000
git-parent:

[df2e1eb8a0d6b779a1327d8df4d867b961ce4b07]

git-author:
Theo Schlossnagle <jesus@omniti.com> 1228429189 +0000
Message:

Add trigger support, compiles on Mac OS X and Solaris, changes made to Linux, but untested (even compile), refs #65

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • src/eventer/eventer.h

    rdf2e1eb r04aaf95  
    7878  eventer_t         (*remove_fd)(int fd); 
    7979  eventer_t         (*find_fd)(int fd); 
     80  void              (*trigger)(eventer_t e, int mask); 
    8081  int               (*loop)(); 
    8182} *eventer_impl_t; 
     
    99100#define eventer_find_fd       __eventer->find_fd 
    100101#define eventer_loop          __eventer->loop 
     102#define eventer_trigger       __eventer->trigger 
    101103 
    102104extern eventer_impl_t registered_eventers[]; 
  • src/eventer/eventer_epoll_impl.c

    rdf2e1eb r04aaf95  
    196196static eventer_t eventer_epoll_impl_find_fd(int fd) { 
    197197  return master_fds[fd].e; 
     198} 
     199 
     200static void eventer_epoll_impl_trigger(eventer_t e, int mask) { 
     201  struct timeval __now; 
     202  int fd, oldmask, newmask; 
     203  const char *cbname; 
     204  ev_lock_state_t lockstate; 
     205 
     206  fd = e->fd; 
     207  if(e != master_fds[fd].e) return; 
     208  lockstate = acquire_master_fd(fd); 
     209  if(lockstate == EV_ALREADY_OWNED) return; 
     210  assert(lockstate == EV_OWNED); 
     211 
     212  gettimeofday(&__now, NULL); 
     213  oldmask = e->mask; 
     214  cbname = eventer_name_for_callback(e->callback); 
     215  noitLT(eventer_deb, &__now, "epoll: fire on %d/%x to %s(%p)\n", 
     216         fd, mask, cbname?cbname:"???", e->callback); 
     217  newmask = e->callback(e, mask, e->closure, &__now); 
     218 
     219  if(newmask) { 
     220    struct epoll_event _ev; 
     221    memset(&_ev, 0, sizeof(_ev)); 
     222    _ev.data.fd = fd; 
     223    if(newmask & EVENTER_READ) _ev.events |= (EPOLLIN|EPOLLPRI); 
     224    if(newmask & EVENTER_WRITE) _ev.events |= (EPOLLOUT); 
     225    if(newmask & EVENTER_EXCEPTION) _ev.events |= (EPOLLERR|EPOLLHUP); 
     226    epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &_ev); 
     227    /* Set our mask */ 
     228    e->mask = newmask; 
     229  } 
     230  else { 
     231    /* see kqueue implementation for details on the next line */ 
     232    if(master_fds[fd].e == e) master_fds[fd].e = NULL; 
     233    eventer_free(e); 
     234  } 
     235  release_master_fd(fd, lockstate); 
    198236} 
    199237static int eventer_epoll_impl_loop() { 
     
    269307      for(idx = 0; idx < fd_cnt; idx++) { 
    270308        struct epoll_event *ev; 
    271         const char *cbname; 
    272         ev_lock_state_t lockstate; 
    273309        eventer_t e; 
    274         int fd, oldmask, mask = 0; 
     310        int fd, mask = 0; 
    275311 
    276312        ev = &epev[idx]; 
     
    281317 
    282318        fd = ev->data.fd; 
     319 
    283320        e = master_fds[fd].e; 
    284321        /* It's possible that someone removed the event and freed it 
     
    287324        if(!e) continue; 
    288325 
    289  
    290         lockstate = acquire_master_fd(fd); 
    291         assert(lockstate == EV_OWNED); 
    292  
    293         gettimeofday(&__now, NULL); 
    294         oldmask = e->mask; 
    295         cbname = eventer_name_for_callback(e->callback); 
    296         noitLT(eventer_deb, &__now, "epoll: fire on %d/%x to %s(%p)\n", 
    297                fd, mask, cbname?cbname:"???", e->callback); 
    298         newmask = e->callback(e, mask, e->closure, &__now); 
    299  
    300         if(newmask) { 
    301           struct epoll_event _ev; 
    302           memset(&_ev, 0, sizeof(_ev)); 
    303           _ev.data.fd = fd; 
    304           if(newmask & EVENTER_READ) _ev.events |= (EPOLLIN|EPOLLPRI); 
    305           if(newmask & EVENTER_WRITE) _ev.events |= (EPOLLOUT); 
    306           if(newmask & EVENTER_EXCEPTION) _ev.events |= (EPOLLERR|EPOLLHUP); 
    307           epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &_ev); 
    308           /* Set our mask */ 
    309           e->mask = newmask; 
    310         } 
    311         else { 
    312           /* see kqueue implementation for details on the next line */ 
    313           if(master_fds[fd].e == e) master_fds[fd].e = NULL; 
    314           eventer_free(e); 
    315         } 
    316         release_master_fd(fd, lockstate); 
     326        eventer_epoll_impl_trigger(e, mask); 
    317327      } 
    318328    } 
  • src/eventer/eventer_kqueue_impl.c

    rdf2e1eb r04aaf95  
    251251static eventer_t eventer_kqueue_impl_find_fd(int fd) { 
    252252  return master_fds[fd].e; 
     253} 
     254static void eventer_kqueue_impl_trigger(eventer_t e, int mask) { 
     255  ev_lock_state_t lockstate; 
     256  struct timeval __now; 
     257  int oldmask, newmask; 
     258  const char *cbname; 
     259  int fd; 
     260 
     261  fd = e->fd; 
     262  if(e != master_fds[fd].e) return; 
     263  lockstate = acquire_master_fd(fd); 
     264  if(lockstate == EV_ALREADY_OWNED) return; 
     265  assert(lockstate == EV_OWNED); 
     266 
     267  gettimeofday(&__now, NULL); 
     268  oldmask = e->mask; 
     269  cbname = eventer_name_for_callback(e->callback); 
     270  noitLT(eventer_deb, &__now, "kqueue: fire on %d/%x to %s(%p)\n", 
     271         fd, masks[fd], cbname?cbname:"???", e->callback); 
     272  newmask = e->callback(e, mask, e->closure, &__now); 
     273 
     274  if(newmask) { 
     275    /* toggle the read bits if needed */ 
     276    if(newmask & (EVENTER_READ | EVENTER_EXCEPTION)) { 
     277      if(!(oldmask & (EVENTER_READ | EVENTER_EXCEPTION))) 
     278        ke_change(fd, EVFILT_READ, EV_ADD | EV_ENABLE, e); 
     279    } 
     280    else if(oldmask & (EVENTER_READ | EVENTER_EXCEPTION)) 
     281      ke_change(fd, EVFILT_READ, EV_DELETE | EV_DISABLE, e); 
     282 
     283    /* toggle the write bits if needed */ 
     284    if(newmask & EVENTER_WRITE) { 
     285      if(!(oldmask & EVENTER_WRITE)) 
     286        ke_change(fd, EVFILT_WRITE, EV_ADD | EV_ENABLE, e); 
     287    } 
     288    else if(oldmask & EVENTER_WRITE) 
     289        ke_change(fd, EVFILT_WRITE, EV_DELETE | EV_DISABLE, e); 
     290 
     291    /* Set our mask */ 
     292    e->mask = newmask; 
     293  } 
     294  else { 
     295    /* 
     296     * Long story long: 
     297     *  When integrating with a few external event systems, we find 
     298     *  it difficult to make their use of remove+add as an update 
     299     *  as it can be recurrent in a single handler call and you cannot 
     300     *  remove completely from the event system if you are going to 
     301     *  just update (otherwise the eventer_t in your call stack could 
     302     *  be stale).  What we do is perform a superficial remove, marking 
     303     *  the mask as 0, but not eventer_remove_fd.  Then on an add, if 
     304     *  we already have an event, we just update the mask (as we 
     305     *  have not yet returned to the eventer's loop. 
     306     *  This leaves us in a tricky situation when a remove is called 
     307     *  and the add doesn't roll in, we return 0 (mask == 0) and hit 
     308     *  this spot.  We have intended to remove the event, but it still 
     309     *  resides at master_fds[fd].e -- even after we free it. 
     310     *  So, in the evnet that we return 0 and the event that 
     311     *  master_fds[fd].e == the event we're about to free... we NULL 
     312     *  it out. 
     313     */ 
     314    if(master_fds[fd].e == e) master_fds[fd].e = NULL; 
     315    eventer_free(e); 
     316  } 
     317  release_master_fd(fd, lockstate); 
    253318} 
    254319static int eventer_kqueue_impl_loop() { 
     
    366431      /* Loop a last time to process */ 
    367432      for(idx = 0; idx < fd_cnt; idx++) { 
    368         ev_lock_state_t lockstate; 
    369433        struct kevent *ke; 
    370434        eventer_t e; 
    371         int fd, oldmask
     435        int fd
    372436 
    373437        ke = &ke_vec[idx]; 
    374438        if(ke->flags & EV_ERROR) { 
    375439          if(ke->data != EBADF) 
    376             noitLT(eventer_err, &__now, "error: %s\n", strerror(ke->data)); 
     440            noitLT(eventer_err, &__now, "error [%d]: %s\n", 
     441                   (int)ke->ident, strerror(ke->data)); 
    377442          continue; 
    378443        } 
     
    384449         * before we got here. 
    385450         */ 
    386         if(e != master_fds[fd].e) continue; 
    387         lockstate = acquire_master_fd(fd); 
    388         assert(lockstate == EV_OWNED); 
    389  
    390         gettimeofday(&__now, NULL); 
    391         oldmask = e->mask; 
    392         cbname = eventer_name_for_callback(e->callback); 
    393         noitLT(eventer_deb, &__now, "kqueue: fire on %d/%x to %s(%p)\n", 
    394                fd, masks[fd], cbname?cbname:"???", e->callback); 
    395         newmask = e->callback(e, masks[fd], e->closure, &__now); 
     451        eventer_kqueue_impl_trigger(e, masks[fd]); 
    396452        masks[fd] = 0; /* indicates we've processed this fd */ 
    397  
    398         if(newmask) { 
    399           /* toggle the read bits if needed */ 
    400           if(newmask & (EVENTER_READ | EVENTER_EXCEPTION)) { 
    401             if(!(oldmask & (EVENTER_READ | EVENTER_EXCEPTION))) 
    402               ke_change(fd, EVFILT_READ, EV_ADD | EV_ENABLE, e); 
    403           } 
    404           else if(oldmask & (EVENTER_READ | EVENTER_EXCEPTION)) 
    405             ke_change(fd, EVFILT_READ, EV_DELETE | EV_DISABLE, e); 
    406    
    407           /* toggle the write bits if needed */ 
    408           if(newmask & EVENTER_WRITE) { 
    409             if(!(oldmask & EVENTER_WRITE)) 
    410               ke_change(fd, EVFILT_WRITE, EV_ADD | EV_ENABLE, e); 
    411           } 
    412           else if(oldmask & EVENTER_WRITE) 
    413               ke_change(fd, EVFILT_WRITE, EV_DELETE | EV_DISABLE, e); 
    414    
    415           /* Set our mask */ 
    416           e->mask = newmask; 
    417         } 
    418         else { 
    419           /* 
    420            * Long story long: 
    421            *  When integrating with a few external event systems, we find 
    422            *  it difficult to make their use of remove+add as an update 
    423            *  as it can be recurrent in a single handler call and you cannot 
    424            *  remove completely from the event system if you are going to 
    425            *  just update (otherwise the eventer_t in your call stack could 
    426            *  be stale).  What we do is perform a superficial remove, marking 
    427            *  the mask as 0, but not eventer_remove_fd.  Then on an add, if 
    428            *  we already have an event, we just update the mask (as we 
    429            *  have not yet returned to the eventer's loop. 
    430            *  This leaves us in a tricky situation when a remove is called 
    431            *  and the add doesn't roll in, we return 0 (mask == 0) and hit 
    432            *  this spot.  We have intended to remove the event, but it still 
    433            *  resides at master_fds[fd].e -- even after we free it. 
    434            *  So, in the evnet that we return 0 and the event that 
    435            *  master_fds[fd].e == the event we're about to free... we NULL 
    436            *  it out. 
    437            */ 
    438           if(master_fds[fd].e == e) master_fds[fd].e = NULL; 
    439           eventer_free(e); 
    440         } 
    441         release_master_fd(fd, lockstate); 
    442453      } 
    443454    } 
     
    456467  eventer_kqueue_impl_remove_fd, 
    457468  eventer_kqueue_impl_find_fd, 
     469  eventer_kqueue_impl_trigger, 
    458470  eventer_kqueue_impl_loop 
    459471}; 
  • src/eventer/eventer_ports_impl.c

    rdf2e1eb r04aaf95  
    201201static eventer_t eventer_ports_impl_find_fd(int fd) { 
    202202  return master_fds[fd].e; 
     203} 
     204static void 
     205eventer_ports_impl_trigger(eventer_t e, int mask) { 
     206  ev_lock_state_t lockstate; 
     207  const char *cbname; 
     208  struct timeval __now; 
     209  int fd, oldmask, newmask; 
     210 
     211  fd = e->fd; 
     212  if(e != master_fds[fd].e) return; 
     213  lockstate = acquire_master_fd(fd); 
     214  if(lockstate == EV_ALREADY_OWNED) return; 
     215  assert(lockstate == EV_OWNED); 
     216 
     217  gettimeofday(&__now, NULL); 
     218  oldmask = e->mask; 
     219  cbname = eventer_name_for_callback(e->callback); 
     220  noitLT(eventer_deb, &__now, "ports: fire on %d/%x to %s(%p)\n", 
     221         fd, mask, cbname?cbname:"???", e->callback); 
     222  newmask = e->callback(e, mask, e->closure, &__now); 
     223 
     224  if(newmask) { 
     225    alter_fd(e, newmask); 
     226    /* Set our mask */ 
     227    e->mask = newmask; 
     228  } 
     229  else { 
     230    /* 
     231     * Long story long: 
     232     *  When integrating with a few external event systems, we find 
     233     *  it difficult to make their use of remove+add as an update 
     234     *  as it can be recurrent in a single handler call and you cannot 
     235     *  remove completely from the event system if you are going to 
     236     *  just update (otherwise the eventer_t in your call stack could 
     237     *  be stale).  What we do is perform a superficial remove, marking 
     238     *  the mask as 0, but not eventer_remove_fd.  Then on an add, if 
     239     *  we already have an event, we just update the mask (as we 
     240     *  have not yet returned to the eventer's loop. 
     241     *  This leaves us in a tricky situation when a remove is called 
     242     *  and the add doesn't roll in, we return 0 (mask == 0) and hit 
     243     *  this spot.  We have intended to remove the event, but it still 
     244     *  resides at master_fds[fd].e -- even after we free it. 
     245     *  So, in the evnet that we return 0 and the event that 
     246     *  master_fds[fd].e == the event we're about to free... we NULL 
     247     *  it out. 
     248     */ 
     249    if(master_fds[fd].e == e) master_fds[fd].e = NULL; 
     250    eventer_free(e); 
     251  } 
     252  release_master_fd(fd, lockstate); 
    203253} 
    204254static int eventer_ports_impl_loop() { 
     
    285335      /* Loop a last time to process */ 
    286336      for(idx = 0; idx < fd_cnt; idx++) { 
    287         ev_lock_state_t lockstate; 
    288337        port_event_t *pe; 
    289338        eventer_t e; 
     
    305354         * before we got here. 
    306355         */ 
    307         if(e != master_fds[fd].e) continue; 
    308         lockstate = acquire_master_fd(fd); 
    309         assert(lockstate == EV_OWNED); 
    310  
    311         gettimeofday(&__now, NULL); 
    312         oldmask = e->mask; 
    313         cbname = eventer_name_for_callback(e->callback); 
    314         noitLT(eventer_deb, &__now, "ports: fire on %d/%x to %s(%p)\n", 
    315                fd, mask, cbname?cbname:"???", e->callback); 
    316         newmask = e->callback(e, mask, e->closure, &__now); 
    317  
    318         if(newmask) { 
    319           alter_fd(e, newmask); 
    320           /* Set our mask */ 
    321           e->mask = newmask; 
    322         } 
    323         else { 
    324           /* 
    325            * Long story long: 
    326            *  When integrating with a few external event systems, we find 
    327            *  it difficult to make their use of remove+add as an update 
    328            *  as it can be recurrent in a single handler call and you cannot 
    329            *  remove completely from the event system if you are going to 
    330            *  just update (otherwise the eventer_t in your call stack could 
    331            *  be stale).  What we do is perform a superficial remove, marking 
    332            *  the mask as 0, but not eventer_remove_fd.  Then on an add, if 
    333            *  we already have an event, we just update the mask (as we 
    334            *  have not yet returned to the eventer's loop. 
    335            *  This leaves us in a tricky situation when a remove is called 
    336            *  and the add doesn't roll in, we return 0 (mask == 0) and hit 
    337            *  this spot.  We have intended to remove the event, but it still 
    338            *  resides at master_fds[fd].e -- even after we free it. 
    339            *  So, in the evnet that we return 0 and the event that 
    340            *  master_fds[fd].e == the event we're about to free... we NULL 
    341            *  it out. 
    342            */ 
    343           if(master_fds[fd].e == e) master_fds[fd].e = NULL; 
    344           eventer_free(e); 
    345         } 
    346         release_master_fd(fd, lockstate); 
     356        eventer_ports_impl_trigger(e, mask); 
    347357      } 
    348358    } 
     
    360370  eventer_ports_impl_remove_fd, 
    361371  eventer_ports_impl_find_fd, 
     372  eventer_ports_impl_trigger, 
    362373  eventer_ports_impl_loop 
    363374};