change poll and select to epoll - Linux

This is a discussion on change poll and select to epoll - Linux ; hi all, now I want change poll and select to epoll call in squid 2.5.6, is it difficult to do that ? I know squid3.0 using epoll, but I have to modify 2.5.6, I found in comm_select.c: for (; { ...

+ Reply to Thread
Results 1 to 7 of 7

Thread: change poll and select to epoll

  1. change poll and select to epoll

    hi all,

    now I want change poll and select to epoll call in squid 2.5.6, is
    it difficult to do that ? I know squid3.0 using epoll, but I have to
    modify 2.5.6, I found in comm_select.c:
    for (; {
    statCounter.syscalls.polls++;
    num = poll(pfds, nfds, msec);


    but I don't know how to change it to epoll, someone can give me an
    example? thanks

  2. Re: change poll and select to epoll

    On Nov 5, 7:04*pm, "yikai...@gmail.com" wrote:
    > hi all,
    >
    > * * now I want change poll and select to epoll call in squid 2.5.6, is
    > it difficult to do that ? *I know squid3.0 using epoll, but I have to
    > modify 2.5.6, I found in comm_select.c:
    > * * * * for (; {
    > * * * * * * statCounter.syscalls.polls++;
    > * * * * * * num = poll(pfds, nfds, msec);
    >
    > but I don't know how to change it to epoll, someone can give me an
    > example? *thanks


    I wouldn't bother. Either upgrade to Squid 3.0 or live with 'poll'.

    If you absolutely, positively must, you can make a 'poll' wrapper. The
    logic is like this:

    1) Compare the input poll set to the poll set on the previous call to
    'poll'. For any differences you find, use 'epoll_ctl' to update the
    event set in the kernel to match that of squid.

    2) Save a copy of the current poll set for the next call to 'poll'.

    3) Call 'epoll_wait'.

    4) Set the returned events in the input poll set to all zeroes. The
    update the returned events in the input poll set based on any events
    returned from 'epoll_wait'.

    5) Return the appropriate return code.

    This will only work if all calls to 'poll' are coming from
    substantially the same code to substantially the same set of
    descriptors. I would think this would be the case for squid2, but I
    don't know for sure.

    DS

  3. Re: change poll and select to epoll

    I got bored. Here's your 100% untested drop-in epoll-based replacement
    for 'poll'. It may or may not work. It compiles, but is untested"

    #include
    #include

    /*
    Drop in poll->epoll upgrader
    By: David J. Schwartz, Copyright 2008,
    May or may not be suitable for your application! CAUTION!

    Redistribution and use in source and binary forms, with or without
    modification, are permitted. This software is provided 'as is' and
    no representation is made that it is suitable for any purpose. It
    has
    not been debugged or tested in any way.

    CAUTION: This drop-in replacement for 'poll' using 'epoll' may or
    may not improve performance and may or may not break your code!
    It is definitely inferior to modifying the code itself to use
    'epoll'.
    It will fail horribly if the program using it generates calls to
    'poll_epoll' from more than one place with fundamentally different
    'ufds' parameters!
    */

    static int epoll_fd=-1;
    static struct epoll_event epoll_ev[32768];
    static int reg_ev[65536];

    int poll_epoll(struct pollfd *ufds, nfds_t nfds, int timeout)
    {
    int i, j, rc, ec;

    /*
    First step: Make sure we have an epoll fd. Sanity checks.
    Initialization if needed.
    */

    if(epoll_fd<0)
    {
    if(epoll_fd==-2) return poll(ufds, nfds, timeout);
    epoll_fd=epoll_create(32768);
    if(epoll_fd<0)
    {
    epoll_fd=-2;
    return poll(ufds, nfds, timeout);
    }
    for(i=0; i<65536; i++) reg_ev[i]=0;
    }

    /*
    Second step: Add any missing events.
    Extra events are okay, we'll catch them in step four.
    */
    for(i=0; i {
    ufds[i].revents=0;
    int fd=ufds[i].fd;
    if(fd>=0)
    { /* This is a valid test for events */
    ufds[i].revents=0;
    if(reg_ev[fd]!=ufds[i].events)
    {
    int missing_events=ufds[i].events&~reg_ev[i];
    if(missing_events!=0)
    { /* we need to add at least one event */
    struct epoll_event ev;
    ev.data.fd=fd;
    ev.events=reg_ev[i]|missing_events;
    epoll_ctl(epoll_fd, (reg_ev[fd]==0) ? EPOLL_CTL_ADD :
    EPOLL_CTL_MOD,
    fd, &ev);
    reg_ev[i]=ev.events;
    }
    }
    }
    }

    /*
    Third step: Call epoll. Return error, if any
    */
    rc=epoll_wait(epoll_fd, epoll_ev, 32768, timeout);
    if(rc<=0) return rc;

    /*
    Fourth step: Report events, unregister unwanted ones
    */
    ec=0;
    for(i=0; i {
    int fd=epoll_ev[j].data.fd;
    int needed_events=0;
    int remaining_events=epoll_ev[j].events;
    for(j=0; j if(fd==ufds[i].fd)
    { /* we found a hit on an FD that we are interested in */
    int report=ufds[i].events|POLLHUP|POLLNVAL|POLLERR;
    needed_events|=report; // still interested in these
    remaining_events&=~report; // still not interested in these
    ufds[i].revents=epoll_ev[j].events&report;
    if(ufds[i].revents!=0) ec++;
    }
    if(remaining_events)
    { /* we found some events we could not report */
    struct epoll_event ev;
    ev.data.fd=fd;
    ev.events=needed_events;
    epoll_ctl(epoll_fd, (needed_events==0) ? EPOLL_CTL_DEL :
    EPOLL_CTL_MOD,
    fd, &ev);
    }
    }

    return ec;
    }


  4. Re: change poll and select to epoll


    Sorry to reply to myself again. Here it is with some loop variable
    bugs fixed. This passes, at least, the Apache APR poll test. I
    verified with 'strace' that it was calling the various 'epoll'
    functions.

    #include
    #include

    /*
    Drop in poll->epoll upgrader
    By: David J. Schwartz, Copyright 2008,
    May or may not be suitable for your application! CAUTION!

    Redistribution and use in source and binary forms, with or without
    modification, are permitted. This software is provided 'as is' and
    no representation is made that it is suitable for any purpose. It
    has
    not been debugged or tested in any way.

    CAUTION: This drop-in replacement for 'poll' using 'epoll' may or
    may not improve performance and may or may not break your code!
    It is definitely inferior to modifying the code itself to use
    'epoll'.
    It will fail horribly if the program using it generates calls to
    'poll_epoll' from more than one place with fundamentally different
    'ufds' parameters!
    */

    static int epoll_fd=-1;
    static struct epoll_event epoll_ev[32768];
    static int reg_ev[65536];

    int poll_epoll(struct pollfd *ufds, nfds_t nfds, int timeout)
    {
    int i, j, rc, ec;

    /*
    First step: Make sure we have an epoll fd. Sanity checks.
    Initialization if needed.
    */

    if(epoll_fd<0)
    {
    if(epoll_fd==-2) return poll(ufds, nfds, timeout);
    epoll_fd=epoll_create(32768);
    if(epoll_fd<0)
    {
    epoll_fd=-2;
    return poll(ufds, nfds, timeout);
    }
    for(i=0; i<65536; i++) reg_ev[i]=0;
    }

    /*
    Second step: Add any missing events.
    Extra events are okay, we'll catch them in step four.
    */
    for(i=0; i {
    ufds[i].revents=0;
    int fd=ufds[i].fd;
    if(fd>=0)
    { /* This is a valid test for events */
    ufds[i].revents=0;
    if(reg_ev[fd]!=ufds[i].events)
    {
    int missing_events=ufds[i].events&~reg_ev[i];
    if(missing_events!=0)
    { /* we need to add at least one event */
    struct epoll_event ev;
    ev.data.fd=fd;
    ev.events=reg_ev[i]|missing_events;
    epoll_ctl(epoll_fd, (reg_ev[fd]==0) ? EPOLL_CTL_ADD :
    EPOLL_CTL_MOD,
    fd, &ev);
    reg_ev[i]=ev.events;
    }
    }
    }
    }

    /*
    Third step: Call epoll. Return error, if any
    */
    rc=epoll_wait(epoll_fd, epoll_ev, 32768, timeout);
    if(rc<=0) return rc;

    /*
    Fourth step: Report events, unregister unwanted ones
    */
    ec=0;
    for(i=0; i {
    int fd=epoll_ev[i].data.fd;
    int needed_events=0;
    int remaining_events=epoll_ev[i].events;
    for(j=0; j if(fd==ufds[j].fd)
    { /* we found a hit on an FD that we are interested in */
    int report=ufds[j].events|POLLHUP|POLLNVAL|POLLERR;
    needed_events|=report; // still interested in these
    remaining_events&=~report; // still not interested in these
    ufds[j].revents=epoll_ev[i].events&report;
    if(ufds[j].revents!=0) ec++;
    }
    if(remaining_events)
    { /* we found some events we could not report */
    struct epoll_event ev;
    ev.data.fd=fd;
    ev.events=needed_events;
    epoll_ctl(epoll_fd, (needed_events==0) ? EPOLL_CTL_DEL :
    EPOLL_CTL_MOD,
    fd, &ev);
    }
    }

    return ec;
    }

  5. Re: change poll and select to epoll

    On Nov 5, 8:23*pm, David Schwartz wrote:

    Sorry to reply to myself yet again, I'm starting to feel like Skybuck.
    There was another serious bug. I should have just pointed to a web
    page in the first place. Sorry. Here's the one-liner fix:


    --- bad/poll_replace.c 2008-11-05 20:36:57.000000000 -0800
    +++ good/poll_replace.c 2008-11-05 20:36:57.000000000 -0800
    @@ -100,7 +100,7 @@ int poll_epoll(struct pollfd *ufds, nfds
    { /* we found some events we could not report */
    struct epoll_event ev;
    ev.data.fd=fd;
    - ev.events=needed_events;
    + ev.events=ref_ev[j]=needed_events;
    epoll_ctl(epoll_fd, (needed_events==0) ? EPOLL_CTL_DEL :
    EPOLL_CTL_MOD,
    fd, &ev);
    }

    Sadly, this is a serious bug. It could cause us to permanently lose
    events. I will put maintain a version with a version number and all
    current bugfixes at the following URL:
    http://beta.webmaster.com/poll_replace.c

    Sorry again.

    DS

  6. Re: change poll and select to epoll

    On Nov 5, 8:39*pm, David Schwartz wrote:

    > URL:http://beta.webmaster.com/poll_replace.c


    I tested this version of the patch on an old IRC server codebase from
    2005. Using 'poll' directly, it used 60% of the CPU, and still fell
    behind, dropping many of the test clients due to send queues being
    exceeded. With the patch, the CPU was at 40%, and no test clients were
    dropped.

    I found that very, very surprising.

    DS

  7. Re: change poll and select to epoll

    Thank you for your code

    On Nov 6, 12:23*pm, David Schwartz wrote:

+ Reply to Thread