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) {
326 assert(node->watched);
327 if (!node->pending) {
329 if (!impl->signal_posted) {
330 impl->signal_posted = 1;
335 LeaveCriticalSection(&io_sigset_shared.CriticalSection);
340 io_sigset_impl_dev_get_ctx(
const io_dev_t *dev)
348 io_sigset_impl_dev_get_exec(
const io_dev_t *dev)
363 io_sigset_impl_pop(impl, &queue, task);
365 return io_sigset_wait_queue_post(&queue, 0);
376 io_sigset_impl_pop(impl, &queue, task);
384 const struct io_sigset_impl *impl = io_sigset_impl_from_sigset(sigset);
386 return &impl->dev_vptr;
394 EnterCriticalSection(&io_sigset_shared.CriticalSection);
395 for (
int i = 1; i < LELY_NSIG; i++)
396 io_sigset_impl_do_remove(impl, i);
397 LeaveCriticalSection(&io_sigset_shared.CriticalSection);
403 io_sigset_impl_insert(
io_sigset_t *sigset,
int signo)
407 if (signo <= 0 || signo >= LELY_NSIG) {
408 SetLastError(ERROR_INVALID_PARAMETER);
412 EnterCriticalSection(&io_sigset_shared.CriticalSection);
413 io_sigset_impl_do_insert(impl, signo);
414 LeaveCriticalSection(&io_sigset_shared.CriticalSection);
420 io_sigset_impl_remove(
io_sigset_t *sigset,
int signo)
424 if (signo <= 0 || signo >= LELY_NSIG) {
425 SetLastError(ERROR_INVALID_PARAMETER);
429 EnterCriticalSection(&io_sigset_shared.CriticalSection);
430 io_sigset_impl_do_remove(impl, signo);
431 LeaveCriticalSection(&io_sigset_shared.CriticalSection);
444 task->
exec = impl->exec;
448 EnterCriticalSection(&impl->CriticalSection);
450 if (impl->shutdown) {
452 LeaveCriticalSection(&impl->CriticalSection);
454 io_sigset_wait_post(wait, 0);
457 int post_wait = !impl->wait_posted && impl->pending;
459 impl->wait_posted = 1;
461 LeaveCriticalSection(&impl->CriticalSection);
469 io_sigset_impl_svc_shutdown(
struct io_svc *svc)
475 EnterCriticalSection(&impl->CriticalSection);
477 int shutdown = !impl->shutdown;
481 if (shutdown && impl->wait_posted
485 impl->wait_posted = 0;
487 LeaveCriticalSection(&impl->CriticalSection);
492 io_sigset_impl_dev_cancel(dev, NULL);
496 io_sigset_impl_signal_cp_func(
struct io_cp *cp,
size_t nbytes,
int errc)
505 EnterCriticalSection(&impl->CriticalSection);
508 int post_wait = !impl->wait_posted && !
sllist_empty(&impl->queue)
511 impl->wait_posted = 1;
513 LeaveCriticalSection(&impl->CriticalSection);
516 EnterCriticalSection(&io_sigset_shared.CriticalSection);
517 impl->signal_posted = 0;
518 LeaveCriticalSection(&io_sigset_shared.CriticalSection);
525 io_sigset_impl_wait_task_func(
struct ev_task *task)
532 int signo = LELY_NSIG;
535 EnterCriticalSection(&impl->CriticalSection);
538 EnterCriticalSection(&io_sigset_shared.CriticalSection);
549 LeaveCriticalSection(&io_sigset_shared.CriticalSection);
552 impl->pending = signo != LELY_NSIG;
553 int post_wait = impl->wait_posted = impl->pending
556 LeaveCriticalSection(&impl->CriticalSection);
560 io_sigset_wait_post(wait, signo);
567 io_sigset_impl_from_dev(
const io_dev_t *dev)
575 io_sigset_impl_from_sigset(
const io_sigset_t *sigset)
583 io_sigset_impl_from_svc(
const struct io_svc *svc)
598 EnterCriticalSection(&impl->CriticalSection);
605 LeaveCriticalSection(&impl->CriticalSection);
614 assert(signo < LELY_NSIG);
617 assert(node->signo == signo);
622 assert(!node->pending);
624 node->next = io_sigset_shared.list[signo - 1];
625 io_sigset_shared.list[signo - 1] = node;
633 assert(signo < LELY_NSIG);
636 assert(node->signo == signo);
645 while (*
pnode != node)
647 assert(*
pnode == node);