Re: [PATCH v2] epoll: Support for disabling items, and a self-test app.

Started by Michael Kerrisk (man-pages) on Oct 25, 2012 · 2 messages from 2 authors · Last reply Oct 26, 2012

open the first message on its own page

Message details and related content
Hi Pat,

quoted
I suppose that I have a concern that goes in the other direction. Is
there not some other solution possible that doesn't require the use of
EPOLLONESHOT? It seems overly restrictive to require that the caller
must employ this flag, and imposes the burden that the caller must
re-enable monitoring after each event.

Does a solution like the following (with no requirement for EPOLLONESHOT)
work?

0. Implement an epoll_ctl() operation EPOLL_CTL_XXX
   where the name XXX might be chosen based on the decision
   in 4(a).
1. EPOLL_CTL_XXX employs a private flag, EPOLLUSED, in the
   per-fd events mask in the ready list. By default,
   that flag is off.
2. epoll_wait() always clears the EPOLLUSED flag if a
   file descriptor is found to be ready.
3. If an epoll_ctl(EPOLL_CTL_XXX) discovers that the EPOLLUSED
   flag is NOT set, then
        a) it sets the EPOLLUSED flag
        b) It disables I/O events (as per EPOLL_CTL_DISABLE)
           (I'm not 100% sure if this is necesary).
        c) it returns EBUSY to the caller
4. If an epoll_ctl(EPOLL_CTL_XXX) discovers that the EPOLLUSED
   flag IS set, then it
        a) either deletes the fd or disables events for the fd
           (the choice here is a matter of design taste, I think;
           deletion has the virtue of simplicity; disabling provides
           the option to re-enable the fd later, if desired)
        b) returns 0 to the caller.

All of the above with suitable locking around the user-space cache.

Cheers,

Michael

I don't believe that proposal will solve the problem. Consider the case
where a worker thread has just executed epoll_wait and is about to execute

6 more quoted lines

Okay -- I had the idea there might be a hole in my proposal ;-).

By the way, have you been reading the comments in the two LWN articles
on EPOLL_CTL_DISABLE?
https://lwn.net/Articles/520012/
http://lwn.net/SubscriberLink/520198/fd81ba0ecb1858a2/

There's some interesting proposals there--some suggesting that an
entirely user-space solution might be possible. I haven't looked
deeply into the ideas though.

Cheers,

Michael


-- 
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Author of "The Linux Programming Interface"; http://man7.org/tlpi/
Message details and related content
On Thu, Oct 25, 2012 at 12:23:24PM +0200, Michael Kerrisk (man-pages) wrote:
Hi Pat,

quoted
quoted
I suppose that I have a concern that goes in the other direction. Is
there not some other solution possible that doesn't require the use of
EPOLLONESHOT? It seems overly restrictive to require that the caller
must employ this flag, and imposes the burden that the caller must
re-enable monitoring after each event.

Does a solution like the following (with no requirement for EPOLLONESHOT)
work?

0. Implement an epoll_ctl() operation EPOLL_CTL_XXX
   where the name XXX might be chosen based on the decision
   in 4(a).
1. EPOLL_CTL_XXX employs a private flag, EPOLLUSED, in the
   per-fd events mask in the ready list. By default,
   that flag is off.
2. epoll_wait() always clears the EPOLLUSED flag if a
   file descriptor is found to be ready.
3. If an epoll_ctl(EPOLL_CTL_XXX) discovers that the EPOLLUSED
   flag is NOT set, then
        a) it sets the EPOLLUSED flag
        b) It disables I/O events (as per EPOLL_CTL_DISABLE)
           (I'm not 100% sure if this is necesary).
        c) it returns EBUSY to the caller
4. If an epoll_ctl(EPOLL_CTL_XXX) discovers that the EPOLLUSED
   flag IS set, then it
        a) either deletes the fd or disables events for the fd
           (the choice here is a matter of design taste, I think;
           deletion has the virtue of simplicity; disabling provides
           the option to re-enable the fd later, if desired)
        b) returns 0 to the caller.

All of the above with suitable locking around the user-space cache.

Cheers,

Michael

20 more quoted lines

Yeah, I became quite interested so I wrote a crude epoll + urcu test.
Since it's RCU review to ensure I've not made any serious mistakes could
be quite helpful:

#define _LGPL_SOURCE 1
#define _GNU_SOURCE 1

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>

#include <sys/epoll.h>

/*
 * Locking Voodoo:
 *
 * The globabls prefixed by _ require special care because they will be
 * accessed from multiple threads.
 *
 * The precise locking scheme we use varies whether READERS_USE_MUTEX is defined
 * When we're using userspace RCU the mutex only gets acquired for writes
 *     to _-prefixed globals. Reads are done inside RCU read side critical
 *     sections.
 * Otherwise the epmutex covers reads and writes to them all and the test
 * is not very scalable.
 */
static pthread_mutex_t epmutex = PTHREAD_MUTEX_INITIALIZER;
static int _p[2]; /* Send dummy data from one thread to another */
static int _epfd; /* Threads wait to read/write on epfd */
static int _nepitems = 0;

#ifdef READERS_USE_MUTEX
#define init_lock() do {} while(0)
#define init_thread() do {} while(0)

226 more lines

Keyboard shortcuts
hback out one level
jnext message in thread / next series-diff position
kprevious message in thread / previous series-diff position
ldrill in
Escclose help / fold thread tree
?toggle this help