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);
539 for (signo = 1; signo < LELY_NSIG; signo++) {
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)
646 pnode = &(*pnode)->next;
647 assert(*pnode == node);
void ev_exec_post(ev_exec_t *exec, struct ev_task *task)
Submits *task to *exec for execution.
const struct ev_exec_vtbl *const ev_exec_t
An abstract task executor.
struct ev_task task
The task (to be) submitted upon completion (or cancellation) of the wait operation.
#define EV_TASK_INIT(exec, func)
The static initializer for ev_task.
This header file is part of the I/O library; it contains the I/O context and service declarations...
An I/O polling interface.
const struct io_sigset_vtbl *const io_sigset_t
An abstract signal handler.
size_t ev_task_queue_abort(struct sllist *queue)
Aborts the tasks in queue by invoking ev_exec_on_task_fini() for each of them.
This header file is part of the I/O library; it contains the I/O polling declarations for Windows...
size_t ev_exec_abort(ev_exec_t *exec, struct ev_task *task)
Aborts the specified task submitted to *exec, if it has not yet begun executing, or all pending tasks...
void io_ctx_insert(io_ctx_t *ctx, struct io_svc *svc)
Registers an I/O service with an I/O context.
#define IO_CP_INIT(func)
The static initializer for io_cp.
struct slnode * sllist_pop_front(struct sllist *list)
Pops a node from the front of a singly-linked list.
struct sllist * sllist_append(struct sllist *dst, struct sllist *src)
Appends the singly-linked list at src to the one at dst.
struct slnode * sllist_remove(struct sllist *list, struct slnode *node)
Removes a node from a singly-linked list.
A wait operation suitable for use with a signal handler.
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
void sllist_push_back(struct sllist *list, struct slnode *node)
Pushes a node to the back of a singly-linked list.
This header file is part of the utilities library; it contains the native and platform-independent er...
ev_exec_t * exec
A pointer to the executor to which the task is (to be) submitted.
An I/O completion packet.
int io_poll_post(io_poll_t *poll, size_t nbytes, struct io_cp *cp)
Posts a completion packet to the I/O completion port of an I/O polling instance.
void ev_exec_on_task_init(ev_exec_t *exec)
Indicates to the specified executor that a task will be submitted for execution in the future...
void io_sigset_destroy(io_sigset_t *sigset)
Destroys a system signal handler.
int errno2c(int errnum)
Transforms a standard C error number to a native error code.
This is the internal header file of the Windows-specific I/O declarations.
struct io_sigset_wait * io_sigset_wait_from_task(struct ev_task *task)
Obtains a pointer to a signal wait operation from a pointer to its completion task.
void io_ctx_remove(io_ctx_t *ctx, struct io_svc *svc)
Unregisters an I/O service with an I/O context.
io_ctx_t * io_poll_get_ctx(const io_poll_t *poll)
Returns a pointer to the I/O context with which the I/O polling instance is registered.
int sllist_empty(const struct sllist *list)
Returns 1 if the singly-linked list is empty, and 0 if not.
#define structof(ptr, type, member)
Obtains the address of a structure from the address of one of its members.
The virtual table of an I/O service.
This header file is part of the I/O library; it contains the system signal handler declarations...
#define IO_SVC_INIT(vptr)
The static initializer for io_svc.
struct ev_task * ev_task_from_node(struct slnode *node)
Converts a pointer to a node in a queue to the address of the task containing the node...
This header file is part of the C11 and POSIX compatibility library; it includes <stdlib.h> and defines any missing functionality.
void sllist_init(struct sllist *list)
Initializes a singly-linked list.
const struct io_dev_vtbl *const io_dev_t
An abstract I/O device.
This is the public header file of the utilities library.
io_sigset_t * io_sigset_create(io_poll_t *poll, ev_exec_t *exec)
Creates a new system signal handler.
A node in a pairing heap.