]> git.ipfire.org Git - thirdparty/systemd.git/commit
sd-event: drop some bitfield specifiers from struct sd_event_source
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sun, 8 Jun 2025 11:21:28 +0000 (13:21 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 3 Jul 2025 14:17:42 +0000 (16:17 +0200)
commitea51623345b1a1bed0db72e836d07b27c72daae8
treef9b4f3316da89732e72cbec9185b979c05737a52
parent1b4645d762d0d31e46173a389742978c32700901
sd-event: drop some bitfield specifiers from struct sd_event_source

This does not change the size of the structure, because the size is determined
by .child, which has a 128-byte siginfo_t field. But by dropping the specifiers
we let the compiler generate code that operates on full bytes instead of having
to play with bitmasks, see second diff below.

Also move the bools in .memory_pressure into a gap to save a few bytes on
initialization.

$ diff -U100 <(pahole build/src/shared/libsystemd-shared-258.so.0 | awk '/struct sd_event_source/,/^}/') \
             <(pahole build/src/shared/libsystemd-shared-258.so | awk '/struct sd_event_source/,/^}/')
--- /proc/self/fd/11 2025-06-08 13:16:55.614738334 +0200
+++ /proc/self/fd/12 2025-06-08 13:16:55.615738386 +0200
@@ -1,109 +1,109 @@
 struct sd_event_source {
  WakeupType                 wakeup;               /*     0     4 */
  unsigned int               n_ref;                /*     4     4 */
  sd_event *                 event;                /*     8     8 */
  void *                     userdata;             /*    16     8 */
  sd_event_handler_t         prepare;              /*    24     8 */
  char *                     description;          /*    32     8 */
  EventSourceType            type;                 /*    40     4 */
        signed int                 enabled:3;            /*    44: 0  4 */
  _Bool                      pending:1;            /*    44: 3  1 */
  _Bool                      dispatching:1;        /*    44: 4  1 */
  _Bool                      floating:1;           /*    44: 5  1 */
  _Bool                      exit_on_failure:1;    /*    44: 6  1 */
  _Bool                      ratelimited:1;        /*    44: 7  1 */

  /* XXX 24 bits hole, try to pack */

  int64_t                    priority;             /*    48     8 */
  unsigned int               pending_index;        /*    56     4 */
  unsigned int               prepare_index;        /*    60     4 */
  /* --- cacheline 1 boundary (64 bytes) --- */
  uint64_t                   pending_iteration;    /*    64     8 */
  uint64_t                   prepare_iteration;    /*    72     8 */
  sd_event_destroy_t         destroy_callback;     /*    80     8 */
  sd_event_handler_t         ratelimit_expire_callback; /*    88     8 */
  sd_event_source *          sources_next;         /*    96     8 */
  sd_event_source *          sources_prev;         /*   104     8 */
  RateLimit                  rate_limit;           /*   112    24 */
  /* --- cacheline 2 boundary (128 bytes) was 8 bytes ago --- */
  unsigned int               earliest_index;       /*   136     4 */
  unsigned int               latest_index;         /*   140     4 */
  union {
  struct {
  sd_event_io_handler_t callback;  /*   144     8 */
  int        fd;                   /*   152     4 */
  uint32_t   events;               /*   156     4 */
  uint32_t   revents;              /*   160     4 */
- _Bool      registered:1;         /*   164: 0  1 */
- _Bool      owned:1;              /*   164: 1  1 */
+ _Bool      registered;           /*   164     1 */
+ _Bool      owned;                /*   165     1 */
  } io;                                    /*   144    24 */
  struct {
  sd_event_time_handler_t callback; /*   144     8 */
  usec_t     next;                 /*   152     8 */
  usec_t     accuracy;             /*   160     8 */
  } time;                                  /*   144    24 */
  struct {
  sd_event_signal_handler_t callback; /*   144     8 */
  struct signalfd_siginfo siginfo; /*   152   128 */
  /* --- cacheline 4 boundary (256 bytes) was 24 bytes ago --- */
  int        sig;                  /*   280     4 */
  _Bool      unblock;              /*   284     1 */
  } signal;                                /*   144   144 */
  struct {
  sd_event_child_handler_t callback; /*   144     8 */
  siginfo_t  siginfo;              /*   152   128 */
  /* --- cacheline 4 boundary (256 bytes) was 24 bytes ago --- */
  pid_t      pid;                  /*   280     4 */
  int        options;              /*   284     4 */
  int        pidfd;                /*   288     4 */
  _Bool      registered:1;         /*   292: 0  1 */
  _Bool      pidfd_owned:1;        /*   292: 1  1 */
  _Bool      process_owned:1;      /*   292: 2  1 */
  _Bool      exited:1;             /*   292: 3  1 */
  _Bool      waited:1;             /*   292: 4  1 */
  } child;                                 /*   144   152 */
  struct {
  sd_event_handler_t callback;     /*   144     8 */
  } defer;                                 /*   144     8 */
  struct {
  sd_event_handler_t callback;     /*   144     8 */
  } post;                                  /*   144     8 */
  struct {
  sd_event_handler_t callback;     /*   144     8 */
  unsigned int prioq_index;        /*   152     4 */
  } exit;                                  /*   144    16 */
  struct {
  sd_event_inotify_handler_t callback; /*   144     8 */
  uint32_t   mask;                 /*   152     4 */

  /* XXX 4 bytes hole, try to pack */

  struct inode_data * inode_data;  /*   160     8 */
  sd_event_source * by_inode_data_next; /*   168     8 */
  sd_event_source * by_inode_data_prev; /*   176     8 */
  } inotify;                               /*   144    40 */
  struct {
  int        fd;                   /*   144     4 */
+ _Bool      registered;           /*   148     1 */
+ _Bool      locked;               /*   149     1 */
+ _Bool      in_write_list;        /*   150     1 */

- /* XXX 4 bytes hole, try to pack */
+ /* XXX 1 byte hole, try to pack */

  sd_event_handler_t callback;     /*   152     8 */
  void *     write_buffer;         /*   160     8 */
  size_t     write_buffer_size;    /*   168     8 */
  uint32_t   events;               /*   176     4 */
  uint32_t   revents;              /*   180     4 */
  sd_event_source * write_list_next; /*   184     8 */
  /* --- cacheline 3 boundary (192 bytes) --- */
  sd_event_source * write_list_prev; /*   192     8 */
- _Bool      registered:1;         /*   200: 0  1 */
- _Bool      locked:1;             /*   200: 1  1 */
- _Bool      in_write_list:1;      /*   200: 2  1 */
- } memory_pressure;                       /*   144    64 */
+ } memory_pressure;                       /*   144    56 */
  };                                               /*   144   152 */

  /* size: 296, cachelines: 5, members: 26 */
  /* sum members: 292 */
  /* sum bitfield members: 8 bits, bit holes: 1, sum bit holes: 24 bits */
  /* last cacheline: 40 bytes */
 };

Example diff in assembly:

$ diff -u <(objdump -S build/src/shared/libsystemd-shared-258.so.0|awk '/^static void event_source_time_prioq_reshuffle/,/^\}/') \
          <(objdump -S build/src/shared/libsystemd-shared-258.so|awk '/^static void event_source_time_prioq_reshuffle/,/^\}/')

         d->needs_rearm = true;
-  34d80e:      48 8b 45 f8             mov    -0x8(%rbp),%rax
-  34d812:      0f b6 50 20             movzbl 0x20(%rax),%edx
-  34d816:      83 ca 01                or     $0x1,%edx
-  34d819:      88 50 20                mov    %dl,0x20(%rax)
-  34d81c:      eb 01                   jmp    34d81f <event_source_time_prioq_reshuffle+0x12c>
+  34d7c3:      48 8b 45 f8             mov    -0x8(%rbp),%rax
+  34d7c7:      c6 40 20 01             movb   $0x1,0x20(%rax)
+  34d7cb:      eb 01                   jmp    34d7ce <event_source_time_prioq_reshuffle+0x126>
                 return; /* no-op for an event source which is neither a timer nor ratelimited. */
-  34d81e:      90                      nop
+  34d7cd:      90                      nop
src/libsystemd/sd-event/event-source.h