@@ -47,12 +47,13 @@ typedef struct dispatch_muxnote_s {
4747 TAILQ_ENTRY (dispatch_muxnote_s ) dmn_list ;
4848 TAILQ_HEAD (, dispatch_unote_linkage_s ) dmn_readers_head ;
4949 TAILQ_HEAD (, dispatch_unote_linkage_s ) dmn_writers_head ;
50- int dmn_fd ;
51- uint32_t dmn_ident ;
52- uint32_t dmn_events ;
53- int16_t dmn_filter ;
54- bool dmn_skip_outq_ioctl ;
55- bool dmn_skip_inq_ioctl ;
50+ int dmn_fd ;
51+ uint32_t dmn_ident ;
52+ uint32_t dmn_events ;
53+ uint16_t dmn_disarmed_events ;
54+ int8_t dmn_filter ;
55+ bool dmn_skip_outq_ioctl : 1 ;
56+ bool dmn_skip_inq_ioctl : 1 ;
5657} * dispatch_muxnote_t ;
5758
5859typedef struct dispatch_epoll_timeout_s {
@@ -83,6 +84,13 @@ static struct dispatch_epoll_timeout_s _dispatch_epoll_timeout[] = {
8384
8485#pragma mark dispatch_muxnote_t
8586
87+ DISPATCH_ALWAYS_INLINE
88+ static inline uint32_t
89+ _dispatch_muxnote_armed_events (dispatch_muxnote_t dmn )
90+ {
91+ return dmn -> dmn_events & ~dmn -> dmn_disarmed_events ;
92+ }
93+
8694DISPATCH_ALWAYS_INLINE
8795static inline struct dispatch_muxnote_bucket_s *
8896_dispatch_muxnote_bucket (uint32_t ident )
@@ -95,7 +103,7 @@ _dispatch_muxnote_bucket(uint32_t ident)
95103DISPATCH_ALWAYS_INLINE
96104static inline dispatch_muxnote_t
97105_dispatch_muxnote_find (struct dispatch_muxnote_bucket_s * dmb ,
98- uint32_t ident , int16_t filter )
106+ uint32_t ident , int8_t filter )
99107{
100108 dispatch_muxnote_t dmn ;
101109 if (filter == EVFILT_WRITE ) filter = EVFILT_READ ;
@@ -143,7 +151,7 @@ _dispatch_muxnote_create(dispatch_unote_t du, uint32_t events)
143151 dispatch_muxnote_t dmn ;
144152 struct stat sb ;
145153 int fd = (int )du ._du -> du_ident ;
146- int16_t filter = du ._du -> du_filter ;
154+ int8_t filter = du ._du -> du_filter ;
147155 bool skip_outq_ioctl = false, skip_inq_ioctl = false;
148156 sigset_t sigmask ;
149157
@@ -207,33 +215,27 @@ _dispatch_muxnote_create(dispatch_unote_t du, uint32_t events)
207215#pragma mark dispatch_unote_t
208216
209217static int
210- _dispatch_epoll_update (dispatch_muxnote_t dmn , int op )
218+ _dispatch_epoll_update (dispatch_muxnote_t dmn , uint32_t events , int op )
211219{
212220 dispatch_once_f (& epoll_init_pred , NULL , _dispatch_epoll_init );
213221 struct epoll_event ev = {
214- .events = dmn -> dmn_events ,
222+ .events = events ,
215223 .data = { .ptr = dmn },
216224 };
217225 return epoll_ctl (_dispatch_epfd , op , dmn -> dmn_fd , & ev );
218226}
219227
220- bool
221- _dispatch_unote_register ( dispatch_unote_t du ,
222- DISPATCH_UNUSED dispatch_wlh_t wlh , dispatch_priority_t pri )
228+ DISPATCH_ALWAYS_INLINE
229+ static inline uint32_t
230+ _dispatch_unote_required_events ( dispatch_unote_t du )
223231{
224- struct dispatch_muxnote_bucket_s * dmb ;
225- dispatch_muxnote_t dmn ;
226232 uint32_t events = EPOLLFREE ;
227233
228- dispatch_assert (!_dispatch_unote_registered (du ));
229- du ._du -> du_priority = pri ;
230-
231234 switch (du ._du -> du_filter ) {
232235 case DISPATCH_EVFILT_CUSTOM_ADD :
233236 case DISPATCH_EVFILT_CUSTOM_OR :
234237 case DISPATCH_EVFILT_CUSTOM_REPLACE :
235- du ._du -> du_wlh = DISPATCH_WLH_ANON ;
236- return true;
238+ return 0 ;
237239 case EVFILT_WRITE :
238240 events |= EPOLLOUT ;
239241 break ;
@@ -246,20 +248,35 @@ _dispatch_unote_register(dispatch_unote_t du,
246248 events |= EPOLLONESHOT ;
247249 }
248250
251+ return events ;
252+ }
253+
254+ bool
255+ _dispatch_unote_register (dispatch_unote_t du ,
256+ DISPATCH_UNUSED dispatch_wlh_t wlh , dispatch_priority_t pri )
257+ {
258+ struct dispatch_muxnote_bucket_s * dmb ;
259+ dispatch_muxnote_t dmn ;
260+ uint32_t events = _dispatch_unote_required_events (du );
261+
262+ dispatch_assert (!_dispatch_unote_registered (du ));
263+ du ._du -> du_priority = pri ;
264+
249265 dmb = _dispatch_unote_muxnote_bucket (du );
250266 dmn = _dispatch_unote_muxnote_find (dmb , du );
251267 if (dmn ) {
252- events &= ~dmn -> dmn_events ;
253- if (events ) {
254- dmn -> dmn_events |= events ;
255- if (_dispatch_epoll_update (dmn , EPOLL_CTL_MOD ) < 0 ) {
256- dmn -> dmn_events &= ~events ;
268+ if (events & ~_dispatch_muxnote_armed_events (dmn )) {
269+ events |= _dispatch_muxnote_armed_events (dmn );
270+ if (_dispatch_epoll_update (dmn , events , EPOLL_CTL_MOD ) < 0 ) {
257271 dmn = NULL ;
272+ } else {
273+ dmn -> dmn_events = events ;
274+ dmn -> dmn_disarmed_events &= ~events ;
258275 }
259276 }
260277 } else {
261278 dmn = _dispatch_muxnote_create (du , events );
262- if (_dispatch_epoll_update (dmn , EPOLL_CTL_ADD ) < 0 ) {
279+ if (_dispatch_epoll_update (dmn , events , EPOLL_CTL_ADD ) < 0 ) {
263280 _dispatch_muxnote_dispose (dmn );
264281 dmn = NULL ;
265282 } else {
@@ -286,8 +303,13 @@ _dispatch_unote_resume(dispatch_unote_t du)
286303{
287304 dispatch_muxnote_t dmn = _dispatch_unote_get_linkage (du )-> du_muxnote ;
288305 dispatch_assert (_dispatch_unote_registered (du ));
306+ uint32_t events = _dispatch_unote_required_events (du );
289307
290- _dispatch_epoll_update (dmn , EPOLL_CTL_MOD );
308+ if (events & dmn -> dmn_disarmed_events ) {
309+ dmn -> dmn_disarmed_events &= ~events ;
310+ events = _dispatch_muxnote_armed_events (dmn );
311+ _dispatch_epoll_update (dmn , events , EPOLL_CTL_MOD );
312+ }
291313}
292314
293315bool
@@ -314,17 +336,26 @@ _dispatch_unote_unregister(dispatch_unote_t du, DISPATCH_UNUSED uint32_t flags)
314336 dul -> du_muxnote = NULL ;
315337
316338 if (TAILQ_EMPTY (& dmn -> dmn_readers_head )) {
317- events &= (uint32_t )(~EPOLLIN );
339+ events &= (uint32_t )~EPOLLIN ;
340+ if (dmn -> dmn_disarmed_events & EPOLLIN ) {
341+ dmn -> dmn_disarmed_events &= (uint16_t )~EPOLLIN ;
342+ dmn -> dmn_events &= (uint32_t )~EPOLLIN ;
343+ }
318344 }
319345 if (TAILQ_EMPTY (& dmn -> dmn_writers_head )) {
320- events &= (uint32_t )(~EPOLLOUT );
346+ events &= (uint32_t )~EPOLLOUT ;
347+ if (dmn -> dmn_disarmed_events & EPOLLOUT ) {
348+ dmn -> dmn_disarmed_events &= (uint16_t )~EPOLLOUT ;
349+ dmn -> dmn_events &= (uint32_t )~EPOLLOUT ;
350+ }
321351 }
322352
323- if (events == dmn -> dmn_events ) {
324- // nothing to do
325- } else if (events & (EPOLLIN | EPOLLOUT )) {
326- dmn -> dmn_events = events ;
327- _dispatch_epoll_update (dmn , EPOLL_CTL_MOD );
353+ if (events & (EPOLLIN | EPOLLOUT )) {
354+ if (events != _dispatch_muxnote_armed_events (dmn )) {
355+ dmn -> dmn_events = events ;
356+ events = _dispatch_muxnote_armed_events (dmn );
357+ _dispatch_epoll_update (dmn , events , EPOLL_CTL_MOD );
358+ }
328359 } else {
329360 epoll_ctl (_dispatch_epfd , EPOLL_CTL_DEL , dmn -> dmn_fd , NULL );
330361 TAILQ_REMOVE (_dispatch_unote_muxnote_bucket (du ), dmn , dmn_list );
@@ -533,6 +564,8 @@ _dispatch_event_merge_fd(dispatch_muxnote_t dmn, uint32_t events)
533564 dispatch_unote_linkage_t dul , dul_next ;
534565 uintptr_t data ;
535566
567+ dmn -> dmn_disarmed_events |= (events & (EPOLLIN | EPOLLOUT ));
568+
536569 if (events & EPOLLIN ) {
537570 data = _dispatch_get_buffer_size (dmn , false);
538571 TAILQ_FOREACH_SAFE (dul , & dmn -> dmn_readers_head , du_link , dul_next ) {
@@ -548,6 +581,9 @@ _dispatch_event_merge_fd(dispatch_muxnote_t dmn, uint32_t events)
548581 dux_merge_evt (du ._du , EV_ADD |EV_ENABLE |EV_DISPATCH , ~data , 0 , 0 );
549582 }
550583 }
584+
585+ events = _dispatch_muxnote_armed_events (dmn );
586+ if (events ) _dispatch_epoll_update (dmn , events , EPOLL_CTL_MOD );
551587}
552588
553589DISPATCH_NOINLINE
0 commit comments