1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2016 Joyent, Inc.
14 */
15
16 /*
17 * Support for the signalfd facility, a Linux-borne facility for
18 * file descriptor-based synchronous signal consumption.
19 *
20 * As described on the signalfd(3C) man page, the general idea behind these
21 * file descriptors is that they can be used to synchronously consume signals
22 * via the read(2) syscall. While that capability already exists with the
23 * sigwaitinfo(3C) function, signalfd holds an advantage since it is file
24 * descriptor based: It is able use the event facilities (poll(2), /dev/poll,
25 * event ports) to notify interested parties when consumable signals arrive.
26 *
27 * The signalfd lifecycle begins When a process opens /dev/signalfd. A minor
28 * will be allocated for them along with an associated signalfd_state_t struct.
29 * It is there where the mask of desired signals resides.
30 *
31 * Reading from the signalfd is straightforward and mimics the kernel behavior
32 * for sigtimedwait(). Signals continue to live on either the proc's p_sig, or
33 * thread's t_sig, member. During a read operation, those which match the mask
543 res = 0;
544
545 return (res);
546 }
547
548 /*
549 * If ksigset_t's were a single word, we would do:
550 * return (((p->p_sig | t->t_sig) & set) & fillset);
551 */
552 static int
553 signalfd_sig_pending(proc_t *p, kthread_t *t, k_sigset_t set)
554 {
555 return (((p->p_sig.__sigbits[0] | t->t_sig.__sigbits[0]) &
556 set.__sigbits[0]) |
557 ((p->p_sig.__sigbits[1] | t->t_sig.__sigbits[1]) &
558 set.__sigbits[1]) |
559 (((p->p_sig.__sigbits[2] | t->t_sig.__sigbits[2]) &
560 set.__sigbits[2]) & FILLSET2));
561 }
562
563 _NOTE(ARGSUSED(4))
564 static int
565 signalfd_poll(dev_t dev, short events, int anyyet, short *reventsp,
566 struct pollhead **phpp)
567 {
568 signalfd_state_t *state, **sstate;
569 minor_t minor = getminor(dev);
570 kthread_t *t = curthread;
571 proc_t *p = ttoproc(t);
572 short revents = 0;
573
574 sstate = ddi_get_soft_state(signalfd_softstate, minor);
575 state = *sstate;
576
577 mutex_enter(&state->sfd_lock);
578
579 if (signalfd_sig_pending(p, t, state->sfd_set) != 0)
580 revents |= POLLRDNORM | POLLIN;
581
582 mutex_exit(&state->sfd_lock);
583
584 if (!(*reventsp = revents & events) && !anyyet) {
585 sigfd_proc_state_t *pstate;
586 sigfd_poll_waiter_t *pw;
587
588 /*
589 * Enable pollwakeup handling.
590 */
591 mutex_enter(&p->p_lock);
592 if ((pstate = (sigfd_proc_state_t *)p->p_sigfd) == NULL) {
593
594 mutex_exit(&p->p_lock);
595 pstate = kmem_zalloc(sizeof (*pstate), KM_SLEEP);
596 list_create(&pstate->sigfd_list,
597 sizeof (sigfd_poll_waiter_t),
598 offsetof(sigfd_poll_waiter_t, spw_list));
599 pstate->sigfd_pollwake_cb = signalfd_pollwake_cb;
600
601 /* Check again, after blocking for the alloc. */
602 mutex_enter(&p->p_lock);
603 if (p->p_sigfd == NULL) {
604 p->p_sigfd = pstate;
|
1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2017 Joyent, Inc.
14 */
15
16 /*
17 * Support for the signalfd facility, a Linux-borne facility for
18 * file descriptor-based synchronous signal consumption.
19 *
20 * As described on the signalfd(3C) man page, the general idea behind these
21 * file descriptors is that they can be used to synchronously consume signals
22 * via the read(2) syscall. While that capability already exists with the
23 * sigwaitinfo(3C) function, signalfd holds an advantage since it is file
24 * descriptor based: It is able use the event facilities (poll(2), /dev/poll,
25 * event ports) to notify interested parties when consumable signals arrive.
26 *
27 * The signalfd lifecycle begins When a process opens /dev/signalfd. A minor
28 * will be allocated for them along with an associated signalfd_state_t struct.
29 * It is there where the mask of desired signals resides.
30 *
31 * Reading from the signalfd is straightforward and mimics the kernel behavior
32 * for sigtimedwait(). Signals continue to live on either the proc's p_sig, or
33 * thread's t_sig, member. During a read operation, those which match the mask
543 res = 0;
544
545 return (res);
546 }
547
548 /*
549 * If ksigset_t's were a single word, we would do:
550 * return (((p->p_sig | t->t_sig) & set) & fillset);
551 */
552 static int
553 signalfd_sig_pending(proc_t *p, kthread_t *t, k_sigset_t set)
554 {
555 return (((p->p_sig.__sigbits[0] | t->t_sig.__sigbits[0]) &
556 set.__sigbits[0]) |
557 ((p->p_sig.__sigbits[1] | t->t_sig.__sigbits[1]) &
558 set.__sigbits[1]) |
559 (((p->p_sig.__sigbits[2] | t->t_sig.__sigbits[2]) &
560 set.__sigbits[2]) & FILLSET2));
561 }
562
563 static int
564 signalfd_poll(dev_t dev, short events, int anyyet, short *reventsp,
565 struct pollhead **phpp)
566 {
567 signalfd_state_t *state, **sstate;
568 minor_t minor = getminor(dev);
569 kthread_t *t = curthread;
570 proc_t *p = ttoproc(t);
571 short revents = 0;
572
573 sstate = ddi_get_soft_state(signalfd_softstate, minor);
574 state = *sstate;
575
576 mutex_enter(&state->sfd_lock);
577
578 if (signalfd_sig_pending(p, t, state->sfd_set) != 0)
579 revents |= POLLRDNORM | POLLIN;
580
581 mutex_exit(&state->sfd_lock);
582
583 *reventsp = revents & events;
584 if ((*reventsp == 0 && !anyyet) || (events & POLLET)) {
585 sigfd_proc_state_t *pstate;
586 sigfd_poll_waiter_t *pw;
587
588 /*
589 * Enable pollwakeup handling.
590 */
591 mutex_enter(&p->p_lock);
592 if ((pstate = (sigfd_proc_state_t *)p->p_sigfd) == NULL) {
593
594 mutex_exit(&p->p_lock);
595 pstate = kmem_zalloc(sizeof (*pstate), KM_SLEEP);
596 list_create(&pstate->sigfd_list,
597 sizeof (sigfd_poll_waiter_t),
598 offsetof(sigfd_poll_waiter_t, spw_list));
599 pstate->sigfd_pollwake_cb = signalfd_pollwake_cb;
600
601 /* Check again, after blocking for the alloc. */
602 mutex_enter(&p->p_lock);
603 if (p->p_sigfd == NULL) {
604 p->p_sigfd = pstate;
|