3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek/*
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * This file and its contents are supplied under the terms of the
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * Common Development and Distribution License ("CDDL"), version 1.0.
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * You may only use this file in accordance with the terms of version
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * 1.0 of the CDDL.
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek *
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * A full copy of the text of the CDDL should have accompanied this
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * source. A copy of the CDDL is also available via the Internet at
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * http://www.illumos.org/license/CDDL.
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek/*
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * Copyright 2016 Joyent, Inc.
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek/*
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * Support for the signalfd facility, a Linux-borne facility for
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * file descriptor-based synchronous signal consumption.
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek *
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * As described on the signalfd(3C) man page, the general idea behind these
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * file descriptors is that they can be used to synchronously consume signals
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * via the read(2) syscall. While that capability already exists with the
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * sigwaitinfo(3C) function, signalfd holds an advantage since it is file
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * descriptor based: It is able use the event facilities (poll(2), /dev/poll,
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * event ports) to notify interested parties when consumable signals arrive.
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek *
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * The signalfd lifecycle begins When a process opens /dev/signalfd. A minor
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * will be allocated for them along with an associated signalfd_state_t struct.
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * It is there where the mask of desired signals resides.
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek *
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * Reading from the signalfd is straightforward and mimics the kernel behavior
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * for sigtimedwait(). Signals continue to live on either the proc's p_sig, or
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * thread's t_sig, member. During a read operation, those which match the mask
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * are consumed so they are no longer pending.
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek *
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * The poll side is more complex. Every time a signal is delivered, all of the
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * signalfds on the process need to be examined in order to pollwake threads
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * waiting for signal arrival.
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek *
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * When a thread polling on a signalfd requires a pollhead, several steps must
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * be taken to safely ensure the proper result. A sigfd_proc_state_t is
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * created for the calling process if it does not yet exist. It is there where
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * a list of sigfd_poll_waiter_t structures reside which associate pollheads to
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * signalfd_state_t entries. The sigfd_proc_state_t list is walked to find a
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * sigfd_poll_waiter_t matching the signalfd_state_t which corresponds to the
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * polled resource. If one is found, it is reused. Otherwise a new one is
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * created, incrementing the refcount on the signalfd_state_t, and it is added
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * to the sigfd_poll_waiter_t list.
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek *
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * The complications imposed by fork(2) are why the pollhead is stored in the
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * associated sigfd_poll_waiter_t instead of directly in the signalfd_state_t.
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * More than one process can hold a reference to the signalfd at a time but
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * arriving signals should wake only process-local pollers. Additionally,
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * signalfd_close is called only when the last referencing fd is closed, hiding
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * occurrences of preceeding threads which released their references. This
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * necessitates reference counting on the signalfd_state_t so it is able to
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * persist after close until all poll references have been cleansed. Doing so
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * ensures that blocked pollers which hold references to the signalfd_state_t
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * will be able to do clean-up after the descriptor itself has been closed.
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek *
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * When a signal arrives in a process polling on signalfd, signalfd_pollwake_cb
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * is called via the pointer in sigfd_proc_state_t. It will walk over the
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * sigfd_poll_waiter_t entries present in the list, searching for any
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * associated with a signalfd_state_t with a matching signal mask. The
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * approach of keeping the poller list in p_sigfd was chosen because a process
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * is likely to use few signalfds relative to its total file descriptors. It
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * reduces the work required for each received signal.
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney *
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * When matching sigfd_poll_waiter_t entries are encountered in the poller list
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * during signalfd_pollwake_cb, they are dispatched into signalfd_wakeq to
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * perform the pollwake. This is due to a lock ordering conflict between
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * signalfd_poll and signalfd_pollwake_cb. The former acquires
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * pollcache_t`pc_lock before proc_t`p_lock. The latter (via sigtoproc)
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * reverses the order. Defering the pollwake into a taskq means it can be
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * performed without proc_t`p_lock held, avoiding the deadlock.
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek *
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * The sigfd_list is self-cleaning; as signalfd_pollwake_cb is called, the list
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * will clear out on its own. Any remaining per-process state which remains
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * will be cleaned up by the exit helper (signalfd_exit_helper).
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek *
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * The structures associated with signalfd state are designed to operate
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * correctly across fork, but there is one caveat that applies. Using
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * fork-shared signalfd descriptors in conjuction with fork-shared caching poll
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * descriptors (such as /dev/poll or event ports) will result in missed poll
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * wake-ups. This is caused by the pollhead identity of signalfd descriptors
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * being dependent on the process they are polled from. Because it has a
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * thread-local cache, poll(2) is unaffected by this limitation.
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek *
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * Lock ordering:
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek *
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * 1. signalfd_lock
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * 2. signalfd_state_t`sfd_lock
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek *
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * 1. proc_t`p_lock (to walk p_sigfd)
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * 2. signalfd_state_t`sfd_lock
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * 2a. signalfd_lock (after sfd_lock is dropped, when sfd_count falls to 0)
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek#include <sys/ddi.h>
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek#include <sys/sunddi.h>
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek#include <sys/signalfd.h>
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek#include <sys/conf.h>
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek#include <sys/sysmacros.h>
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek#include <sys/filio.h>
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek#include <sys/stat.h>
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek#include <sys/file.h>
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek#include <sys/schedctl.h>
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek#include <sys/id_space.h>
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek#include <sys/sdt.h>
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney#include <sys/disp.h>
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney#include <sys/taskq_impl.h>
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinektypedef struct signalfd_state signalfd_state_t;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinekstruct signalfd_state {
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney list_node_t sfd_list; /* node in global list */
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney kmutex_t sfd_lock; /* protects fields below */
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney uint_t sfd_count; /* ref count */
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney boolean_t sfd_valid; /* valid while open */
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney k_sigset_t sfd_set; /* signals for this fd */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek};
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooneytypedef struct sigfd_poll_waiter {
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney list_node_t spw_list;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney signalfd_state_t *spw_state;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney pollhead_t spw_pollhd;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney taskq_ent_t spw_taskent;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney short spw_pollev;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney} sigfd_poll_waiter_t;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek/*
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * Protects global state in signalfd_devi, signalfd_minor, signalfd_softstate,
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * and signalfd_state (including sfd_list field of members)
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek */
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooneystatic kmutex_t signalfd_lock;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinekstatic dev_info_t *signalfd_devi; /* device info */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinekstatic id_space_t *signalfd_minor; /* minor number arena */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinekstatic void *signalfd_softstate; /* softstate pointer */
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooneystatic list_t signalfd_state; /* global list of state */
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooneystatic taskq_t *signalfd_wakeq; /* pollwake event taskq */
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinekstatic void
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooneysignalfd_state_enter_locked(signalfd_state_t *state)
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek{
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney ASSERT(MUTEX_HELD(&state->sfd_lock));
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney ASSERT(state->sfd_count > 0);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney VERIFY(state->sfd_valid == B_TRUE);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney state->sfd_count++;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney}
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooneystatic void
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooneysignalfd_state_release(signalfd_state_t *state, boolean_t force_invalidate)
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney{
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney mutex_enter(&state->sfd_lock);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney if (force_invalidate) {
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney state->sfd_valid = B_FALSE;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek }
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney ASSERT(state->sfd_count > 0);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney if (state->sfd_count == 1) {
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney VERIFY(state->sfd_valid == B_FALSE);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney mutex_exit(&state->sfd_lock);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney if (force_invalidate) {
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney /*
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * The invalidation performed in signalfd_close is done
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * while signalfd_lock is held.
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney */
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney ASSERT(MUTEX_HELD(&signalfd_lock));
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney list_remove(&signalfd_state, state);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney } else {
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney ASSERT(MUTEX_NOT_HELD(&signalfd_lock));
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney mutex_enter(&signalfd_lock);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney list_remove(&signalfd_state, state);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney mutex_exit(&signalfd_lock);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney }
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney kmem_free(state, sizeof (*state));
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney return;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek }
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney state->sfd_count--;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney mutex_exit(&state->sfd_lock);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek}
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooneystatic sigfd_poll_waiter_t *
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooneysignalfd_wake_list_add(sigfd_proc_state_t *pstate, signalfd_state_t *state)
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek{
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney list_t *lst = &pstate->sigfd_list;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney sigfd_poll_waiter_t *pw;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney for (pw = list_head(lst); pw != NULL; pw = list_next(lst, pw)) {
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney if (pw->spw_state == state)
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney break;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney }
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney if (pw == NULL) {
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney pw = kmem_zalloc(sizeof (*pw), KM_SLEEP);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney mutex_enter(&state->sfd_lock);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney signalfd_state_enter_locked(state);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney pw->spw_state = state;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney mutex_exit(&state->sfd_lock);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney list_insert_head(lst, pw);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney }
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney return (pw);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney}
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooneystatic sigfd_poll_waiter_t *
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooneysignalfd_wake_list_rm(sigfd_proc_state_t *pstate, signalfd_state_t *state)
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney{
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney list_t *lst = &pstate->sigfd_list;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney sigfd_poll_waiter_t *pw;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney for (pw = list_head(lst); pw != NULL; pw = list_next(lst, pw)) {
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney if (pw->spw_state == state) {
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek break;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek }
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek }
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney if (pw != NULL) {
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney list_remove(lst, pw);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney pw->spw_state = NULL;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney signalfd_state_release(state, B_FALSE);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek }
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney return (pw);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek}
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinekstatic void
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelineksignalfd_wake_list_cleanup(proc_t *p)
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek{
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney sigfd_proc_state_t *pstate = p->p_sigfd;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney sigfd_poll_waiter_t *pw;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek list_t *lst;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek ASSERT(MUTEX_HELD(&p->p_lock));
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney ASSERT(pstate != NULL);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney lst = &pstate->sigfd_list;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney while ((pw = list_remove_head(lst)) != NULL) {
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney signalfd_state_t *state = pw->spw_state;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney pw->spw_state = NULL;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney signalfd_state_release(state, B_FALSE);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney pollwakeup(&pw->spw_pollhd, POLLERR);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney pollhead_clean(&pw->spw_pollhd);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney kmem_free(pw, sizeof (*pw));
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek }
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney list_destroy(lst);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney p->p_sigfd = NULL;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney kmem_free(pstate, sizeof (*pstate));
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek}
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinekstatic void
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelineksignalfd_exit_helper(void)
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek{
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek proc_t *p = curproc;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_enter(&p->p_lock);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek signalfd_wake_list_cleanup(p);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_exit(&p->p_lock);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek}
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney/*
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * Perform pollwake for a sigfd_poll_waiter_t entry.
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * Thanks to the strict and conflicting lock orders required for signalfd_poll
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * (pc_lock before p_lock) and signalfd_pollwake_cb (p_lock before pc_lock),
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * this is relegated to a taskq to avoid deadlock.
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney */
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooneystatic void
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooneysignalfd_wake_task(void *arg)
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney{
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney sigfd_poll_waiter_t *pw = arg;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney signalfd_state_t *state = pw->spw_state;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney pw->spw_state = NULL;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney signalfd_state_release(state, B_FALSE);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney pollwakeup(&pw->spw_pollhd, pw->spw_pollev);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney pollhead_clean(&pw->spw_pollhd);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney kmem_free(pw, sizeof (*pw));
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney}
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek/*
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * Called every time a signal is delivered to the process so that we can
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * see if any signal stream needs a pollwakeup. We maintain a list of
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * signal state elements so that we don't have to look at every file descriptor
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * on the process. If necessary, a further optimization would be to maintain a
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * signal set mask that is a union of all of the sets in the list so that
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * we don't even traverse the list if the signal is not in one of the elements.
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * However, since the list is likely to be very short, this is not currently
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * being done. A more complex data structure might also be used, but it is
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * unclear what that would be since each signal set needs to be checked for a
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * match.
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinekstatic void
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelineksignalfd_pollwake_cb(void *arg0, int sig)
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek{
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek proc_t *p = (proc_t *)arg0;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney sigfd_proc_state_t *pstate = (sigfd_proc_state_t *)p->p_sigfd;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek list_t *lst;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney sigfd_poll_waiter_t *pw;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek ASSERT(MUTEX_HELD(&p->p_lock));
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney ASSERT(pstate != NULL);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney lst = &pstate->sigfd_list;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney pw = list_head(lst);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney while (pw != NULL) {
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney signalfd_state_t *state = pw->spw_state;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney sigfd_poll_waiter_t *next;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_enter(&state->sfd_lock);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney if (!state->sfd_valid) {
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney pw->spw_pollev = POLLERR;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney } else if (sigismember(&state->sfd_set, sig)) {
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney pw->spw_pollev = POLLRDNORM | POLLIN;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek } else {
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_exit(&state->sfd_lock);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney pw = list_next(lst, pw);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney continue;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek }
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney mutex_exit(&state->sfd_lock);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney /*
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * Pull the sigfd_poll_waiter_t out of the list and dispatch it
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * to perform a pollwake. This cannot be done synchronously
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * since signalfd_poll and signalfd_pollwake_cb have
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * conflicting lock orders which can deadlock.
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney */
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney next = list_next(lst, pw);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney list_remove(lst, pw);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney taskq_dispatch_ent(signalfd_wakeq, signalfd_wake_task, pw, 0,
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney &pw->spw_taskent);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney pw = next;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek }
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek}
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek_NOTE(ARGSUSED(1))
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinekstatic int
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelineksignalfd_open(dev_t *devp, int flag, int otyp, cred_t *cred_p)
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek{
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney signalfd_state_t *state, **sstate;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek major_t major = getemajor(*devp);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek minor_t minor = getminor(*devp);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek if (minor != SIGNALFDMNRN_SIGNALFD)
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek return (ENXIO);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_enter(&signalfd_lock);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek minor = (minor_t)id_allocff(signalfd_minor);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek if (ddi_soft_state_zalloc(signalfd_softstate, minor) != DDI_SUCCESS) {
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek id_free(signalfd_minor, minor);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_exit(&signalfd_lock);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek return (ENODEV);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek }
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney state = kmem_zalloc(sizeof (*state), KM_SLEEP);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney state->sfd_valid = B_TRUE;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney state->sfd_count = 1;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney list_insert_head(&signalfd_state, (void *)state);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney sstate = ddi_get_soft_state(signalfd_softstate, minor);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney *sstate = state;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney *devp = makedevice(major, minor);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_exit(&signalfd_lock);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek return (0);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek}
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek/*
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * Consume one signal from our set in a manner similar to sigtimedwait().
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * The block parameter is used to control whether we wait for a signal or
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * return immediately if no signal is pending. We use the thread's t_sigwait
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * member in the same way that it is used by sigtimedwait.
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek *
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * Return 0 if we successfully consumed a signal or an errno if not.
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinekstatic int
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinekconsume_signal(k_sigset_t set, uio_t *uio, boolean_t block)
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek{
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek k_sigset_t oldmask;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek kthread_t *t = curthread;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek klwp_t *lwp = ttolwp(t);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek proc_t *p = ttoproc(t);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek timespec_t now;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek timespec_t *rqtp = NULL; /* null means blocking */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek int timecheck = 0;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek int ret = 0;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek k_siginfo_t info, *infop;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek signalfd_siginfo_t ssi, *ssp = &ssi;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek if (block == B_FALSE) {
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek timecheck = timechanged;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek gethrestime(&now);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek rqtp = &now; /* non-blocking check for pending signals */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek }
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek t->t_sigwait = set;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_enter(&p->p_lock);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek /*
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * set the thread's signal mask to unmask those signals in the
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * specified set.
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek schedctl_finish_sigblock(t);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek oldmask = t->t_hold;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek sigdiffset(&t->t_hold, &t->t_sigwait);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek /*
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * Based on rqtp, wait indefinitely until we take a signal in our set
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * or return immediately if there are no signals pending from our set.
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek while ((ret = cv_waituntil_sig(&t->t_delay_cv, &p->p_lock, rqtp,
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek timecheck)) > 0)
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek continue;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek /* Restore thread's signal mask to its previous value. */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek t->t_hold = oldmask;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek t->t_sig_check = 1; /* so post_syscall sees new t_hold mask */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek if (ret == -1) {
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek /* no signals pending */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_exit(&p->p_lock);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek sigemptyset(&t->t_sigwait);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek return (EAGAIN); /* no signals pending */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek }
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek /* Don't bother with signal if it is not in request set. */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek if (lwp->lwp_cursig == 0 ||
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek !sigismember(&t->t_sigwait, lwp->lwp_cursig)) {
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_exit(&p->p_lock);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek /*
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * lwp_cursig is zero if pokelwps() awakened cv_wait_sig().
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * This happens if some other thread in this process called
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * forkall() or exit().
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek sigemptyset(&t->t_sigwait);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek return (EINTR);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek }
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek if (lwp->lwp_curinfo) {
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek infop = &lwp->lwp_curinfo->sq_info;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek } else {
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek infop = &info;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek bzero(infop, sizeof (info));
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek infop->si_signo = lwp->lwp_cursig;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek infop->si_code = SI_NOINFO;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek }
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek lwp->lwp_ru.nsignals++;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek DTRACE_PROC2(signal__clear, int, ret, ksiginfo_t *, infop);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek lwp->lwp_cursig = 0;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek lwp->lwp_extsig = 0;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_exit(&p->p_lock);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek /* Convert k_siginfo into external, datamodel independent, struct. */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek bzero(ssp, sizeof (*ssp));
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek ssp->ssi_signo = infop->si_signo;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek ssp->ssi_errno = infop->si_errno;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek ssp->ssi_code = infop->si_code;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek ssp->ssi_pid = infop->si_pid;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek ssp->ssi_uid = infop->si_uid;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek ssp->ssi_fd = infop->si_fd;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek ssp->ssi_band = infop->si_band;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek ssp->ssi_trapno = infop->si_trapno;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek ssp->ssi_status = infop->si_status;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek ssp->ssi_utime = infop->si_utime;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek ssp->ssi_stime = infop->si_stime;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek ssp->ssi_addr = (uint64_t)(intptr_t)infop->si_addr;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek ret = uiomove(ssp, sizeof (*ssp), UIO_READ, uio);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek if (lwp->lwp_curinfo) {
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek siginfofree(lwp->lwp_curinfo);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek lwp->lwp_curinfo = NULL;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek }
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek sigemptyset(&t->t_sigwait);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek return (ret);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek}
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek/*
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * This is similar to sigtimedwait. Based on the fd mode we may wait until a
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * signal within our specified set is posted. We consume as many available
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * signals within our set as we can.
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek_NOTE(ARGSUSED(2))
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinekstatic int
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelineksignalfd_read(dev_t dev, uio_t *uio, cred_t *cr)
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek{
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney signalfd_state_t *state, **sstate;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek minor_t minor = getminor(dev);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek boolean_t block = B_TRUE;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek k_sigset_t set;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek boolean_t got_one = B_FALSE;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek int res;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek if (uio->uio_resid < sizeof (signalfd_siginfo_t))
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek return (EINVAL);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney sstate = ddi_get_soft_state(signalfd_softstate, minor);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney state = *sstate;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek if (uio->uio_fmode & (FNDELAY|FNONBLOCK))
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek block = B_FALSE;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_enter(&state->sfd_lock);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek set = state->sfd_set;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_exit(&state->sfd_lock);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek if (sigisempty(&set))
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek return (set_errno(EINVAL));
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek do {
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney res = consume_signal(set, uio, block);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney if (res == 0) {
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney /*
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * After consuming one signal, do not block while
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * trying to consume more.
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney */
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney got_one = B_TRUE;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney block = B_FALSE;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney /*
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * Refresh the matching signal set in case it was
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * updated during the wait.
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney */
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney mutex_enter(&state->sfd_lock);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney set = state->sfd_set;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney mutex_exit(&state->sfd_lock);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney if (sigisempty(&set))
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney break;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney }
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek } while (res == 0 && uio->uio_resid >= sizeof (signalfd_siginfo_t));
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek if (got_one)
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek res = 0;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek return (res);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek}
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek/*
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * If ksigset_t's were a single word, we would do:
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * return (((p->p_sig | t->t_sig) & set) & fillset);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinekstatic int
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelineksignalfd_sig_pending(proc_t *p, kthread_t *t, k_sigset_t set)
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek{
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek return (((p->p_sig.__sigbits[0] | t->t_sig.__sigbits[0]) &
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek set.__sigbits[0]) |
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek ((p->p_sig.__sigbits[1] | t->t_sig.__sigbits[1]) &
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek set.__sigbits[1]) |
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek (((p->p_sig.__sigbits[2] | t->t_sig.__sigbits[2]) &
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek set.__sigbits[2]) & FILLSET2));
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek}
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek_NOTE(ARGSUSED(4))
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinekstatic int
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelineksignalfd_poll(dev_t dev, short events, int anyyet, short *reventsp,
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek struct pollhead **phpp)
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek{
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney signalfd_state_t *state, **sstate;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek minor_t minor = getminor(dev);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek kthread_t *t = curthread;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek proc_t *p = ttoproc(t);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek short revents = 0;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney sstate = ddi_get_soft_state(signalfd_softstate, minor);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney state = *sstate;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_enter(&state->sfd_lock);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek if (signalfd_sig_pending(p, t, state->sfd_set) != 0)
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek revents |= POLLRDNORM | POLLIN;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_exit(&state->sfd_lock);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek if (!(*reventsp = revents & events) && !anyyet) {
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney sigfd_proc_state_t *pstate;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney sigfd_poll_waiter_t *pw;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek /*
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek * Enable pollwakeup handling.
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek */
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney mutex_enter(&p->p_lock);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney if ((pstate = (sigfd_proc_state_t *)p->p_sigfd) == NULL) {
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney mutex_exit(&p->p_lock);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney pstate = kmem_zalloc(sizeof (*pstate), KM_SLEEP);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek list_create(&pstate->sigfd_list,
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney sizeof (sigfd_poll_waiter_t),
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney offsetof(sigfd_poll_waiter_t, spw_list));
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney pstate->sigfd_pollwake_cb = signalfd_pollwake_cb;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney /* Check again, after blocking for the alloc. */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_enter(&p->p_lock);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek if (p->p_sigfd == NULL) {
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek p->p_sigfd = pstate;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek } else {
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek /* someone beat us to it */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek list_destroy(&pstate->sigfd_list);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney kmem_free(pstate, sizeof (*pstate));
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney pstate = p->p_sigfd;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek }
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek }
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney pw = signalfd_wake_list_add(pstate, state);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney *phpp = &pw->spw_pollhd;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_exit(&p->p_lock);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek }
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek return (0);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek}
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek_NOTE(ARGSUSED(4))
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinekstatic int
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelineksignalfd_ioctl(dev_t dev, int cmd, intptr_t arg, int md, cred_t *cr, int *rv)
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek{
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney signalfd_state_t *state, **sstate;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek minor_t minor = getminor(dev);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek sigset_t mask;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney sstate = ddi_get_soft_state(signalfd_softstate, minor);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney state = *sstate;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek switch (cmd) {
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek case SIGNALFDIOC_MASK:
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek if (ddi_copyin((caddr_t)arg, (caddr_t)&mask, sizeof (sigset_t),
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek md) != 0)
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek return (set_errno(EFAULT));
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_enter(&state->sfd_lock);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek sigutok(&mask, &state->sfd_set);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_exit(&state->sfd_lock);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek return (0);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek default:
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek break;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek }
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek return (ENOTTY);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek}
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek_NOTE(ARGSUSED(1))
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinekstatic int
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelineksignalfd_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek{
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney signalfd_state_t *state, **sstate;
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney sigfd_poll_waiter_t *pw = NULL;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek minor_t minor = getminor(dev);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek proc_t *p = curproc;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney sstate = ddi_get_soft_state(signalfd_softstate, minor);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney state = *sstate;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney /* Make sure state is removed from this proc's pollwake list. */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_enter(&p->p_lock);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney if (p->p_sigfd != NULL) {
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney sigfd_proc_state_t *pstate = p->p_sigfd;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney pw = signalfd_wake_list_rm(pstate, state);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney if (list_is_empty(&pstate->sigfd_list)) {
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney signalfd_wake_list_cleanup(p);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney }
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney }
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney mutex_exit(&p->p_lock);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney if (pw != NULL) {
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney pollwakeup(&pw->spw_pollhd, POLLERR);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney pollhead_clean(&pw->spw_pollhd);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney kmem_free(pw, sizeof (*pw));
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney }
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney mutex_enter(&signalfd_lock);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney *sstate = NULL;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek ddi_soft_state_free(signalfd_softstate, minor);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek id_free(signalfd_minor, minor);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney signalfd_state_release(state, B_TRUE);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_exit(&signalfd_lock);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek return (0);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek}
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinekstatic int
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelineksignalfd_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek{
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek if (cmd != DDI_ATTACH || signalfd_devi != NULL)
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek return (DDI_FAILURE);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_enter(&signalfd_lock);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek signalfd_minor = id_space_create("signalfd_minor", 1, L_MAXMIN32 + 1);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek if (signalfd_minor == NULL) {
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek cmn_err(CE_WARN, "signalfd couldn't create id space");
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_exit(&signalfd_lock);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek return (DDI_FAILURE);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek }
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek if (ddi_soft_state_init(&signalfd_softstate,
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney sizeof (signalfd_state_t *), 0) != 0) {
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek cmn_err(CE_WARN, "signalfd failed to create soft state");
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek id_space_destroy(signalfd_minor);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_exit(&signalfd_lock);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek return (DDI_FAILURE);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek }
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek if (ddi_create_minor_node(devi, "signalfd", S_IFCHR,
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek SIGNALFDMNRN_SIGNALFD, DDI_PSEUDO, NULL) == DDI_FAILURE) {
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek cmn_err(CE_NOTE, "/dev/signalfd couldn't create minor node");
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek ddi_soft_state_fini(&signalfd_softstate);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek id_space_destroy(signalfd_minor);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_exit(&signalfd_lock);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek return (DDI_FAILURE);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek }
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek ddi_report_dev(devi);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek signalfd_devi = devi;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek sigfd_exit_helper = signalfd_exit_helper;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney list_create(&signalfd_state, sizeof (signalfd_state_t),
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney offsetof(signalfd_state_t, sfd_list));
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney signalfd_wakeq = taskq_create("signalfd_wake", 1, minclsyspri,
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney 0, INT_MAX, TASKQ_PREPOPULATE);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_exit(&signalfd_lock);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek return (DDI_SUCCESS);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek}
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek_NOTE(ARGSUSED(0))
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinekstatic int
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelineksignalfd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek{
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek switch (cmd) {
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek case DDI_DETACH:
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek break;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek default:
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek return (DDI_FAILURE);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek }
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_enter(&signalfd_lock);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney if (!list_is_empty(&signalfd_state)) {
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney /*
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * There are dangling poll waiters holding signalfd_state_t
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * entries on the global list. Detach is not possible until
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * they purge themselves.
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney */
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney mutex_exit(&signalfd_lock);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney return (DDI_FAILURE);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney }
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney list_destroy(&signalfd_state);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney /*
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * With no remaining entries in the signalfd_state list, the wake taskq
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney * should be empty with no possibility for new entries.
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney */
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney taskq_destroy(signalfd_wakeq);
abf99a006172ea5aab2246bda23f9d6d935bf1adPatrick Mooney
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek id_space_destroy(signalfd_minor);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek ddi_remove_minor_node(signalfd_devi, NULL);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek signalfd_devi = NULL;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek sigfd_exit_helper = NULL;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek ddi_soft_state_fini(&signalfd_softstate);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek mutex_exit(&signalfd_lock);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek return (DDI_SUCCESS);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek}
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek_NOTE(ARGSUSED(0))
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinekstatic int
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelineksignalfd_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek{
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek int error;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek switch (infocmd) {
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek case DDI_INFO_DEVT2DEVINFO:
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek *result = (void *)signalfd_devi;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek error = DDI_SUCCESS;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek break;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek case DDI_INFO_DEVT2INSTANCE:
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek *result = (void *)0;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek error = DDI_SUCCESS;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek break;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek default:
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek error = DDI_FAILURE;
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek }
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek return (error);
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek}
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinekstatic struct cb_ops signalfd_cb_ops = {
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek signalfd_open, /* open */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek signalfd_close, /* close */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek nulldev, /* strategy */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek nulldev, /* print */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek nodev, /* dump */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek signalfd_read, /* read */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek nodev, /* write */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek signalfd_ioctl, /* ioctl */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek nodev, /* devmap */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek nodev, /* mmap */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek nodev, /* segmap */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek signalfd_poll, /* poll */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek ddi_prop_op, /* cb_prop_op */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek 0, /* streamtab */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek D_NEW | D_MP /* Driver compatibility flag */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek};
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinekstatic struct dev_ops signalfd_ops = {
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek DEVO_REV, /* devo_rev */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek 0, /* refcnt */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek signalfd_info, /* get_dev_info */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek nulldev, /* identify */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek nulldev, /* probe */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek signalfd_attach, /* attach */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek signalfd_detach, /* detach */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek nodev, /* reset */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek &signalfd_cb_ops, /* driver operations */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek NULL, /* bus operations */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek nodev, /* dev power */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek ddi_quiesce_not_needed, /* quiesce */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek};
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinekstatic struct modldrv modldrv = {
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek &mod_driverops, /* module type (this is a pseudo driver) */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek "signalfd support", /* name of module */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek &signalfd_ops, /* driver ops */
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek};
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinekstatic struct modlinkage modlinkage = {
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek MODREV_1,
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek (void *)&modldrv,
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek NULL
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek};
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinekint
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek_init(void)
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek{
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek return (mod_install(&modlinkage));
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek}
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinekint
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek_info(struct modinfo *modinfop)
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek{
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek return (mod_info(&modlinkage, modinfop));
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek}
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinekint
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek_fini(void)
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek{
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek return (mod_remove(&modlinkage));
3d729aecc03ea6ebb9bd5d56b8dccd24f57daa41Jerry Jelinek}