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