10f1702c5SYu Xiangning /* 20f1702c5SYu Xiangning * CDDL HEADER START 30f1702c5SYu Xiangning * 40f1702c5SYu Xiangning * The contents of this file are subject to the terms of the 50f1702c5SYu Xiangning * Common Development and Distribution License (the "License"). 60f1702c5SYu Xiangning * You may not use this file except in compliance with the License. 70f1702c5SYu Xiangning * 80f1702c5SYu Xiangning * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90f1702c5SYu Xiangning * or http://www.opensolaris.org/os/licensing. 100f1702c5SYu Xiangning * See the License for the specific language governing permissions 110f1702c5SYu Xiangning * and limitations under the License. 120f1702c5SYu Xiangning * 130f1702c5SYu Xiangning * When distributing Covered Code, include this CDDL HEADER in each 140f1702c5SYu Xiangning * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150f1702c5SYu Xiangning * If applicable, add the following below this CDDL HEADER, with the 160f1702c5SYu Xiangning * fields enclosed by brackets "[]" replaced with your own identifying 170f1702c5SYu Xiangning * information: Portions Copyright [yyyy] [name of copyright owner] 180f1702c5SYu Xiangning * 190f1702c5SYu Xiangning * CDDL HEADER END 200f1702c5SYu Xiangning */ 210f1702c5SYu Xiangning 220f1702c5SYu Xiangning /* 233e95bd4aSAnders Persson * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 240f1702c5SYu Xiangning */ 250f1702c5SYu Xiangning 2668846fd0SBryan Cantrill /* 2768846fd0SBryan Cantrill * Copyright (c) 2014, Joyent, Inc. All rights reserved. 2868846fd0SBryan Cantrill */ 2968846fd0SBryan Cantrill 300f1702c5SYu Xiangning #include <sys/types.h> 310f1702c5SYu Xiangning #include <sys/param.h> 320f1702c5SYu Xiangning #include <sys/systm.h> 330f1702c5SYu Xiangning #include <sys/stropts.h> 340f1702c5SYu Xiangning #include <sys/socketvar.h> 350f1702c5SYu Xiangning #include <sys/ksocket.h> 360f1702c5SYu Xiangning #include <io/ksocket/ksocket_impl.h> 370f1702c5SYu Xiangning #include <fs/sockfs/sockcommon.h> 38bbc000e5SAnders Persson #include <fs/sockfs/sodirect.h> 393e95bd4aSAnders Persson #include <fs/sockfs/sockfilter_impl.h> 400f1702c5SYu Xiangning 410f1702c5SYu Xiangning /* 420f1702c5SYu Xiangning * There can only be a single thread waiting for data (enforced by 430f1702c5SYu Xiangning * so_lock_read()), whereas for write there might be multiple threads 440f1702c5SYu Xiangning * waiting for transmit buffers. So therefore we use cv_broadcast for 450f1702c5SYu Xiangning * write and cv_signal for read. 460f1702c5SYu Xiangning */ 470f1702c5SYu Xiangning #define SO_WAKEUP_READER(so) { \ 480f1702c5SYu Xiangning if ((so)->so_rcv_wakeup) { \ 490f1702c5SYu Xiangning (so)->so_rcv_wakeup = B_FALSE; \ 500f1702c5SYu Xiangning cv_signal(&(so)->so_rcv_cv); \ 510f1702c5SYu Xiangning } \ 520f1702c5SYu Xiangning } 530f1702c5SYu Xiangning 540f1702c5SYu Xiangning #define SO_WAKEUP_WRITER(so) { \ 550f1702c5SYu Xiangning if ((so)->so_snd_wakeup) { \ 560f1702c5SYu Xiangning (so)->so_snd_wakeup = B_FALSE; \ 570f1702c5SYu Xiangning cv_broadcast(&(so)->so_snd_cv); \ 580f1702c5SYu Xiangning } \ 590f1702c5SYu Xiangning } 600f1702c5SYu Xiangning 610f1702c5SYu Xiangning static int i_so_notify_last_rx(struct sonode *, int *, int *); 620f1702c5SYu Xiangning static int i_so_notify_last_tx(struct sonode *, int *, int *); 630f1702c5SYu Xiangning 640f1702c5SYu Xiangning /* 650f1702c5SYu Xiangning * The notification functions must be called with so_lock held, 660f1702c5SYu Xiangning * and they will all *drop* so_lock before returning. 670f1702c5SYu Xiangning */ 680f1702c5SYu Xiangning 690f1702c5SYu Xiangning /* 700f1702c5SYu Xiangning * Wake up anyone waiting for the connection to be established. 710f1702c5SYu Xiangning */ 720f1702c5SYu Xiangning void 730f1702c5SYu Xiangning so_notify_connected(struct sonode *so) 740f1702c5SYu Xiangning { 750f1702c5SYu Xiangning ASSERT(MUTEX_HELD(&so->so_lock)); 760f1702c5SYu Xiangning 770f1702c5SYu Xiangning if (IS_KERNEL_SOCKET(so)) { 780f1702c5SYu Xiangning KSOCKET_CALLBACK(so, connected, 0); 790f1702c5SYu Xiangning mutex_exit(&so->so_lock); 800f1702c5SYu Xiangning } else { 810f1702c5SYu Xiangning socket_sendsig(so, SOCKETSIG_WRITE); 820f1702c5SYu Xiangning mutex_exit(&so->so_lock); 830f1702c5SYu Xiangning pollwakeup(&so->so_poll_list, POLLOUT); 840f1702c5SYu Xiangning } 853e95bd4aSAnders Persson sof_sonode_notify_filters(so, SOF_EV_CONNECTED, 0); 860f1702c5SYu Xiangning 870f1702c5SYu Xiangning ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 880f1702c5SYu Xiangning } 890f1702c5SYu Xiangning 900f1702c5SYu Xiangning /* 910f1702c5SYu Xiangning * The socket is disconnecting, so no more data can be sent. Wake up 920f1702c5SYu Xiangning * anyone that is waiting to send data. 930f1702c5SYu Xiangning */ 940f1702c5SYu Xiangning void 950f1702c5SYu Xiangning so_notify_disconnecting(struct sonode *so) 960f1702c5SYu Xiangning { 970f1702c5SYu Xiangning int pollev = 0; 980f1702c5SYu Xiangning int sigev = 0; 990f1702c5SYu Xiangning 1000f1702c5SYu Xiangning ASSERT(MUTEX_HELD(&so->so_lock)); 1013e95bd4aSAnders Persson (void) i_so_notify_last_tx(so, &pollev, &sigev); 1020f1702c5SYu Xiangning 1030f1702c5SYu Xiangning if (IS_KERNEL_SOCKET(so)) { 1040f1702c5SYu Xiangning KSOCKET_CALLBACK(so, cantsendmore, 0); 1050f1702c5SYu Xiangning mutex_exit(&so->so_lock); 1063e95bd4aSAnders Persson } else { 1073e95bd4aSAnders Persson if (sigev != 0) 1080f1702c5SYu Xiangning socket_sendsig(so, sigev); 1090f1702c5SYu Xiangning mutex_exit(&so->so_lock); 11068846fd0SBryan Cantrill 1113e95bd4aSAnders Persson if (pollev != 0) 1120f1702c5SYu Xiangning pollwakeup(&so->so_poll_list, pollev); 1130f1702c5SYu Xiangning } 1143e95bd4aSAnders Persson sof_sonode_notify_filters(so, SOF_EV_CANTSENDMORE, 0); 1150f1702c5SYu Xiangning 1160f1702c5SYu Xiangning ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 1170f1702c5SYu Xiangning } 1180f1702c5SYu Xiangning 1190f1702c5SYu Xiangning /* 1200f1702c5SYu Xiangning * The socket is disconnected, so not more data can be sent or received. 1210f1702c5SYu Xiangning * Wake up anyone that is waiting to send or receive data. 1220f1702c5SYu Xiangning */ 1230f1702c5SYu Xiangning void 1243e95bd4aSAnders Persson so_notify_disconnected(struct sonode *so, boolean_t connfailed, int error) 1250f1702c5SYu Xiangning { 1260f1702c5SYu Xiangning int pollev = 0; 1270f1702c5SYu Xiangning int sigev = 0; 1280f1702c5SYu Xiangning 1290f1702c5SYu Xiangning ASSERT(MUTEX_HELD(&so->so_lock)); 1300f1702c5SYu Xiangning 1310f1702c5SYu Xiangning (void) i_so_notify_last_tx(so, &pollev, &sigev); 1320f1702c5SYu Xiangning (void) i_so_notify_last_rx(so, &pollev, &sigev); 1330f1702c5SYu Xiangning 1340f1702c5SYu Xiangning if (IS_KERNEL_SOCKET(so)) { 1353e95bd4aSAnders Persson if (connfailed) { 1360f1702c5SYu Xiangning KSOCKET_CALLBACK(so, disconnected, error); 1373e95bd4aSAnders Persson } else { 1383e95bd4aSAnders Persson KSOCKET_CALLBACK(so, connectfailed, error); 1393e95bd4aSAnders Persson } 1400f1702c5SYu Xiangning mutex_exit(&so->so_lock); 1410f1702c5SYu Xiangning } else { 1420f1702c5SYu Xiangning if (sigev != 0) 1430f1702c5SYu Xiangning socket_sendsig(so, sigev); 1440f1702c5SYu Xiangning mutex_exit(&so->so_lock); 14568846fd0SBryan Cantrill 14668846fd0SBryan Cantrill /* 14768846fd0SBryan Cantrill * If we're here because the socket has become disconnected, 14868846fd0SBryan Cantrill * we explicitly set POLLHUP. At the same time, we also clear 14968846fd0SBryan Cantrill * POLLOUT, as POLLOUT and POLLHUP are defined to be mutually 15068846fd0SBryan Cantrill * exclusive with respect to one another. 15168846fd0SBryan Cantrill */ 15268846fd0SBryan Cantrill if (!connfailed) 15368846fd0SBryan Cantrill pollev = (pollev | POLLHUP) & ~POLLOUT; 15468846fd0SBryan Cantrill 1550f1702c5SYu Xiangning if (pollev != 0) 1560f1702c5SYu Xiangning pollwakeup(&so->so_poll_list, pollev); 1570f1702c5SYu Xiangning } 1583e95bd4aSAnders Persson sof_sonode_notify_filters(so, (connfailed) ? SOF_EV_CONNECTFAILED : 1593e95bd4aSAnders Persson SOF_EV_DISCONNECTED, error); 1600f1702c5SYu Xiangning 1610f1702c5SYu Xiangning ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 1620f1702c5SYu Xiangning } 1630f1702c5SYu Xiangning 1640f1702c5SYu Xiangning /* 1650f1702c5SYu Xiangning * The socket is writeable. Wake up anyone waiting to send data. 1660f1702c5SYu Xiangning */ 1670f1702c5SYu Xiangning void 1680f1702c5SYu Xiangning so_notify_writable(struct sonode *so) 1690f1702c5SYu Xiangning { 1700f1702c5SYu Xiangning ASSERT(MUTEX_HELD(&so->so_lock)); 1710f1702c5SYu Xiangning 1720f1702c5SYu Xiangning SO_WAKEUP_WRITER(so); 1730f1702c5SYu Xiangning 1740f1702c5SYu Xiangning if (IS_KERNEL_SOCKET(so)) { 1750f1702c5SYu Xiangning KSOCKET_CALLBACK(so, cansend, 0); 1760f1702c5SYu Xiangning mutex_exit(&so->so_lock); 1770f1702c5SYu Xiangning } else { 1780f1702c5SYu Xiangning socket_sendsig(so, SOCKETSIG_WRITE); 1790f1702c5SYu Xiangning mutex_exit(&so->so_lock); 1800f1702c5SYu Xiangning pollwakeup(&so->so_poll_list, POLLOUT); 1810f1702c5SYu Xiangning } 1820f1702c5SYu Xiangning 1830f1702c5SYu Xiangning ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 1843e95bd4aSAnders Persson 1853e95bd4aSAnders Persson /* filters can start injecting data */ 1863e95bd4aSAnders Persson if (so->so_filter_active > 0) 1873e95bd4aSAnders Persson sof_sonode_notify_filters(so, SOF_EV_INJECT_DATA_OUT_OK, 0); 1880f1702c5SYu Xiangning } 1890f1702c5SYu Xiangning 1900f1702c5SYu Xiangning /* 1910f1702c5SYu Xiangning * Data is available, so wake up anyone waiting for data. 1920f1702c5SYu Xiangning */ 1930f1702c5SYu Xiangning void 1940f1702c5SYu Xiangning so_notify_data(struct sonode *so, size_t qlen) 1950f1702c5SYu Xiangning { 1960f1702c5SYu Xiangning ASSERT(MUTEX_HELD(&so->so_lock)); 1970f1702c5SYu Xiangning 1980f1702c5SYu Xiangning SO_WAKEUP_READER(so); 1990f1702c5SYu Xiangning 2000f1702c5SYu Xiangning if (IS_KERNEL_SOCKET(so)) { 2010f1702c5SYu Xiangning KSOCKET_CALLBACK(so, newdata, qlen); 2020f1702c5SYu Xiangning mutex_exit(&so->so_lock); 2030f1702c5SYu Xiangning } else { 2040f1702c5SYu Xiangning socket_sendsig(so, SOCKETSIG_READ); 2050f1702c5SYu Xiangning if (so->so_pollev & (SO_POLLEV_IN|SO_POLLEV_ALWAYS)) { 2060f1702c5SYu Xiangning so->so_pollev &= ~SO_POLLEV_IN; 2070f1702c5SYu Xiangning mutex_exit(&so->so_lock); 2080f1702c5SYu Xiangning pollwakeup(&so->so_poll_list, POLLIN|POLLRDNORM); 2090f1702c5SYu Xiangning } else { 2100f1702c5SYu Xiangning mutex_exit(&so->so_lock); 2110f1702c5SYu Xiangning } 2120f1702c5SYu Xiangning } 2130f1702c5SYu Xiangning 2140f1702c5SYu Xiangning ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 2150f1702c5SYu Xiangning } 2160f1702c5SYu Xiangning 2170f1702c5SYu Xiangning /* 2180f1702c5SYu Xiangning * Transient error. Wake up anyone waiting to send or receive data. 2190f1702c5SYu Xiangning */ 2200f1702c5SYu Xiangning void 2210f1702c5SYu Xiangning so_notify_error(struct sonode *so) 2220f1702c5SYu Xiangning { 2230f1702c5SYu Xiangning ASSERT(MUTEX_HELD(&so->so_lock)); 2240f1702c5SYu Xiangning 2250f1702c5SYu Xiangning SO_WAKEUP_WRITER(so); 2260f1702c5SYu Xiangning SO_WAKEUP_READER(so); 2270f1702c5SYu Xiangning 2280f1702c5SYu Xiangning if (IS_KERNEL_SOCKET(so)) { 2290f1702c5SYu Xiangning KSOCKET_CALLBACK(so, error, 0); 2300f1702c5SYu Xiangning mutex_exit(&so->so_lock); 2310f1702c5SYu Xiangning } else { 2320f1702c5SYu Xiangning socket_sendsig(so, SOCKETSIG_WRITE|SOCKETSIG_READ); 2330f1702c5SYu Xiangning so->so_pollev &= ~SO_POLLEV_IN; 2340f1702c5SYu Xiangning mutex_exit(&so->so_lock); 2350f1702c5SYu Xiangning pollwakeup(&so->so_poll_list, POLLOUT|POLLIN|POLLRDNORM); 2360f1702c5SYu Xiangning } 2370f1702c5SYu Xiangning 2380f1702c5SYu Xiangning ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 2390f1702c5SYu Xiangning } 2400f1702c5SYu Xiangning 2410f1702c5SYu Xiangning /* 2420f1702c5SYu Xiangning * Out-of-band data is incoming, notify any interested parties. 2430f1702c5SYu Xiangning */ 2440f1702c5SYu Xiangning void 2450f1702c5SYu Xiangning so_notify_oobsig(struct sonode *so) 2460f1702c5SYu Xiangning { 2470f1702c5SYu Xiangning socket_sendsig(so, SOCKETSIG_URG); 2480f1702c5SYu Xiangning mutex_exit(&so->so_lock); 2490f1702c5SYu Xiangning pollwakeup(&so->so_poll_list, POLLRDBAND); 2500f1702c5SYu Xiangning } 2510f1702c5SYu Xiangning 2520f1702c5SYu Xiangning /* 2530f1702c5SYu Xiangning * Received out-of-band data. If the OOB data is delivered inline, then 2540f1702c5SYu Xiangning * in addition of regular OOB notification, anyone waiting for normal 2550f1702c5SYu Xiangning * data is also notified. 2560f1702c5SYu Xiangning */ 2570f1702c5SYu Xiangning void 2580f1702c5SYu Xiangning so_notify_oobdata(struct sonode *so, boolean_t oob_inline) 2590f1702c5SYu Xiangning { 2600f1702c5SYu Xiangning ASSERT(MUTEX_HELD(&so->so_lock)); 261bbc000e5SAnders Persson if (so->so_direct != NULL) 2620f1702c5SYu Xiangning SOD_UIOAFINI(so->so_direct); 2630f1702c5SYu Xiangning 2640f1702c5SYu Xiangning SO_WAKEUP_READER(so); 2658591a19aSAnders Persson 2668591a19aSAnders Persson if (IS_KERNEL_SOCKET(so)) { 2670f1702c5SYu Xiangning KSOCKET_CALLBACK(so, oobdata, 0); 2680f1702c5SYu Xiangning mutex_exit(&so->so_lock); 2690f1702c5SYu Xiangning } else { 2700f1702c5SYu Xiangning if (oob_inline) { 2710f1702c5SYu Xiangning socket_sendsig(so, SOCKETSIG_READ); 2720f1702c5SYu Xiangning so->so_pollev &= ~SO_POLLEV_IN; 2730f1702c5SYu Xiangning mutex_exit(&so->so_lock); 2740f1702c5SYu Xiangning pollwakeup(&so->so_poll_list, 2750f1702c5SYu Xiangning POLLRDBAND|POLLIN|POLLRDNORM); 2760f1702c5SYu Xiangning } else { 2770f1702c5SYu Xiangning mutex_exit(&so->so_lock); 2780f1702c5SYu Xiangning pollwakeup(&so->so_poll_list, POLLRDBAND); 2790f1702c5SYu Xiangning } 2800f1702c5SYu Xiangning } 2810f1702c5SYu Xiangning 2820f1702c5SYu Xiangning ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 2830f1702c5SYu Xiangning } 2840f1702c5SYu Xiangning 2850f1702c5SYu Xiangning /* 2860f1702c5SYu Xiangning * End-of-file has been reach, so peer will send no new data. Wake up 2870f1702c5SYu Xiangning * anyone that is waiting for data. 2880f1702c5SYu Xiangning */ 2890f1702c5SYu Xiangning void 2900f1702c5SYu Xiangning so_notify_eof(struct sonode *so) 2910f1702c5SYu Xiangning { 2920f1702c5SYu Xiangning int pollev = 0; 2930f1702c5SYu Xiangning int sigev = 0; 2940f1702c5SYu Xiangning 2950f1702c5SYu Xiangning ASSERT(MUTEX_HELD(&so->so_lock)); 2960f1702c5SYu Xiangning 2970f1702c5SYu Xiangning (void) i_so_notify_last_rx(so, &pollev, &sigev); 2980f1702c5SYu Xiangning 2990f1702c5SYu Xiangning if (IS_KERNEL_SOCKET(so)) { 3000f1702c5SYu Xiangning KSOCKET_CALLBACK(so, cantrecvmore, 0); 3010f1702c5SYu Xiangning mutex_exit(&so->so_lock); 3020f1702c5SYu Xiangning } else { 3030f1702c5SYu Xiangning if (sigev != 0) 3040f1702c5SYu Xiangning socket_sendsig(so, sigev); 3050f1702c5SYu Xiangning mutex_exit(&so->so_lock); 3060f1702c5SYu Xiangning if (pollev != 0) 3070f1702c5SYu Xiangning pollwakeup(&so->so_poll_list, pollev); 3080f1702c5SYu Xiangning 3090f1702c5SYu Xiangning } 3103e95bd4aSAnders Persson sof_sonode_notify_filters(so, SOF_EV_CANTRECVMORE, 0); 3110f1702c5SYu Xiangning 3120f1702c5SYu Xiangning ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 3130f1702c5SYu Xiangning } 3140f1702c5SYu Xiangning 3150f1702c5SYu Xiangning /* 3160f1702c5SYu Xiangning * Wake up anyone waiting for a new connection. 3170f1702c5SYu Xiangning */ 3180f1702c5SYu Xiangning void 3190f1702c5SYu Xiangning so_notify_newconn(struct sonode *so) 3200f1702c5SYu Xiangning { 3210f1702c5SYu Xiangning ASSERT(MUTEX_HELD(&so->so_lock)); 3220f1702c5SYu Xiangning 3230f1702c5SYu Xiangning if (IS_KERNEL_SOCKET(so)) { 3243e95bd4aSAnders Persson KSOCKET_CALLBACK(so, newconn, 0); 3250f1702c5SYu Xiangning mutex_exit(&so->so_lock); 3260f1702c5SYu Xiangning } else { 3270f1702c5SYu Xiangning socket_sendsig(so, SOCKETSIG_READ); 3280f1702c5SYu Xiangning if (so->so_pollev & (SO_POLLEV_IN|SO_POLLEV_ALWAYS)) { 3290f1702c5SYu Xiangning so->so_pollev &= ~SO_POLLEV_IN; 3300f1702c5SYu Xiangning mutex_exit(&so->so_lock); 3310f1702c5SYu Xiangning pollwakeup(&so->so_poll_list, POLLIN|POLLRDNORM); 3320f1702c5SYu Xiangning } else { 3330f1702c5SYu Xiangning mutex_exit(&so->so_lock); 3340f1702c5SYu Xiangning } 3350f1702c5SYu Xiangning } 3360f1702c5SYu Xiangning 3370f1702c5SYu Xiangning ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 3380f1702c5SYu Xiangning } 3390f1702c5SYu Xiangning 3400f1702c5SYu Xiangning /* 3410f1702c5SYu Xiangning * User initated shutdown/close, wake anyone that is trying to do 3420f1702c5SYu Xiangning * an operation that is no longer possible. 3430f1702c5SYu Xiangning */ 3440f1702c5SYu Xiangning void 3450f1702c5SYu Xiangning so_notify_shutdown(struct sonode *so) 3460f1702c5SYu Xiangning { 3470f1702c5SYu Xiangning int pollev = 0; 3480f1702c5SYu Xiangning int sigev = 0; 3490f1702c5SYu Xiangning 3500f1702c5SYu Xiangning ASSERT(MUTEX_HELD(&so->so_lock)); 3510f1702c5SYu Xiangning ASSERT(so->so_state & (SS_CANTSENDMORE|SS_CANTRCVMORE)); 3520f1702c5SYu Xiangning 3530f1702c5SYu Xiangning if (so->so_state & SS_CANTSENDMORE) 3540f1702c5SYu Xiangning (void) i_so_notify_last_tx(so, &pollev, &sigev); 3550f1702c5SYu Xiangning if (so->so_state & SS_CANTRCVMORE) 3560f1702c5SYu Xiangning (void) i_so_notify_last_rx(so, &pollev, &sigev); 3570f1702c5SYu Xiangning 3580f1702c5SYu Xiangning if (sigev != 0) 3590f1702c5SYu Xiangning socket_sendsig(so, sigev); 3600f1702c5SYu Xiangning mutex_exit(&so->so_lock); 3610f1702c5SYu Xiangning if (pollev != 0) 3620f1702c5SYu Xiangning pollwakeup(&so->so_poll_list, pollev); 3630f1702c5SYu Xiangning 3640f1702c5SYu Xiangning ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 3650f1702c5SYu Xiangning } 3660f1702c5SYu Xiangning 3670f1702c5SYu Xiangning /* 3680f1702c5SYu Xiangning * No more data will be coming in, and this will be the last notification 3690f1702c5SYu Xiangning * made. 3700f1702c5SYu Xiangning */ 3710f1702c5SYu Xiangning static int 3720f1702c5SYu Xiangning i_so_notify_last_rx(struct sonode *so, int *pollev, int *sigev) 3730f1702c5SYu Xiangning { 3740f1702c5SYu Xiangning if (!(so->so_state & SS_SENTLASTREADSIG)) { 3750f1702c5SYu Xiangning SOCKET_TIMER_CANCEL(so); 3760f1702c5SYu Xiangning SO_WAKEUP_READER(so); 3770f1702c5SYu Xiangning so->so_state |= SS_SENTLASTREADSIG; 3780f1702c5SYu Xiangning so->so_pollev &= ~SO_POLLEV_IN; 3790f1702c5SYu Xiangning 380*a5eb7107SBryan Cantrill *pollev |= POLLIN|POLLRDNORM|POLLRDHUP; 3810f1702c5SYu Xiangning *sigev |= SOCKETSIG_READ; 3820f1702c5SYu Xiangning 3830f1702c5SYu Xiangning return (1); 3840f1702c5SYu Xiangning } else { 3850f1702c5SYu Xiangning return (0); 3860f1702c5SYu Xiangning } 3870f1702c5SYu Xiangning } 3880f1702c5SYu Xiangning 3890f1702c5SYu Xiangning /* 3900f1702c5SYu Xiangning * The socket is un-writeable. Make one last notification. 3910f1702c5SYu Xiangning */ 3920f1702c5SYu Xiangning static int 3930f1702c5SYu Xiangning i_so_notify_last_tx(struct sonode *so, int *pollev, int *sigev) 3940f1702c5SYu Xiangning { 3950f1702c5SYu Xiangning if (!(so->so_state & SS_SENTLASTWRITESIG)) { 3960f1702c5SYu Xiangning SO_WAKEUP_WRITER(so); 3970f1702c5SYu Xiangning so->so_state |= SS_SENTLASTWRITESIG; 3980f1702c5SYu Xiangning 3990f1702c5SYu Xiangning *pollev |= POLLOUT; 4000f1702c5SYu Xiangning *sigev |= SOCKETSIG_WRITE; 4010f1702c5SYu Xiangning 4020f1702c5SYu Xiangning return (1); 4030f1702c5SYu Xiangning } else { 4040f1702c5SYu Xiangning return (0); 4050f1702c5SYu Xiangning } 4060f1702c5SYu Xiangning } 407