Satu socket yang ready dapat membangunkan beberapa thread ketika setiap thread menunggu pada epoll instance berbeda yang memantau socket tersebut. Linux menyediakan EPOLLEXCLUSIVE untuk mempersempit fan-out wakeup itu: di antara epoll instance yang mendaftarkan target dengan flag tersebut, sebuah readiness event membangunkan satu atau lebih instance, bukan semuanya.
Batas semantiknya sengaja lebih lemah daripada “tepat satu waiter.” EPOLLEXCLUSIVE mengubah seleksi notifikasi antar-epoll instance. Flag ini tidak memindahkan kepemilikan file descriptor, tidak menserialkan seluruh I/O, dan tidak menjamin hanya satu thread yang dapat melihat pekerjaan yang berguna.
Flag melekat pada registration
Sebuah epoll instance memiliki interest list berisi file descriptor yang dipantau. Target ditambahkan dengan epoll_ctl() beserta event mask:
struct epoll_event ev = {
.events = EPOLLIN | EPOLLEXCLUSIVE,
.data.fd = listener,
};
if (epoll_ctl(epfd, EPOLL_CTL_ADD, listener, &ev) == -1)
perror("epoll_ctl");Pada contoh ini, properti exclusive berlaku pada relasi antara epfd dan listener. epoll instance lain dapat mendaftarkan target yang sama secara independen.
Tanpa EPOLLEXCLUSIVE, ketika beberapa epoll instance terpasang pada target yang sama dan readiness terjadi, semua epoll instance tersebut dapat menerima event. Dengan registration exclusive, Linux membatasi instance exclusive yang dibangunkan. Kontrak yang didokumentasikan adalah “satu atau lebih”, sehingga kode tidak boleh bergantung pada aturan tepat-satu.
Perilaku ini menargetkan pola thundering herd, saat banyak worker yang sedang blocked menjadi runnable karena satu transisi readiness lalu sebagian besar tidak memperoleh pekerjaan berguna.
Registration exclusive dan biasa dapat berdampingan
Exclusivity tidak menekan observer nonexclusive. Jika sebuah target terdaftar pada beberapa epoll instance, sebagian memakai EPOLLEXCLUSIVE dan sebagian tidak, event dikirim ke semua instance nonexclusive dan setidaknya satu instance exclusive.
Properti ini relevan pada desain yang menggabungkan worker dispatch dengan monitoring. Registration epoll biasa yang dipakai komponen diagnostik atau kontrol tetap menerima readiness walaupun epoll instance milik worker memakai registration exclusive.
Model yang terbentuk bukan global lock pada target:
target fd
|-- ordinary epoll A -> receives event
|-- exclusive epoll B -> eligible exclusive receiver
|-- exclusive epoll C -> eligible exclusive receiver
`-- exclusive epoll D -> eligible exclusive receiverKernel mempersempit cabang exclusive, sementara registration biasa berada di luar seleksi tersebut.
Batas registration merupakan bagian dari API
EPOLLEXCLUSIVE hanya diterima bersama EPOLL_CTL_ADD. Flag ini tidak dapat ditambahkan kemudian melalui EPOLL_CTL_MOD. Setelah pasangan epfd dan target ditambahkan dengan EPOLLEXCLUSIVE, pemanggilan EPOLL_CTL_MOD berikutnya untuk pasangan tersebut juga gagal dengan EINVAL.
Kombinasi event mask dibatasi. EPOLLIN, EPOLLOUT, EPOLLWAKEUP, dan EPOLLET dapat dipakai bersama EPOLLEXCLUSIVE. EPOLLHUP dan EPOLLERR dilaporkan seperti biasa dan tidak perlu diminta. Event flag lain yang digabungkan dengan EPOLLEXCLUSIVE dapat menghasilkan EINVAL.
File descriptor epoll sendiri tidak dapat menjadi target registration exclusive. Percobaan kombinasi tersebut juga gagal dengan EINVAL.
Batas ini menjadikan exclusivity sebagai properti yang dipilih ketika watch dibuat, bukan mode yang ditujukan untuk diubah secara bebas saat runtime.
Seleksi wakeup tidak menserialkan konsumsi
Misalkan beberapa worker thread masing-masing memiliki satu epoll instance, dan setiap instance mendaftarkan listening socket yang sama dengan EPOLLIN | EPOLLEXCLUSIVE. Ketika koneksi masuk, kernel dapat menghindari membangunkan setiap epoll waiter yang sedang blocked.
Setelah satu worker bangun, semantik socket normal tetap berlaku. Thread lain dapat memanggil accept() melalui descriptor yang dibagi, lebih dari satu koneksi mungkin sudah berada di queue, dan transisi readiness lain dapat terjadi saat pemrosesan masih berlangsung. EPOLLEXCLUSIVE tidak membentuk critical section di sekitar accept().
Batas yang sama berlaku pada tipe descriptor lain. Readiness menyatakan bahwa suatu operasi dapat berjalan ketika status readiness dievaluasi; readiness bukan reservasi data untuk epoll waiter yang terpilih.
Aplikasi yang memerlukan ownership, ordering, atau mutual exclusion membutuhkan mekanisme terpisah atau topologi yang menetapkan descriptor kepada worker secara eksplisit.
Edge triggering tetap menjadi dimensi terpisah
EPOLLET dapat digabungkan dengan EPOLLEXCLUSIVE, tetapi kedua flag menangani perilaku berbeda. EPOLLET mengontrol semantik delivery berbasis edge untuk target yang dipantau. EPOLLEXCLUSIVE mengontrol seleksi wakeup ketika beberapa epoll instance yang bersaing memantau target tersebut.
Kombinasi keduanya tidak mengubah exclusive wakeup menjadi exclusive access. Kode edge-triggered tetap harus mengikuti semantik konsumsi normal dan menguras pekerjaan yang tersedia sesuai mode I/O serta desain event loop.
Memisahkan kedua dimensi ini mencegah masalah progress pada logika konsumsi edge-triggered keliru dianggap sebagai efek dari flag seleksi wakeup.
Batas optimisasi berada pada epoll instance yang bersaing
EPOLLEXCLUSIVE berguna secara spesifik ketika target yang sama dipantau oleh beberapa epoll instance dan wakeup redundan tidak diinginkan. Flag ini bukan scheduler hint umum dan tidak menjanjikan rotasi worker yang adil.
Kontrak API juga mengizinkan lebih dari satu epoll instance exclusive menerima event. Ruang implementasi itu penting: jaminannya adalah pengurangan fan-out wakeup dibanding perilaku biasa yang memberi event kepada seluruh observer, bukan dispatch deterministik ke satu worker.
Pada arsitektur server, flag ini berada pada batas yang jelas. Ia dapat mengurangi contention akibat membangunkan banyak event loop untuk shared readiness, sedangkan assignment koneksi, distribusi beban, ordering request, dan sinkronisasi tingkat aplikasi tetap menjadi concern terpisah.