37

In Linux header file epoll.h, I found the following code:

enum EPOLL_EVENTS
{
    EPOLLIN = 0x001,
#define EPOLLIN EPOLLIN
...
}

What does it mean by #define EPOLLIN EPOLLIN?

xmllmx
  • 39,765
  • 26
  • 162
  • 323
  • 12
    It's probably to deal with code that has `#ifdef EPOLLIN` to check if that is defined or not. – tadman Jun 13 '20 at 04:05
  • 3
    May be is to be used in sentences like `#if EPOLLIN`. If you left it as `#define EPOLLIN`, then only can be used with `#ifdef` – Eduardo Pascual Aseff Jun 13 '20 at 04:08
  • Limited to your title, also the [glibc's stdio.h](https://github.com/lattera/glibc/blob/895ef79e04a953cac1493863bcae29ad85657ee1/libio/stdio.h#L140) uses a similar trick for `stdout`, `stdin` and `stderr`, but for a different purpose: make the standard happy. – Giovanni Cerretani Jun 13 '20 at 06:46
  • 1
    My guess would be that originally there were only `#define EPOLLIN 0x001` etc before they were put in an `enum`, and this preserves backward compatibility for code relying on the define. – Bergi Jun 13 '20 at 16:05
  • 1
    @Berge Yes, that's exactly it. In other C libraries, these macros expand directly to numeric constants. Glibc wants to set the values with an enum because that makes the symbolic names available to the debugger, but ISO C requires them to be preprocessor macros, so this is a hack to have it both ways. – zwol Jun 14 '20 at 02:03
  • ...Er, wait, we're not talking about errno codes here. Well, this enum+define hack was originally developed for the errno codes, where ISO C really does make that requirement, and now it's used for most of glibc's symbolic constants because it _is_ quite convenient to be able to do `#ifdef CONSTANT` no matter what CONSTANT is. And it's also convenient to be able to use CONSTANT in the debugger. – zwol Jun 14 '20 at 02:08

2 Answers2

30

This create a macro named EPOLLIN whose replacement text is also EPOLLIN.

This is most likely a way for the preprocessor to check which event codes are available and conditionally compile code as necessary. If we go to the git repo for glibc and look at the output of git blame we see the following for enum EPOLL_EVENTS:

ad3bf20c (Ulrich Drepper 2002-12-16 23:38:42 +0000  34) enum EPOLL_EVENTS
ad3bf20c (Ulrich Drepper 2002-12-16 23:38:42 +0000  35)   { 
ad3bf20c (Ulrich Drepper 2002-12-16 23:38:42 +0000  36)     EPOLLIN = 0x001,
ad3bf20c (Ulrich Drepper 2002-12-16 23:38:42 +0000  37) #define EPOLLIN EPOLLIN
ad3bf20c (Ulrich Drepper 2002-12-16 23:38:42 +0000  38)     EPOLLPRI = 0x002,
ad3bf20c (Ulrich Drepper 2002-12-16 23:38:42 +0000  39) #define EPOLLPRI EPOLLPRI
ad3bf20c (Ulrich Drepper 2002-12-16 23:38:42 +0000  40)     EPOLLOUT = 0x004,
ad3bf20c (Ulrich Drepper 2002-12-16 23:38:42 +0000  41) #define EPOLLOUT EPOLLOUT
ad3bf20c (Ulrich Drepper 2002-12-16 23:38:42 +0000  42)     EPOLLRDNORM = 0x040,
ad3bf20c (Ulrich Drepper 2002-12-16 23:38:42 +0000  43) #define EPOLLRDNORM EPOLLRDNORM
ad3bf20c (Ulrich Drepper 2002-12-16 23:38:42 +0000  44)     EPOLLRDBAND = 0x080,
ad3bf20c (Ulrich Drepper 2002-12-16 23:38:42 +0000  45) #define EPOLLRDBAND EPOLLRDBAND
ad3bf20c (Ulrich Drepper 2002-12-16 23:38:42 +0000  46)     EPOLLWRNORM = 0x100,
ad3bf20c (Ulrich Drepper 2002-12-16 23:38:42 +0000  47) #define EPOLLWRNORM EPOLLWRNORM
ad3bf20c (Ulrich Drepper 2002-12-16 23:38:42 +0000  48)     EPOLLWRBAND = 0x200,
ad3bf20c (Ulrich Drepper 2002-12-16 23:38:42 +0000  49) #define EPOLLWRBAND EPOLLWRBAND
ad3bf20c (Ulrich Drepper 2002-12-16 23:38:42 +0000  50)     EPOLLMSG = 0x400,
ad3bf20c (Ulrich Drepper 2002-12-16 23:38:42 +0000  51) #define EPOLLMSG EPOLLMSG
ad3bf20c (Ulrich Drepper 2002-12-16 23:38:42 +0000  52)     EPOLLERR = 0x008,
ad3bf20c (Ulrich Drepper 2002-12-16 23:38:42 +0000  53) #define EPOLLERR EPOLLERR
5e826ab5 (Ulrich Drepper 2003-03-25 01:14:36 +0000  54)     EPOLLHUP = 0x010,
ad3bf20c (Ulrich Drepper 2002-12-16 23:38:42 +0000  55) #define EPOLLHUP EPOLLHUP
94833f11 (Ulrich Drepper 2007-10-28 01:34:10 +0000  56)     EPOLLRDHUP = 0x2000,
94833f11 (Ulrich Drepper 2007-10-28 01:34:10 +0000  57) #define EPOLLRDHUP EPOLLRDHUP
981569c7 (Joseph Myers   2016-03-14 19:04:53 +0000  58)     EPOLLEXCLUSIVE = 1u << 28,
981569c7 (Joseph Myers   2016-03-14 19:04:53 +0000  59) #define EPOLLEXCLUSIVE EPOLLEXCLUSIVE
f8d44fdc (Andreas Jaeger 2012-07-26 13:11:33 +0200  60)     EPOLLWAKEUP = 1u << 29,
f8d44fdc (Andreas Jaeger 2012-07-26 13:11:33 +0200  61) #define EPOLLWAKEUP EPOLLWAKEUP
4920765e (Ulrich Drepper 2011-12-21 22:14:05 -0500  62)     EPOLLONESHOT = 1u << 30,
e11676dd (Ulrich Drepper 2004-01-21 06:23:26 +0000  63) #define EPOLLONESHOT EPOLLONESHOT
4920765e (Ulrich Drepper 2011-12-21 22:14:05 -0500  64)     EPOLLET = 1u << 31
5e826ab5 (Ulrich Drepper 2003-03-25 01:14:36 +0000  65) #define EPOLLET EPOLLET
ad3bf20c (Ulrich Drepper 2002-12-16 23:38:42 +0000  66)   };

From here, you can see that most of these events were created back in 2002 but a number of others were added later. So these macros allow you to check if a particular flag is available as follows:

#ifdef EPOLLEXCLUSIVE 
/* code that can handle EPOLLEXCLUSIVE */
#else
/* code that uses an alternate event */
#endif

This way the code can run on newer Linux versions that have the newer events available or on older versions that don't.

mcarton
  • 27,633
  • 5
  • 85
  • 95
dbush
  • 205,898
  • 23
  • 218
  • 273
  • 1
    For that purpose, wouldn't `#define EPOLLIN` be enough? – DYZ Jun 13 '20 at 04:42
  • 13
    @DYZ If you do that, then the enum won't compile since the preprocessor would substitute the `EPOLLIN` enum member for a blank string. – dbush Jun 13 '20 at 04:45
  • 1
    @dbush DYZ I think what DYZ is suggesting is that they do `#ifdef EPOLLIN_SUPPORTED` and then use the `EPOLLIN` rather than defining a macro with a symbol of the same name – Allison Jun 13 '20 at 22:16
7

#define EPOLLIN EPOLLIN

This defines the preprocessor macro EPOLLIN to be EPOLLIN.

It is probably defined for the purposes of later #ifdef EPOLLIN checks.

DYZ
  • 55,249
  • 10
  • 64
  • 93
GirkovArpa
  • 4,427
  • 4
  • 14
  • 43