@@ -27,28 +27,217 @@ enum _dispatch_windows_port {
27
27
DISPATCH_PORT_TIMER_CLOCK_WALL ,
28
28
DISPATCH_PORT_TIMER_CLOCK_UPTIME ,
29
29
DISPATCH_PORT_TIMER_CLOCK_MONOTONIC ,
30
+ DISPATCH_PORT_FILE_HANDLE ,
30
31
};
31
32
32
33
#pragma mark dispatch_unote_t
33
34
35
+ typedef struct dispatch_muxnote_s {
36
+ LIST_ENTRY (dispatch_muxnote_s ) dmn_list ;
37
+ dispatch_unote_ident_t dmn_ident ;
38
+ int8_t dmn_filter ;
39
+ enum _dispatch_muxnote_handle_type {
40
+ DISPATCH_MUXNOTE_HANDLE_TYPE_INVALID ,
41
+ DISPATCH_MUXNOTE_HANDLE_TYPE_FILE ,
42
+ } dmn_handle_type ;
43
+ } * dispatch_muxnote_t ;
44
+
45
+ static LIST_HEAD (dispatch_muxnote_bucket_s , dispatch_muxnote_s )
46
+ _dispatch_sources [DSL_HASH_SIZE ];
47
+
48
+ static SRWLOCK _dispatch_file_handles_lock = SRWLOCK_INIT ;
49
+ static LIST_HEAD (, dispatch_unote_linkage_s ) _dispatch_file_handles ;
50
+
51
+ DISPATCH_ALWAYS_INLINE
52
+ static inline struct dispatch_muxnote_bucket_s *
53
+ _dispatch_unote_muxnote_bucket (uint32_t ident )
54
+ {
55
+ return & _dispatch_sources [DSL_HASH (ident )];
56
+ }
57
+
58
+ DISPATCH_ALWAYS_INLINE
59
+ static inline dispatch_muxnote_t
60
+ _dispatch_unote_muxnote_find (struct dispatch_muxnote_bucket_s * dmb ,
61
+ dispatch_unote_ident_t ident , int8_t filter )
62
+ {
63
+ dispatch_muxnote_t dmn ;
64
+ if (filter == EVFILT_WRITE ) filter = EVFILT_READ ;
65
+ LIST_FOREACH (dmn , dmb , dmn_list ) {
66
+ if (dmn -> dmn_ident == ident && dmn -> dmn_filter == filter ) {
67
+ break ;
68
+ }
69
+ }
70
+ return dmn ;
71
+ }
72
+
73
+ static dispatch_muxnote_t
74
+ _dispatch_muxnote_create (dispatch_unote_t du )
75
+ {
76
+ dispatch_muxnote_t dmn ;
77
+ int8_t filter = du ._du -> du_filter ;
78
+ HANDLE handle = (HANDLE )du ._du -> du_ident ;
79
+
80
+ dmn = _dispatch_calloc (1 , sizeof (* dmn ));
81
+ if (dmn == NULL ) {
82
+ DISPATCH_INTERNAL_CRASH (0 , "_dispatch_calloc" );
83
+ }
84
+ dmn -> dmn_ident = (dispatch_unote_ident_t )handle ;
85
+ dmn -> dmn_filter = filter ;
86
+
87
+ switch (filter ) {
88
+ case EVFILT_SIGNAL :
89
+ WIN_PORT_ERROR ();
90
+
91
+ case EVFILT_WRITE :
92
+ case EVFILT_READ :
93
+ switch (GetFileType (handle )) {
94
+ case FILE_TYPE_UNKNOWN :
95
+ // ensure that an invalid handle was not passed
96
+ (void )dispatch_assume (GetLastError () == NO_ERROR );
97
+ DISPATCH_INTERNAL_CRASH (0 , "unknown handle type" );
98
+
99
+ case FILE_TYPE_REMOTE :
100
+ DISPATCH_INTERNAL_CRASH (0 , "unused handle type" );
101
+
102
+ case FILE_TYPE_CHAR :
103
+ // The specified file is a character file, typically a
104
+ // LPT device or a console.
105
+ WIN_PORT_ERROR ();
106
+
107
+ case FILE_TYPE_DISK :
108
+ // The specified file is a disk file
109
+ dmn -> dmn_handle_type =
110
+ DISPATCH_MUXNOTE_HANDLE_TYPE_FILE ;
111
+ break ;
112
+
113
+ case FILE_TYPE_PIPE :
114
+ // The specified file is a socket, a named pipe, or an
115
+ // anonymous pipe.
116
+ WIN_PORT_ERROR ();
117
+ }
118
+
119
+ break ;
120
+
121
+ default :
122
+ DISPATCH_INTERNAL_CRASH (0 , "unexpected filter" );
123
+ }
124
+
125
+
126
+ return dmn ;
127
+ }
128
+
129
+ static void
130
+ _dispatch_muxnote_dispose (dispatch_muxnote_t dmn )
131
+ {
132
+ free (dmn );
133
+ }
134
+
135
+ DISPATCH_ALWAYS_INLINE
136
+ static BOOL
137
+ _dispatch_io_trigger (dispatch_muxnote_t dmn )
138
+ {
139
+ BOOL bSuccess ;
140
+
141
+ switch (dmn -> dmn_handle_type ) {
142
+ case DISPATCH_MUXNOTE_HANDLE_TYPE_INVALID :
143
+ DISPATCH_INTERNAL_CRASH (0 , "invalid handle" );
144
+
145
+ case DISPATCH_MUXNOTE_HANDLE_TYPE_FILE :
146
+ bSuccess = PostQueuedCompletionStatus (hPort , 0 ,
147
+ (ULONG_PTR )DISPATCH_PORT_FILE_HANDLE , NULL );
148
+ if (bSuccess == FALSE) {
149
+ DISPATCH_INTERNAL_CRASH (GetLastError (),
150
+ "PostQueuedCompletionStatus" );
151
+ }
152
+ break ;
153
+ }
154
+
155
+ return bSuccess ;
156
+ }
157
+
34
158
bool
35
- _dispatch_unote_register_muxed (dispatch_unote_t du DISPATCH_UNUSED )
159
+ _dispatch_unote_register_muxed (dispatch_unote_t du )
36
160
{
37
- WIN_PORT_ERROR ();
38
- return false;
161
+ struct dispatch_muxnote_bucket_s * dmb ;
162
+ dispatch_muxnote_t dmn ;
163
+
164
+ dmb = _dispatch_unote_muxnote_bucket (du ._du -> du_ident );
165
+ dmn = _dispatch_unote_muxnote_find (dmb , du ._du -> du_ident ,
166
+ du ._du -> du_filter );
167
+ if (dmn ) {
168
+ WIN_PORT_ERROR ();
169
+ } else {
170
+ dmn = _dispatch_muxnote_create (du );
171
+ if (dmn ) {
172
+ if (_dispatch_io_trigger (dmn ) == FALSE) {
173
+ _dispatch_muxnote_dispose (dmn );
174
+ dmn = NULL ;
175
+ } else {
176
+ LIST_INSERT_HEAD (dmb , dmn , dmn_list );
177
+ }
178
+ }
179
+ }
180
+
181
+ if (dmn ) {
182
+ dispatch_unote_linkage_t dul = _dispatch_unote_get_linkage (du );
183
+
184
+ AcquireSRWLockExclusive (& _dispatch_file_handles_lock );
185
+ LIST_INSERT_HEAD (& _dispatch_file_handles , dul , du_link );
186
+ ReleaseSRWLockExclusive (& _dispatch_file_handles_lock );
187
+
188
+ dul -> du_muxnote = dmn ;
189
+ _dispatch_unote_state_set (du , DISPATCH_WLH_ANON ,
190
+ DU_STATE_ARMED );
191
+ }
192
+
193
+ return dmn != NULL ;
39
194
}
40
195
41
196
void
42
- _dispatch_unote_resume_muxed (dispatch_unote_t du DISPATCH_UNUSED )
197
+ _dispatch_unote_resume_muxed (dispatch_unote_t du )
43
198
{
44
- WIN_PORT_ERROR ();
199
+ dispatch_unote_linkage_t dul = _dispatch_unote_get_linkage (du );
200
+ dispatch_muxnote_t dmn = dul -> du_muxnote ;
201
+ dispatch_assert (_dispatch_unote_registered (du ));
202
+ _dispatch_io_trigger (dmn );
45
203
}
46
204
47
205
bool
48
- _dispatch_unote_unregister_muxed (dispatch_unote_t du DISPATCH_UNUSED )
206
+ _dispatch_unote_unregister_muxed (dispatch_unote_t du )
49
207
{
50
- WIN_PORT_ERROR ();
51
- return false;
208
+ dispatch_unote_linkage_t dul = _dispatch_unote_get_linkage (du );
209
+ dispatch_muxnote_t dmn = dul -> du_muxnote ;
210
+
211
+ AcquireSRWLockExclusive (& _dispatch_file_handles_lock );
212
+ LIST_REMOVE (dul , du_link );
213
+ _LIST_TRASH_ENTRY (dul , du_link );
214
+ ReleaseSRWLockExclusive (& _dispatch_file_handles_lock );
215
+ dul -> du_muxnote = NULL ;
216
+
217
+ LIST_REMOVE (dmn , dmn_list );
218
+ _dispatch_muxnote_dispose (dmn );
219
+
220
+ _dispatch_unote_state_set (du , DU_STATE_UNREGISTERED );
221
+ return true;
222
+ }
223
+
224
+ static void
225
+ _dispatch_event_merge_file_handle ()
226
+ {
227
+ dispatch_unote_linkage_t dul , dul_next ;
228
+
229
+ AcquireSRWLockExclusive (& _dispatch_file_handles_lock );
230
+ LIST_FOREACH_SAFE (dul , & _dispatch_file_handles , du_link , dul_next ) {
231
+ dispatch_unote_t du = _dispatch_unote_linkage_get_unote (dul );
232
+
233
+ // consumed by dux_merge_evt()
234
+ _dispatch_retain_unote_owner (du );
235
+ dispatch_assert (dux_needs_rearm (du ._du ));
236
+ _dispatch_unote_state_clear_bit (du , DU_STATE_ARMED );
237
+ os_atomic_store2o (du ._dr , ds_pending_data , ~1 , relaxed );
238
+ dux_merge_evt (du ._du , EV_ADD | EV_ENABLE | EV_DISPATCH , 1 , 0 );
239
+ }
240
+ ReleaseSRWLockExclusive (& _dispatch_file_handles_lock );
52
241
}
53
242
54
243
#pragma mark timers
@@ -221,6 +410,10 @@ _dispatch_event_loop_drain(uint32_t flags)
221
410
_dispatch_event_merge_timer (DISPATCH_CLOCK_MONOTONIC );
222
411
break ;
223
412
413
+ case DISPATCH_PORT_FILE_HANDLE :
414
+ _dispatch_event_merge_file_handle ();
415
+ break ;
416
+
224
417
default :
225
418
DISPATCH_INTERNAL_CRASH (ulCompletionKey ,
226
419
"unsupported completion key" );
0 commit comments