Skip to content

Commit 6bf6cb1

Browse files
Merge pull request #473 from compnerd/file-sources
Windows File Sources
2 parents 1482ec9 + e4e3b2d commit 6bf6cb1

File tree

2 files changed

+202
-9
lines changed

2 files changed

+202
-9
lines changed

src/event/event_windows.c

Lines changed: 201 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,28 +27,217 @@ enum _dispatch_windows_port {
2727
DISPATCH_PORT_TIMER_CLOCK_WALL,
2828
DISPATCH_PORT_TIMER_CLOCK_UPTIME,
2929
DISPATCH_PORT_TIMER_CLOCK_MONOTONIC,
30+
DISPATCH_PORT_FILE_HANDLE,
3031
};
3132

3233
#pragma mark dispatch_unote_t
3334

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+
34158
bool
35-
_dispatch_unote_register_muxed(dispatch_unote_t du DISPATCH_UNUSED)
159+
_dispatch_unote_register_muxed(dispatch_unote_t du)
36160
{
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;
39194
}
40195

41196
void
42-
_dispatch_unote_resume_muxed(dispatch_unote_t du DISPATCH_UNUSED)
197+
_dispatch_unote_resume_muxed(dispatch_unote_t du)
43198
{
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);
45203
}
46204

47205
bool
48-
_dispatch_unote_unregister_muxed(dispatch_unote_t du DISPATCH_UNUSED)
206+
_dispatch_unote_unregister_muxed(dispatch_unote_t du)
49207
{
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);
52241
}
53242

54243
#pragma mark timers
@@ -221,6 +410,10 @@ _dispatch_event_loop_drain(uint32_t flags)
221410
_dispatch_event_merge_timer(DISPATCH_CLOCK_MONOTONIC);
222411
break;
223412

413+
case DISPATCH_PORT_FILE_HANDLE:
414+
_dispatch_event_merge_file_handle();
415+
break;
416+
224417
default:
225418
DISPATCH_INTERNAL_CRASH(ulCompletionKey,
226419
"unsupported completion key");

src/init.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1045,7 +1045,7 @@ _dispatch_bug_kevent_vanished(dispatch_unote_t du)
10451045
_dispatch_log_fault("LIBDISPATCH_STRICT: _dispatch_bug_kevent_vanished",
10461046
"BUG in libdispatch client: %s, monitored resource vanished before "
10471047
"the source cancel handler was invoked "
1048-
"{ %p[%s], ident: %d / 0x%x, handler: %p }",
1048+
"{ %p[%s], ident: %" PRIdPTR " / 0x%" PRIxPTR ", handler: %p }",
10491049
dux_type(du._du)->dst_kind, dou._dq,
10501050
dou._dq->dq_label ? dou._dq->dq_label : "<unknown>",
10511051
du._du->du_ident, du._du->du_ident, func);

0 commit comments

Comments
 (0)