26 #if !LELY_NO_STDIO && _WIN32
28 #include "../sigset.h"
38 #include <processthreadsapi.h>
42 #define LELY_NSIG NSIG
44 #define LELY_NSIG (SIGABRT + 1)
55 #define IO_SIGSET_NODE_INIT(signo) \
61 CRITICAL_SECTION CriticalSection;
63 } io_sigset_shared = { .list = { NULL } };
65 static BOOL WINAPI io_sigset_handler_routine(DWORD dwCtrlType);
66 static BOOL io_sigset_handler(
int signo);
70 static size_t io_sigset_impl_dev_cancel(
io_dev_t *dev,
struct ev_task *task);
71 static size_t io_sigset_impl_dev_abort(
io_dev_t *dev,
struct ev_task *task);
74 static const struct io_dev_vtbl io_sigset_impl_dev_vtbl = {
75 &io_sigset_impl_dev_get_ctx,
76 &io_sigset_impl_dev_get_exec,
77 &io_sigset_impl_dev_cancel,
78 &io_sigset_impl_dev_abort
83 static int io_sigset_impl_clear(
io_sigset_t *sigset);
84 static int io_sigset_impl_insert(
io_sigset_t *sigset,
int signo);
85 static int io_sigset_impl_remove(
io_sigset_t *sigset,
int signo);
86 static void io_sigset_impl_submit_wait(
91 &io_sigset_impl_get_dev,
92 &io_sigset_impl_clear,
93 &io_sigset_impl_insert,
94 &io_sigset_impl_remove,
95 &io_sigset_impl_submit_wait
99 static void io_sigset_impl_svc_shutdown(
struct io_svc *svc);
102 static const struct io_svc_vtbl io_sigset_impl_svc_vtbl = {
104 &io_sigset_impl_svc_shutdown
115 struct io_cp signal_cp;
121 CRITICAL_SECTION CriticalSection;
123 unsigned shutdown : 1;
124 unsigned signal_posted : 1;
125 unsigned wait_posted : 1;
126 unsigned pending : 1;
131 static void io_sigset_impl_signal_cp_func(
132 struct io_cp *cp,
size_t nbytes,
int errc);
133 static void io_sigset_impl_wait_task_func(
struct ev_task *task);
140 const struct io_svc *svc);
145 static void io_sigset_impl_do_insert(
struct io_sigset_impl *impl,
int signo);
146 static void io_sigset_impl_do_remove(
struct io_sigset_impl *impl,
int signo);
149 io_win32_sigset_init(
void)
151 InitializeCriticalSection(&io_sigset_shared.CriticalSection);
152 if (!SetConsoleCtrlHandler(&io_sigset_handler_routine, TRUE)) {
153 DeleteCriticalSection(&io_sigset_shared.CriticalSection);
160 io_win32_sigset_fini(
void)
162 SetConsoleCtrlHandler(&io_sigset_handler_routine, FALSE);
163 DeleteCriticalSection(&io_sigset_shared.CriticalSection);
167 io_sigset_alloc(
void)
174 return &impl->sigset_vptr;
178 io_sigset_free(
void *ptr)
181 free(io_sigset_impl_from_sigset(ptr));
193 impl->dev_vptr = &io_sigset_impl_dev_vtbl;
194 impl->sigset_vptr = &io_sigset_impl_vtbl;
204 &io_sigset_impl_signal_cp_func);
206 impl->
exec, &io_sigset_impl_wait_task_func);
209 InitializeCriticalSection(&impl->CriticalSection);
213 impl->signal_posted = 0;
214 impl->wait_posted = 0;
219 for (
int i = 1; i < LELY_NSIG; i++)
235 io_sigset_impl_svc_shutdown(&impl->svc);
241 EnterCriticalSection(&impl->CriticalSection);
244 while (impl->wait_posted) {
248 LeaveCriticalSection(&impl->CriticalSection);
250 EnterCriticalSection(&impl->CriticalSection);
252 LeaveCriticalSection(&impl->CriticalSection);
254 DeleteCriticalSection(&impl->CriticalSection);
265 dwErrCode = GetLastError();
269 io_sigset_t *tmp = io_sigset_init(sigset, poll, exec);
271 dwErrCode = GetLastError();
279 io_sigset_free((
void *)sigset);
281 SetLastError(dwErrCode);
289 io_sigset_fini(sigset);
290 io_sigset_free((
void *)sigset);
295 io_sigset_handler_routine(DWORD dwCtrlType)
297 switch (dwCtrlType) {
298 case CTRL_C_EVENT:
return io_sigset_handler(SIGINT);
299 case CTRL_BREAK_EVENT:
return io_sigset_handler(SIGBREAK);
300 case CTRL_CLOSE_EVENT:
301 if (io_sigset_handler(SIGHUP)) {
309 case CTRL_LOGOFF_EVENT:
310 case CTRL_SHUTDOWN_EVENT:
311 default:
return FALSE;
316 io_sigset_handler(
int signo)
319 assert(signo < LELY_NSIG);
321 EnterCriticalSection(&io_sigset_shared.CriticalSection);
323 for (
struct io_sigset_node *node = list; node; node = node->next) {
327 assert(node->watched);
328 if (!node->pending) {
330 if (!impl->signal_posted) {
331 impl->signal_posted = 1;
336 LeaveCriticalSection(&io_sigset_shared.CriticalSection);
341 io_sigset_impl_dev_get_ctx(
const io_dev_t *dev)
349 io_sigset_impl_dev_get_exec(
const io_dev_t *dev)
364 io_sigset_impl_pop(impl, &queue, task);
366 return io_sigset_wait_queue_post(&queue, 0);
377 io_sigset_impl_pop(impl, &queue, task);
385 const struct io_sigset_impl *impl = io_sigset_impl_from_sigset(sigset);
387 return &impl->dev_vptr;
395 EnterCriticalSection(&io_sigset_shared.CriticalSection);
396 for (
int i = 1; i < LELY_NSIG; i++)
397 io_sigset_impl_do_remove(impl, i);
398 LeaveCriticalSection(&io_sigset_shared.CriticalSection);
404 io_sigset_impl_insert(
io_sigset_t *sigset,
int signo)
408 if (signo <= 0 || signo >= LELY_NSIG) {
409 SetLastError(ERROR_INVALID_PARAMETER);
413 EnterCriticalSection(&io_sigset_shared.CriticalSection);
414 io_sigset_impl_do_insert(impl, signo);
415 LeaveCriticalSection(&io_sigset_shared.CriticalSection);
421 io_sigset_impl_remove(
io_sigset_t *sigset,
int signo)
425 if (signo <= 0 || signo >= LELY_NSIG) {
426 SetLastError(ERROR_INVALID_PARAMETER);
430 EnterCriticalSection(&io_sigset_shared.CriticalSection);
431 io_sigset_impl_do_remove(impl, signo);
432 LeaveCriticalSection(&io_sigset_shared.CriticalSection);
445 task->
exec = impl->exec;
449 EnterCriticalSection(&impl->CriticalSection);
451 if (impl->shutdown) {
453 LeaveCriticalSection(&impl->CriticalSection);
455 io_sigset_wait_post(wait, 0);
458 int post_wait = !impl->wait_posted && impl->pending;
460 impl->wait_posted = 1;
462 LeaveCriticalSection(&impl->CriticalSection);
471 io_sigset_impl_svc_shutdown(
struct io_svc *svc)
477 EnterCriticalSection(&impl->CriticalSection);
479 int shutdown = !impl->shutdown;
483 if (shutdown && impl->wait_posted
487 impl->wait_posted = 0;
489 LeaveCriticalSection(&impl->CriticalSection);
494 io_sigset_impl_dev_cancel(dev, NULL);
498 io_sigset_impl_signal_cp_func(
struct io_cp *cp,
size_t nbytes,
int errc)
507 EnterCriticalSection(&impl->CriticalSection);
510 int post_wait = !impl->wait_posted && !
sllist_empty(&impl->queue)
513 impl->wait_posted = 1;
515 LeaveCriticalSection(&impl->CriticalSection);
518 EnterCriticalSection(&io_sigset_shared.CriticalSection);
519 impl->signal_posted = 0;
520 LeaveCriticalSection(&io_sigset_shared.CriticalSection);
527 io_sigset_impl_wait_task_func(
struct ev_task *task)
534 int signo = LELY_NSIG;
537 EnterCriticalSection(&impl->CriticalSection);
540 EnterCriticalSection(&io_sigset_shared.CriticalSection);
551 LeaveCriticalSection(&io_sigset_shared.CriticalSection);
554 impl->pending = signo != LELY_NSIG;
555 int post_wait = impl->wait_posted = impl->pending
558 LeaveCriticalSection(&impl->CriticalSection);
562 io_sigset_wait_post(wait, signo);
569 io_sigset_impl_from_dev(
const io_dev_t *dev)
577 io_sigset_impl_from_sigset(
const io_sigset_t *sigset)
585 io_sigset_impl_from_svc(
const struct io_svc *svc)
600 EnterCriticalSection(&impl->CriticalSection);
607 LeaveCriticalSection(&impl->CriticalSection);
616 assert(signo < LELY_NSIG);
619 assert(node->signo == signo);
624 assert(!node->pending);
626 node->next = io_sigset_shared.list[signo - 1];
627 io_sigset_shared.list[signo - 1] = node;
635 assert(signo < LELY_NSIG);
638 assert(node->signo == signo);
647 while (*
pnode != node)
649 assert(*
pnode == node);
654 #endif // !LELY_NO_STDIO && _WIN32