@@ -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,24 +248,41 @@ _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 ) {
263
- _dispatch_muxnote_dispose (dmn );
264
- dmn = NULL ;
265
- } else {
266
- TAILQ_INSERT_TAIL (dmb , dmn , dmn_list );
279
+ if (dmn ) {
280
+ if (_dispatch_epoll_update (dmn , events , EPOLL_CTL_ADD ) < 0 ) {
281
+ _dispatch_muxnote_dispose (dmn );
282
+ dmn = NULL ;
283
+ } else {
284
+ TAILQ_INSERT_TAIL (dmb , dmn , dmn_list );
285
+ }
267
286
}
268
287
}
269
288
@@ -286,8 +305,13 @@ _dispatch_unote_resume(dispatch_unote_t du)
286
305
{
287
306
dispatch_muxnote_t dmn = _dispatch_unote_get_linkage (du )-> du_muxnote ;
288
307
dispatch_assert (_dispatch_unote_registered (du ));
308
+ uint32_t events = _dispatch_unote_required_events (du );
289
309
290
- _dispatch_epoll_update (dmn , EPOLL_CTL_MOD );
310
+ if (events & dmn -> dmn_disarmed_events ) {
311
+ dmn -> dmn_disarmed_events &= ~events ;
312
+ events = _dispatch_muxnote_armed_events (dmn );
313
+ _dispatch_epoll_update (dmn , events , EPOLL_CTL_MOD );
314
+ }
291
315
}
292
316
293
317
bool
@@ -314,17 +338,26 @@ _dispatch_unote_unregister(dispatch_unote_t du, DISPATCH_UNUSED uint32_t flags)
314
338
dul -> du_muxnote = NULL ;
315
339
316
340
if (TAILQ_EMPTY (& dmn -> dmn_readers_head )) {
317
- events &= (uint32_t )(~EPOLLIN );
341
+ events &= (uint32_t )~EPOLLIN ;
342
+ if (dmn -> dmn_disarmed_events & EPOLLIN ) {
343
+ dmn -> dmn_disarmed_events &= (uint16_t )~EPOLLIN ;
344
+ dmn -> dmn_events &= (uint32_t )~EPOLLIN ;
345
+ }
318
346
}
319
347
if (TAILQ_EMPTY (& dmn -> dmn_writers_head )) {
320
- events &= (uint32_t )(~EPOLLOUT );
348
+ events &= (uint32_t )~EPOLLOUT ;
349
+ if (dmn -> dmn_disarmed_events & EPOLLOUT ) {
350
+ dmn -> dmn_disarmed_events &= (uint16_t )~EPOLLOUT ;
351
+ dmn -> dmn_events &= (uint32_t )~EPOLLOUT ;
352
+ }
321
353
}
322
354
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 );
355
+ if (events & (EPOLLIN | EPOLLOUT )) {
356
+ if (events != _dispatch_muxnote_armed_events (dmn )) {
357
+ dmn -> dmn_events = events ;
358
+ events = _dispatch_muxnote_armed_events (dmn );
359
+ _dispatch_epoll_update (dmn , events , EPOLL_CTL_MOD );
360
+ }
328
361
} else {
329
362
epoll_ctl (_dispatch_epfd , EPOLL_CTL_DEL , dmn -> dmn_fd , NULL );
330
363
TAILQ_REMOVE (_dispatch_unote_muxnote_bucket (du ), dmn , dmn_list );
@@ -358,13 +391,14 @@ _dispatch_timeout_program(uint32_t tidx, uint64_t target,
358
391
dispatch_epoll_timeout_t timer = & _dispatch_epoll_timeout [clock ];
359
392
struct epoll_event ev = {
360
393
.events = EPOLLONESHOT | EPOLLIN ,
361
- . data = { . u32 = timer -> det_ident },
394
+
362
395
};
363
396
int op ;
364
397
365
398
if (target >= INT64_MAX && !timer -> det_registered ) {
366
399
return ;
367
400
}
401
+ ev .data .u32 = timer -> det_ident ;
368
402
369
403
if (unlikely (timer -> det_fd < 0 )) {
370
404
clockid_t clockid ;
@@ -386,7 +420,7 @@ _dispatch_timeout_program(uint32_t tidx, uint64_t target,
386
420
387
421
if (target < INT64_MAX ) {
388
422
struct itimerspec its = { .it_value = {
389
- .tv_sec = target / NSEC_PER_SEC ,
423
+ .tv_sec = ( time_t )( target / NSEC_PER_SEC ) ,
390
424
.tv_nsec = target % NSEC_PER_SEC ,
391
425
} };
392
426
dispatch_assume_zero (timerfd_settime (timer -> det_fd , TFD_TIMER_ABSTIME ,
@@ -533,6 +567,8 @@ _dispatch_event_merge_fd(dispatch_muxnote_t dmn, uint32_t events)
533
567
dispatch_unote_linkage_t dul , dul_next ;
534
568
uintptr_t data ;
535
569
570
+ dmn -> dmn_disarmed_events |= (events & (EPOLLIN | EPOLLOUT ));
571
+
536
572
if (events & EPOLLIN ) {
537
573
data = _dispatch_get_buffer_size (dmn , false);
538
574
TAILQ_FOREACH_SAFE (dul , & dmn -> dmn_readers_head , du_link , dul_next ) {
@@ -548,6 +584,9 @@ _dispatch_event_merge_fd(dispatch_muxnote_t dmn, uint32_t events)
548
584
dux_merge_evt (du ._du , EV_ADD |EV_ENABLE |EV_DISPATCH , ~data , 0 , 0 );
549
585
}
550
586
}
587
+
588
+ events = _dispatch_muxnote_armed_events (dmn );
589
+ if (events ) _dispatch_epoll_update (dmn , events , EPOLL_CTL_MOD );
551
590
}
552
591
553
592
DISPATCH_NOINLINE
0 commit comments