0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * CDDL HEADER START
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * The contents of this file are subject to the terms of the
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Common Development and Distribution License (the "License").
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * You may not use this file except in compliance with the License.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * or http://www.opensolaris.org/os/licensing.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * See the License for the specific language governing permissions
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * and limitations under the License.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * When distributing Covered Code, include this CDDL HEADER in each
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * If applicable, add the following below this CDDL HEADER, with the
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * fields enclosed by brackets "[]" replaced with your own identifying
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * information: Portions Copyright [yyyy] [name of copyright owner]
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * CDDL HEADER END
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill/*
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill * Copyright (c) 2014, Joyent, Inc. All rights reserved.
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill */
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <sys/types.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <sys/param.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <sys/systm.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <sys/stropts.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <sys/socketvar.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <sys/ksocket.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <io/ksocket/ksocket_impl.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <fs/sockfs/sockcommon.h>
bbc000e522dec6271bdf858a8b013d7fc4c10ed4Anders Persson#include <fs/sockfs/sodirect.h>
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson#include <fs/sockfs/sockfilter_impl.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * There can only be a single thread waiting for data (enforced by
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * so_lock_read()), whereas for write there might be multiple threads
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * waiting for transmit buffers. So therefore we use cv_broadcast for
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * write and cv_signal for read.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#define SO_WAKEUP_READER(so) { \
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((so)->so_rcv_wakeup) { \
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (so)->so_rcv_wakeup = B_FALSE; \
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning cv_signal(&(so)->so_rcv_cv); \
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } \
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#define SO_WAKEUP_WRITER(so) { \
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((so)->so_snd_wakeup) { \
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (so)->so_snd_wakeup = B_FALSE; \
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning cv_broadcast(&(so)->so_snd_cv); \
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } \
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningstatic int i_so_notify_last_rx(struct sonode *, int *, int *);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningstatic int i_so_notify_last_tx(struct sonode *, int *, int *);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * The notification functions must be called with so_lock held,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * and they will all *drop* so_lock before returning.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Wake up anyone waiting for the connection to be established.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningvoid
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_notify_connected(struct sonode *so)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(MUTEX_HELD(&so->so_lock));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (IS_KERNEL_SOCKET(so)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning KSOCKET_CALLBACK(so, connected, 0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning socket_sendsig(so, SOCKETSIG_WRITE);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning pollwakeup(&so->so_poll_list, POLLOUT);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_sonode_notify_filters(so, SOF_EV_CONNECTED, 0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(MUTEX_NOT_HELD(&so->so_lock));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * The socket is disconnecting, so no more data can be sent. Wake up
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * anyone that is waiting to send data.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningvoid
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_notify_disconnecting(struct sonode *so)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int pollev = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int sigev = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(MUTEX_HELD(&so->so_lock));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson (void) i_so_notify_last_tx(so, &pollev, &sigev);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (IS_KERNEL_SOCKET(so)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning KSOCKET_CALLBACK(so, cantsendmore, 0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (sigev != 0)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson socket_sendsig(so, sigev);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (pollev != 0)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson pollwakeup(&so->so_poll_list, pollev);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_sonode_notify_filters(so, SOF_EV_CANTSENDMORE, 0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(MUTEX_NOT_HELD(&so->so_lock));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * The socket is disconnected, so not more data can be sent or received.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Wake up anyone that is waiting to send or receive data.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningvoid
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Perssonso_notify_disconnected(struct sonode *so, boolean_t connfailed, int error)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int pollev = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int sigev = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(MUTEX_HELD(&so->so_lock));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (void) i_so_notify_last_tx(so, &pollev, &sigev);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (void) i_so_notify_last_rx(so, &pollev, &sigev);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (IS_KERNEL_SOCKET(so)) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (connfailed) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson KSOCKET_CALLBACK(so, disconnected, error);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson } else {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson KSOCKET_CALLBACK(so, connectfailed, error);
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (sigev != 0)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning socket_sendsig(so, sigev);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill /*
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill * If we're here because the socket has become disconnected,
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill * we explicitly set POLLHUP. At the same time, we also clear
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill * POLLOUT, as POLLOUT and POLLHUP are defined to be mutually
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill * exclusive with respect to one another.
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill */
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill if (!connfailed)
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill pollev = (pollev | POLLHUP) & ~POLLOUT;
68846fd00135fb0b10944e7806025cbefcfd6546Bryan Cantrill
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (pollev != 0)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning pollwakeup(&so->so_poll_list, pollev);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_sonode_notify_filters(so, (connfailed) ? SOF_EV_CONNECTFAILED :
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson SOF_EV_DISCONNECTED, error);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(MUTEX_NOT_HELD(&so->so_lock));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * The socket is writeable. Wake up anyone waiting to send data.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningvoid
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_notify_writable(struct sonode *so)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(MUTEX_HELD(&so->so_lock));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_WAKEUP_WRITER(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (IS_KERNEL_SOCKET(so)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning KSOCKET_CALLBACK(so, cansend, 0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning socket_sendsig(so, SOCKETSIG_WRITE);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning pollwakeup(&so->so_poll_list, POLLOUT);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(MUTEX_NOT_HELD(&so->so_lock));
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson /* filters can start injecting data */
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson if (so->so_filter_active > 0)
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_sonode_notify_filters(so, SOF_EV_INJECT_DATA_OUT_OK, 0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Data is available, so wake up anyone waiting for data.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningvoid
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_notify_data(struct sonode *so, size_t qlen)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(MUTEX_HELD(&so->so_lock));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_WAKEUP_READER(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (IS_KERNEL_SOCKET(so)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning KSOCKET_CALLBACK(so, newdata, qlen);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning socket_sendsig(so, SOCKETSIG_READ);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (so->so_pollev & (SO_POLLEV_IN|SO_POLLEV_ALWAYS)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_pollev &= ~SO_POLLEV_IN;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning pollwakeup(&so->so_poll_list, POLLIN|POLLRDNORM);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(MUTEX_NOT_HELD(&so->so_lock));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Transient error. Wake up anyone waiting to send or receive data.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningvoid
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_notify_error(struct sonode *so)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(MUTEX_HELD(&so->so_lock));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_WAKEUP_WRITER(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_WAKEUP_READER(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (IS_KERNEL_SOCKET(so)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning KSOCKET_CALLBACK(so, error, 0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning socket_sendsig(so, SOCKETSIG_WRITE|SOCKETSIG_READ);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_pollev &= ~SO_POLLEV_IN;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning pollwakeup(&so->so_poll_list, POLLOUT|POLLIN|POLLRDNORM);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(MUTEX_NOT_HELD(&so->so_lock));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Out-of-band data is incoming, notify any interested parties.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningvoid
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_notify_oobsig(struct sonode *so)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning socket_sendsig(so, SOCKETSIG_URG);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning pollwakeup(&so->so_poll_list, POLLRDBAND);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Received out-of-band data. If the OOB data is delivered inline, then
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * in addition of regular OOB notification, anyone waiting for normal
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * data is also notified.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningvoid
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_notify_oobdata(struct sonode *so, boolean_t oob_inline)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(MUTEX_HELD(&so->so_lock));
bbc000e522dec6271bdf858a8b013d7fc4c10ed4Anders Persson if (so->so_direct != NULL)
bbc000e522dec6271bdf858a8b013d7fc4c10ed4Anders Persson SOD_UIOAFINI(so->so_direct);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
8591a19ae7627d4f6ddb6168875db0d053972cbcAnders Persson SO_WAKEUP_READER(so);
8591a19ae7627d4f6ddb6168875db0d053972cbcAnders Persson
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (IS_KERNEL_SOCKET(so)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning KSOCKET_CALLBACK(so, oobdata, 0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (oob_inline) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning socket_sendsig(so, SOCKETSIG_READ);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_pollev &= ~SO_POLLEV_IN;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning pollwakeup(&so->so_poll_list,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning POLLRDBAND|POLLIN|POLLRDNORM);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning pollwakeup(&so->so_poll_list, POLLRDBAND);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(MUTEX_NOT_HELD(&so->so_lock));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * End-of-file has been reach, so peer will send no new data. Wake up
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * anyone that is waiting for data.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningvoid
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_notify_eof(struct sonode *so)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int pollev = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int sigev = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(MUTEX_HELD(&so->so_lock));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (void) i_so_notify_last_rx(so, &pollev, &sigev);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (IS_KERNEL_SOCKET(so)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning KSOCKET_CALLBACK(so, cantrecvmore, 0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (sigev != 0)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning socket_sendsig(so, sigev);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (pollev != 0)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning pollwakeup(&so->so_poll_list, pollev);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson sof_sonode_notify_filters(so, SOF_EV_CANTRECVMORE, 0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(MUTEX_NOT_HELD(&so->so_lock));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Wake up anyone waiting for a new connection.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningvoid
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_notify_newconn(struct sonode *so)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(MUTEX_HELD(&so->so_lock));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (IS_KERNEL_SOCKET(so)) {
3e95bd4ab92abca814bd28e854607d1975c7dc88Anders Persson KSOCKET_CALLBACK(so, newconn, 0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning socket_sendsig(so, SOCKETSIG_READ);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (so->so_pollev & (SO_POLLEV_IN|SO_POLLEV_ALWAYS)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_pollev &= ~SO_POLLEV_IN;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning pollwakeup(&so->so_poll_list, POLLIN|POLLRDNORM);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(MUTEX_NOT_HELD(&so->so_lock));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * User initated shutdown/close, wake anyone that is trying to do
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * an operation that is no longer possible.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningvoid
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningso_notify_shutdown(struct sonode *so)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int pollev = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int sigev = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(MUTEX_HELD(&so->so_lock));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(so->so_state & (SS_CANTSENDMORE|SS_CANTRCVMORE));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (so->so_state & SS_CANTSENDMORE)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (void) i_so_notify_last_tx(so, &pollev, &sigev);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (so->so_state & SS_CANTRCVMORE)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (void) i_so_notify_last_rx(so, &pollev, &sigev);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (sigev != 0)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning socket_sendsig(so, sigev);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning mutex_exit(&so->so_lock);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (pollev != 0)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning pollwakeup(&so->so_poll_list, pollev);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ASSERT(MUTEX_NOT_HELD(&so->so_lock));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * No more data will be coming in, and this will be the last notification
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * made.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningstatic int
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningi_so_notify_last_rx(struct sonode *so, int *pollev, int *sigev)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (!(so->so_state & SS_SENTLASTREADSIG)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SOCKET_TIMER_CANCEL(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_WAKEUP_READER(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_state |= SS_SENTLASTREADSIG;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_pollev &= ~SO_POLLEV_IN;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
a5eb7107f06a6e23e8e77e8d3a84c1ff90a73ac6Bryan Cantrill *pollev |= POLLIN|POLLRDNORM|POLLRDHUP;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *sigev |= SOCKETSIG_READ;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (1);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning/*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * The socket is un-writeable. Make one last notification.
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningstatic int
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningi_so_notify_last_tx(struct sonode *so, int *pollev, int *sigev)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (!(so->so_state & SS_SENTLASTWRITESIG)) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_WAKEUP_WRITER(so);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning so->so_state |= SS_SENTLASTWRITESIG;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *pollev |= POLLOUT;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning *sigev |= SOCKETSIG_WRITE;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (1);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (0);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning}