@@ -47,12 +47,13 @@ typedef struct dispatch_muxnote_s {
47
47
TAILQ_ENTRY (dispatch_muxnote_s ) dmn_list ;
48
48
TAILQ_HEAD (, dispatch_unote_linkage_s ) dmn_readers_head ;
49
49
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 ;
56
57
} * dispatch_muxnote_t ;
57
58
58
59
typedef struct dispatch_epoll_timeout_s {
@@ -83,6 +84,13 @@ static struct dispatch_epoll_timeout_s _dispatch_epoll_timeout[] = {
83
84
84
85
#pragma mark dispatch_muxnote_t
85
86
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
+
86
94
DISPATCH_ALWAYS_INLINE
87
95
static inline struct dispatch_muxnote_bucket_s *
88
96
_dispatch_muxnote_bucket (uint32_t ident )
@@ -95,7 +103,7 @@ _dispatch_muxnote_bucket(uint32_t ident)
95
103
DISPATCH_ALWAYS_INLINE
96
104
static inline dispatch_muxnote_t
97
105
_dispatch_muxnote_find (struct dispatch_muxnote_bucket_s * dmb ,
98
- uint32_t ident , int16_t filter )
106
+ uint32_t ident , int8_t filter )
99
107
{
100
108
dispatch_muxnote_t dmn ;
101
109
if (filter == EVFILT_WRITE ) filter = EVFILT_READ ;
@@ -143,7 +151,7 @@ _dispatch_muxnote_create(dispatch_unote_t du, uint32_t events)
143
151
dispatch_muxnote_t dmn ;
144
152
struct stat sb ;
145
153
int fd = (int )du ._du -> du_ident ;
146
- int16_t filter = du ._du -> du_filter ;
154
+ int8_t filter = du ._du -> du_filter ;
147
155
bool skip_outq_ioctl = false, skip_inq_ioctl = false;
148
156
sigset_t sigmask ;
149
157
@@ -207,33 +215,27 @@ _dispatch_muxnote_create(dispatch_unote_t du, uint32_t events)
207
215
#pragma mark dispatch_unote_t
208
216
209
217
static int
210
- _dispatch_epoll_update (dispatch_muxnote_t dmn , int op )
218
+ _dispatch_epoll_update (dispatch_muxnote_t dmn , uint32_t events , int op )
211
219
{
212
220
dispatch_once_f (& epoll_init_pred , NULL , _dispatch_epoll_init );
213
221
struct epoll_event ev = {
214
- .events = dmn -> dmn_events ,
222
+ .events = events ,
215
223
.data = { .ptr = dmn },
216
224
};
217
225
return epoll_ctl (_dispatch_epfd , op , dmn -> dmn_fd , & ev );
218
226
}
219
227
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 )
223
231
{
224
- struct dispatch_muxnote_bucket_s * dmb ;
225
- dispatch_muxnote_t dmn ;
226
232
uint32_t events = EPOLLFREE ;
227
233
228
- dispatch_assert (!_dispatch_unote_registered (du ));
229
- du ._du -> du_priority = pri ;
230
-
231
234
switch (du ._du -> du_filter ) {
232
235
case DISPATCH_EVFILT_CUSTOM_ADD :
233
236
case DISPATCH_EVFILT_CUSTOM_OR :
234
237
case DISPATCH_EVFILT_CUSTOM_REPLACE :
235
- du ._du -> du_wlh = DISPATCH_WLH_ANON ;
236
- return true;
238
+ return 0 ;
237
239
case EVFILT_WRITE :
238
240
events |= EPOLLOUT ;
239
241
break ;
@@ -246,20 +248,35 @@ _dispatch_unote_register(dispatch_unote_t du,
246
248
events |= EPOLLONESHOT ;
247
249
}
248
250
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
+
249
265
dmb = _dispatch_unote_muxnote_bucket (du );
250
266
dmn = _dispatch_unote_muxnote_find (dmb , du );
251
267
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 ) {
257
271
dmn = NULL ;
272
+ } else {
273
+ dmn -> dmn_events = events ;
274
+ dmn -> dmn_disarmed_events &= ~events ;
258
275
}
259
276
}
260
277
} else {
261
278
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 ) {
263
280
_dispatch_muxnote_dispose (dmn );
264
281
dmn = NULL ;
265
282
} else {
@@ -286,8 +303,13 @@ _dispatch_unote_resume(dispatch_unote_t du)
286
303
{
287
304
dispatch_muxnote_t dmn = _dispatch_unote_get_linkage (du )-> du_muxnote ;
288
305
dispatch_assert (_dispatch_unote_registered (du ));
306
+ uint32_t events = _dispatch_unote_required_events (du );
289
307
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
+ }
291
313
}
292
314
293
315
bool
@@ -314,17 +336,26 @@ _dispatch_unote_unregister(dispatch_unote_t du, DISPATCH_UNUSED uint32_t flags)
314
336
dul -> du_muxnote = NULL ;
315
337
316
338
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
+ }
318
344
}
319
345
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
+ }
321
351
}
322
352
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
+ }
328
359
} else {
329
360
epoll_ctl (_dispatch_epfd , EPOLL_CTL_DEL , dmn -> dmn_fd , NULL );
330
361
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)
533
564
dispatch_unote_linkage_t dul , dul_next ;
534
565
uintptr_t data ;
535
566
567
+ dmn -> dmn_disarmed_events |= (events & (EPOLLIN | EPOLLOUT ));
568
+
536
569
if (events & EPOLLIN ) {
537
570
data = _dispatch_get_buffer_size (dmn , false);
538
571
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)
548
581
dux_merge_evt (du ._du , EV_ADD |EV_ENABLE |EV_DISPATCH , ~data , 0 , 0 );
549
582
}
550
583
}
584
+
585
+ events = _dispatch_muxnote_armed_events (dmn );
586
+ if (events ) _dispatch_epoll_update (dmn , events , EPOLL_CTL_MOD );
551
587
}
552
588
553
589
DISPATCH_NOINLINE
0 commit comments