18348SEric.Yu@Sun.COM /* 28348SEric.Yu@Sun.COM * CDDL HEADER START 38348SEric.Yu@Sun.COM * 48348SEric.Yu@Sun.COM * The contents of this file are subject to the terms of the 58348SEric.Yu@Sun.COM * Common Development and Distribution License (the "License"). 68348SEric.Yu@Sun.COM * You may not use this file except in compliance with the License. 78348SEric.Yu@Sun.COM * 88348SEric.Yu@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 98348SEric.Yu@Sun.COM * or http://www.opensolaris.org/os/licensing. 108348SEric.Yu@Sun.COM * See the License for the specific language governing permissions 118348SEric.Yu@Sun.COM * and limitations under the License. 128348SEric.Yu@Sun.COM * 138348SEric.Yu@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 148348SEric.Yu@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 158348SEric.Yu@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 168348SEric.Yu@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 178348SEric.Yu@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 188348SEric.Yu@Sun.COM * 198348SEric.Yu@Sun.COM * CDDL HEADER END 208348SEric.Yu@Sun.COM */ 218348SEric.Yu@Sun.COM 228348SEric.Yu@Sun.COM /* 239491SAnders.Persson@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 248348SEric.Yu@Sun.COM * Use is subject to license terms. 258348SEric.Yu@Sun.COM */ 268348SEric.Yu@Sun.COM 278348SEric.Yu@Sun.COM #include <sys/types.h> 288348SEric.Yu@Sun.COM #include <sys/param.h> 298348SEric.Yu@Sun.COM #include <sys/systm.h> 308348SEric.Yu@Sun.COM #include <sys/stropts.h> 318348SEric.Yu@Sun.COM #include <sys/socketvar.h> 328348SEric.Yu@Sun.COM #include <sys/ksocket.h> 338348SEric.Yu@Sun.COM #include <io/ksocket/ksocket_impl.h> 348348SEric.Yu@Sun.COM #include <fs/sockfs/sockcommon.h> 359491SAnders.Persson@Sun.COM #include <fs/sockfs/sodirect.h> 368348SEric.Yu@Sun.COM 378348SEric.Yu@Sun.COM /* 388348SEric.Yu@Sun.COM * There can only be a single thread waiting for data (enforced by 398348SEric.Yu@Sun.COM * so_lock_read()), whereas for write there might be multiple threads 408348SEric.Yu@Sun.COM * waiting for transmit buffers. So therefore we use cv_broadcast for 418348SEric.Yu@Sun.COM * write and cv_signal for read. 428348SEric.Yu@Sun.COM */ 438348SEric.Yu@Sun.COM #define SO_WAKEUP_READER(so) { \ 448348SEric.Yu@Sun.COM if ((so)->so_rcv_wakeup) { \ 458348SEric.Yu@Sun.COM (so)->so_rcv_wakeup = B_FALSE; \ 468348SEric.Yu@Sun.COM cv_signal(&(so)->so_rcv_cv); \ 478348SEric.Yu@Sun.COM } \ 488348SEric.Yu@Sun.COM } 498348SEric.Yu@Sun.COM 508348SEric.Yu@Sun.COM #define SO_WAKEUP_WRITER(so) { \ 518348SEric.Yu@Sun.COM if ((so)->so_snd_wakeup) { \ 528348SEric.Yu@Sun.COM (so)->so_snd_wakeup = B_FALSE; \ 538348SEric.Yu@Sun.COM cv_broadcast(&(so)->so_snd_cv); \ 548348SEric.Yu@Sun.COM } \ 558348SEric.Yu@Sun.COM } 568348SEric.Yu@Sun.COM 578348SEric.Yu@Sun.COM static int i_so_notify_last_rx(struct sonode *, int *, int *); 588348SEric.Yu@Sun.COM static int i_so_notify_last_tx(struct sonode *, int *, int *); 598348SEric.Yu@Sun.COM 608348SEric.Yu@Sun.COM /* 618348SEric.Yu@Sun.COM * The notification functions must be called with so_lock held, 628348SEric.Yu@Sun.COM * and they will all *drop* so_lock before returning. 638348SEric.Yu@Sun.COM */ 648348SEric.Yu@Sun.COM 658348SEric.Yu@Sun.COM /* 668348SEric.Yu@Sun.COM * Wake up anyone waiting for the connection to be established. 678348SEric.Yu@Sun.COM */ 688348SEric.Yu@Sun.COM void 698348SEric.Yu@Sun.COM so_notify_connected(struct sonode *so) 708348SEric.Yu@Sun.COM { 718348SEric.Yu@Sun.COM ASSERT(MUTEX_HELD(&so->so_lock)); 728348SEric.Yu@Sun.COM 738348SEric.Yu@Sun.COM if (IS_KERNEL_SOCKET(so)) { 748348SEric.Yu@Sun.COM KSOCKET_CALLBACK(so, connected, 0); 758348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 768348SEric.Yu@Sun.COM } else { 778348SEric.Yu@Sun.COM socket_sendsig(so, SOCKETSIG_WRITE); 788348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 798348SEric.Yu@Sun.COM pollwakeup(&so->so_poll_list, POLLOUT); 808348SEric.Yu@Sun.COM } 818348SEric.Yu@Sun.COM 828348SEric.Yu@Sun.COM ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 838348SEric.Yu@Sun.COM } 848348SEric.Yu@Sun.COM 858348SEric.Yu@Sun.COM /* 868348SEric.Yu@Sun.COM * The socket is disconnecting, so no more data can be sent. Wake up 878348SEric.Yu@Sun.COM * anyone that is waiting to send data. 888348SEric.Yu@Sun.COM */ 898348SEric.Yu@Sun.COM void 908348SEric.Yu@Sun.COM so_notify_disconnecting(struct sonode *so) 918348SEric.Yu@Sun.COM { 928348SEric.Yu@Sun.COM int pollev = 0; 938348SEric.Yu@Sun.COM int sigev = 0; 948348SEric.Yu@Sun.COM 958348SEric.Yu@Sun.COM ASSERT(MUTEX_HELD(&so->so_lock)); 968348SEric.Yu@Sun.COM 978348SEric.Yu@Sun.COM if (IS_KERNEL_SOCKET(so)) { 988348SEric.Yu@Sun.COM SO_WAKEUP_WRITER(so); 998348SEric.Yu@Sun.COM KSOCKET_CALLBACK(so, cantsendmore, 0); 1008348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 1018348SEric.Yu@Sun.COM } else if (i_so_notify_last_tx(so, &pollev, &sigev)) { 1028348SEric.Yu@Sun.COM socket_sendsig(so, sigev); 1038348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 1048348SEric.Yu@Sun.COM pollwakeup(&so->so_poll_list, pollev); 1058348SEric.Yu@Sun.COM } else { 1068348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 1078348SEric.Yu@Sun.COM } 1088348SEric.Yu@Sun.COM 1098348SEric.Yu@Sun.COM ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 1108348SEric.Yu@Sun.COM } 1118348SEric.Yu@Sun.COM 1128348SEric.Yu@Sun.COM /* 1138348SEric.Yu@Sun.COM * The socket is disconnected, so not more data can be sent or received. 1148348SEric.Yu@Sun.COM * Wake up anyone that is waiting to send or receive data. 1158348SEric.Yu@Sun.COM */ 1168348SEric.Yu@Sun.COM void 1178348SEric.Yu@Sun.COM so_notify_disconnected(struct sonode *so, int error) 1188348SEric.Yu@Sun.COM { 1198348SEric.Yu@Sun.COM int pollev = 0; 1208348SEric.Yu@Sun.COM int sigev = 0; 1218348SEric.Yu@Sun.COM 1228348SEric.Yu@Sun.COM ASSERT(MUTEX_HELD(&so->so_lock)); 1238348SEric.Yu@Sun.COM 1248348SEric.Yu@Sun.COM (void) i_so_notify_last_tx(so, &pollev, &sigev); 1258348SEric.Yu@Sun.COM (void) i_so_notify_last_rx(so, &pollev, &sigev); 1268348SEric.Yu@Sun.COM 1278348SEric.Yu@Sun.COM if (IS_KERNEL_SOCKET(so)) { 1288348SEric.Yu@Sun.COM KSOCKET_CALLBACK(so, disconnected, error); 1298348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 1308348SEric.Yu@Sun.COM } else { 1318348SEric.Yu@Sun.COM if (sigev != 0) 1328348SEric.Yu@Sun.COM socket_sendsig(so, sigev); 1338348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 1348348SEric.Yu@Sun.COM if (pollev != 0) 1358348SEric.Yu@Sun.COM pollwakeup(&so->so_poll_list, pollev); 1368348SEric.Yu@Sun.COM } 1378348SEric.Yu@Sun.COM 1388348SEric.Yu@Sun.COM ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 1398348SEric.Yu@Sun.COM } 1408348SEric.Yu@Sun.COM 1418348SEric.Yu@Sun.COM /* 1428348SEric.Yu@Sun.COM * The socket is writeable. Wake up anyone waiting to send data. 1438348SEric.Yu@Sun.COM */ 1448348SEric.Yu@Sun.COM void 1458348SEric.Yu@Sun.COM so_notify_writable(struct sonode *so) 1468348SEric.Yu@Sun.COM { 1478348SEric.Yu@Sun.COM ASSERT(MUTEX_HELD(&so->so_lock)); 1488348SEric.Yu@Sun.COM 1498348SEric.Yu@Sun.COM SO_WAKEUP_WRITER(so); 1508348SEric.Yu@Sun.COM 1518348SEric.Yu@Sun.COM if (IS_KERNEL_SOCKET(so)) { 1528348SEric.Yu@Sun.COM KSOCKET_CALLBACK(so, cansend, 0); 1538348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 1548348SEric.Yu@Sun.COM } else { 1558348SEric.Yu@Sun.COM socket_sendsig(so, SOCKETSIG_WRITE); 1568348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 1578348SEric.Yu@Sun.COM pollwakeup(&so->so_poll_list, POLLOUT); 1588348SEric.Yu@Sun.COM } 1598348SEric.Yu@Sun.COM 1608348SEric.Yu@Sun.COM ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 1618348SEric.Yu@Sun.COM } 1628348SEric.Yu@Sun.COM 1638348SEric.Yu@Sun.COM /* 1648348SEric.Yu@Sun.COM * Data is available, so wake up anyone waiting for data. 1658348SEric.Yu@Sun.COM */ 1668348SEric.Yu@Sun.COM void 1678348SEric.Yu@Sun.COM so_notify_data(struct sonode *so, size_t qlen) 1688348SEric.Yu@Sun.COM { 1698348SEric.Yu@Sun.COM ASSERT(MUTEX_HELD(&so->so_lock)); 1708348SEric.Yu@Sun.COM 1718348SEric.Yu@Sun.COM SO_WAKEUP_READER(so); 1728348SEric.Yu@Sun.COM 1738348SEric.Yu@Sun.COM if (IS_KERNEL_SOCKET(so)) { 1748348SEric.Yu@Sun.COM KSOCKET_CALLBACK(so, newdata, qlen); 1758348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 1768348SEric.Yu@Sun.COM } else { 1778348SEric.Yu@Sun.COM socket_sendsig(so, SOCKETSIG_READ); 1788348SEric.Yu@Sun.COM if (so->so_pollev & (SO_POLLEV_IN|SO_POLLEV_ALWAYS)) { 1798348SEric.Yu@Sun.COM so->so_pollev &= ~SO_POLLEV_IN; 1808348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 1818348SEric.Yu@Sun.COM pollwakeup(&so->so_poll_list, POLLIN|POLLRDNORM); 1828348SEric.Yu@Sun.COM } else { 1838348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 1848348SEric.Yu@Sun.COM } 1858348SEric.Yu@Sun.COM } 1868348SEric.Yu@Sun.COM 1878348SEric.Yu@Sun.COM ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 1888348SEric.Yu@Sun.COM } 1898348SEric.Yu@Sun.COM 1908348SEric.Yu@Sun.COM /* 1918348SEric.Yu@Sun.COM * Transient error. Wake up anyone waiting to send or receive data. 1928348SEric.Yu@Sun.COM */ 1938348SEric.Yu@Sun.COM void 1948348SEric.Yu@Sun.COM so_notify_error(struct sonode *so) 1958348SEric.Yu@Sun.COM { 1968348SEric.Yu@Sun.COM ASSERT(MUTEX_HELD(&so->so_lock)); 1978348SEric.Yu@Sun.COM 1988348SEric.Yu@Sun.COM SO_WAKEUP_WRITER(so); 1998348SEric.Yu@Sun.COM SO_WAKEUP_READER(so); 2008348SEric.Yu@Sun.COM 2018348SEric.Yu@Sun.COM if (IS_KERNEL_SOCKET(so)) { 2028348SEric.Yu@Sun.COM KSOCKET_CALLBACK(so, error, 0); 2038348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 2048348SEric.Yu@Sun.COM } else { 2058348SEric.Yu@Sun.COM socket_sendsig(so, SOCKETSIG_WRITE|SOCKETSIG_READ); 2068348SEric.Yu@Sun.COM so->so_pollev &= ~SO_POLLEV_IN; 2078348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 2088348SEric.Yu@Sun.COM pollwakeup(&so->so_poll_list, POLLOUT|POLLIN|POLLRDNORM); 2098348SEric.Yu@Sun.COM } 2108348SEric.Yu@Sun.COM 2118348SEric.Yu@Sun.COM ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 2128348SEric.Yu@Sun.COM } 2138348SEric.Yu@Sun.COM 2148348SEric.Yu@Sun.COM /* 2158348SEric.Yu@Sun.COM * Out-of-band data is incoming, notify any interested parties. 2168348SEric.Yu@Sun.COM */ 2178348SEric.Yu@Sun.COM void 2188348SEric.Yu@Sun.COM so_notify_oobsig(struct sonode *so) 2198348SEric.Yu@Sun.COM { 2208348SEric.Yu@Sun.COM socket_sendsig(so, SOCKETSIG_URG); 2218348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 2228348SEric.Yu@Sun.COM pollwakeup(&so->so_poll_list, POLLRDBAND); 2238348SEric.Yu@Sun.COM } 2248348SEric.Yu@Sun.COM 2258348SEric.Yu@Sun.COM /* 2268348SEric.Yu@Sun.COM * Received out-of-band data. If the OOB data is delivered inline, then 2278348SEric.Yu@Sun.COM * in addition of regular OOB notification, anyone waiting for normal 2288348SEric.Yu@Sun.COM * data is also notified. 2298348SEric.Yu@Sun.COM */ 2308348SEric.Yu@Sun.COM void 2318348SEric.Yu@Sun.COM so_notify_oobdata(struct sonode *so, boolean_t oob_inline) 2328348SEric.Yu@Sun.COM { 2338348SEric.Yu@Sun.COM ASSERT(MUTEX_HELD(&so->so_lock)); 2349491SAnders.Persson@Sun.COM if (so->so_direct != NULL) 2359491SAnders.Persson@Sun.COM SOD_UIOAFINI(so->so_direct); 2368348SEric.Yu@Sun.COM 237*9752SAnders.Persson@Sun.COM SO_WAKEUP_READER(so); 238*9752SAnders.Persson@Sun.COM 2398348SEric.Yu@Sun.COM if (IS_KERNEL_SOCKET(so)) { 2408348SEric.Yu@Sun.COM KSOCKET_CALLBACK(so, oobdata, 0); 2418348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 2428348SEric.Yu@Sun.COM } else { 2438348SEric.Yu@Sun.COM if (oob_inline) { 2448348SEric.Yu@Sun.COM socket_sendsig(so, SOCKETSIG_READ); 2458348SEric.Yu@Sun.COM so->so_pollev &= ~SO_POLLEV_IN; 2468348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 2478348SEric.Yu@Sun.COM pollwakeup(&so->so_poll_list, 2488348SEric.Yu@Sun.COM POLLRDBAND|POLLIN|POLLRDNORM); 2498348SEric.Yu@Sun.COM } else { 2508348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 2518348SEric.Yu@Sun.COM pollwakeup(&so->so_poll_list, POLLRDBAND); 2528348SEric.Yu@Sun.COM } 2538348SEric.Yu@Sun.COM } 2548348SEric.Yu@Sun.COM 2558348SEric.Yu@Sun.COM ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 2568348SEric.Yu@Sun.COM } 2578348SEric.Yu@Sun.COM 2588348SEric.Yu@Sun.COM /* 2598348SEric.Yu@Sun.COM * End-of-file has been reach, so peer will send no new data. Wake up 2608348SEric.Yu@Sun.COM * anyone that is waiting for data. 2618348SEric.Yu@Sun.COM */ 2628348SEric.Yu@Sun.COM void 2638348SEric.Yu@Sun.COM so_notify_eof(struct sonode *so) 2648348SEric.Yu@Sun.COM { 2658348SEric.Yu@Sun.COM int pollev = 0; 2668348SEric.Yu@Sun.COM int sigev = 0; 2678348SEric.Yu@Sun.COM 2688348SEric.Yu@Sun.COM ASSERT(MUTEX_HELD(&so->so_lock)); 2698348SEric.Yu@Sun.COM 2708348SEric.Yu@Sun.COM (void) i_so_notify_last_rx(so, &pollev, &sigev); 2718348SEric.Yu@Sun.COM 2728348SEric.Yu@Sun.COM if (IS_KERNEL_SOCKET(so)) { 2738348SEric.Yu@Sun.COM SO_WAKEUP_READER(so); 2748348SEric.Yu@Sun.COM KSOCKET_CALLBACK(so, cantrecvmore, 0); 2758348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 2768348SEric.Yu@Sun.COM } else { 2778348SEric.Yu@Sun.COM if (sigev != 0) 2788348SEric.Yu@Sun.COM socket_sendsig(so, sigev); 2798348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 2808348SEric.Yu@Sun.COM if (pollev != 0) 2818348SEric.Yu@Sun.COM pollwakeup(&so->so_poll_list, pollev); 2828348SEric.Yu@Sun.COM 2838348SEric.Yu@Sun.COM } 2848348SEric.Yu@Sun.COM 2858348SEric.Yu@Sun.COM ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 2868348SEric.Yu@Sun.COM } 2878348SEric.Yu@Sun.COM 2888348SEric.Yu@Sun.COM /* 2898348SEric.Yu@Sun.COM * Wake up anyone waiting for a new connection. 2908348SEric.Yu@Sun.COM */ 2918348SEric.Yu@Sun.COM void 2928348SEric.Yu@Sun.COM so_notify_newconn(struct sonode *so) 2938348SEric.Yu@Sun.COM { 2948348SEric.Yu@Sun.COM ASSERT(MUTEX_HELD(&so->so_lock)); 2958348SEric.Yu@Sun.COM 2968348SEric.Yu@Sun.COM if (IS_KERNEL_SOCKET(so)) { 2978348SEric.Yu@Sun.COM KSOCKET_CALLBACK(so, newconn, so->so_rcv_queued); 2988348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 2998348SEric.Yu@Sun.COM } else { 3008348SEric.Yu@Sun.COM socket_sendsig(so, SOCKETSIG_READ); 3018348SEric.Yu@Sun.COM if (so->so_pollev & (SO_POLLEV_IN|SO_POLLEV_ALWAYS)) { 3028348SEric.Yu@Sun.COM so->so_pollev &= ~SO_POLLEV_IN; 3038348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 3048348SEric.Yu@Sun.COM pollwakeup(&so->so_poll_list, POLLIN|POLLRDNORM); 3058348SEric.Yu@Sun.COM } else { 3068348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 3078348SEric.Yu@Sun.COM } 3088348SEric.Yu@Sun.COM } 3098348SEric.Yu@Sun.COM 3108348SEric.Yu@Sun.COM ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 3118348SEric.Yu@Sun.COM } 3128348SEric.Yu@Sun.COM 3138348SEric.Yu@Sun.COM /* 3148348SEric.Yu@Sun.COM * User initated shutdown/close, wake anyone that is trying to do 3158348SEric.Yu@Sun.COM * an operation that is no longer possible. 3168348SEric.Yu@Sun.COM */ 3178348SEric.Yu@Sun.COM void 3188348SEric.Yu@Sun.COM so_notify_shutdown(struct sonode *so) 3198348SEric.Yu@Sun.COM { 3208348SEric.Yu@Sun.COM int pollev = 0; 3218348SEric.Yu@Sun.COM int sigev = 0; 3228348SEric.Yu@Sun.COM 3238348SEric.Yu@Sun.COM ASSERT(MUTEX_HELD(&so->so_lock)); 3248348SEric.Yu@Sun.COM ASSERT(so->so_state & (SS_CANTSENDMORE|SS_CANTRCVMORE)); 3258348SEric.Yu@Sun.COM 3268348SEric.Yu@Sun.COM if (so->so_state & SS_CANTSENDMORE) 3278348SEric.Yu@Sun.COM (void) i_so_notify_last_tx(so, &pollev, &sigev); 3288348SEric.Yu@Sun.COM if (so->so_state & SS_CANTRCVMORE) 3298348SEric.Yu@Sun.COM (void) i_so_notify_last_rx(so, &pollev, &sigev); 3308348SEric.Yu@Sun.COM 3318348SEric.Yu@Sun.COM if (sigev != 0) 3328348SEric.Yu@Sun.COM socket_sendsig(so, sigev); 3338348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 3348348SEric.Yu@Sun.COM if (pollev != 0) 3358348SEric.Yu@Sun.COM pollwakeup(&so->so_poll_list, pollev); 3368348SEric.Yu@Sun.COM 3378348SEric.Yu@Sun.COM ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 3388348SEric.Yu@Sun.COM } 3398348SEric.Yu@Sun.COM 3408348SEric.Yu@Sun.COM /* 3418348SEric.Yu@Sun.COM * No more data will be coming in, and this will be the last notification 3428348SEric.Yu@Sun.COM * made. 3438348SEric.Yu@Sun.COM */ 3448348SEric.Yu@Sun.COM static int 3458348SEric.Yu@Sun.COM i_so_notify_last_rx(struct sonode *so, int *pollev, int *sigev) 3468348SEric.Yu@Sun.COM { 3478348SEric.Yu@Sun.COM if (!(so->so_state & SS_SENTLASTREADSIG)) { 3488348SEric.Yu@Sun.COM SOCKET_TIMER_CANCEL(so); 3498348SEric.Yu@Sun.COM SO_WAKEUP_READER(so); 3508348SEric.Yu@Sun.COM so->so_state |= SS_SENTLASTREADSIG; 3518348SEric.Yu@Sun.COM so->so_pollev &= ~SO_POLLEV_IN; 3528348SEric.Yu@Sun.COM 3538348SEric.Yu@Sun.COM *pollev |= POLLIN|POLLRDNORM; 3548348SEric.Yu@Sun.COM *sigev |= SOCKETSIG_READ; 3558348SEric.Yu@Sun.COM 3568348SEric.Yu@Sun.COM return (1); 3578348SEric.Yu@Sun.COM } else { 3588348SEric.Yu@Sun.COM return (0); 3598348SEric.Yu@Sun.COM } 3608348SEric.Yu@Sun.COM } 3618348SEric.Yu@Sun.COM 3628348SEric.Yu@Sun.COM /* 3638348SEric.Yu@Sun.COM * The socket is un-writeable. Make one last notification. 3648348SEric.Yu@Sun.COM */ 3658348SEric.Yu@Sun.COM static int 3668348SEric.Yu@Sun.COM i_so_notify_last_tx(struct sonode *so, int *pollev, int *sigev) 3678348SEric.Yu@Sun.COM { 3688348SEric.Yu@Sun.COM if (!(so->so_state & SS_SENTLASTWRITESIG)) { 3698348SEric.Yu@Sun.COM SO_WAKEUP_WRITER(so); 3708348SEric.Yu@Sun.COM so->so_state |= SS_SENTLASTWRITESIG; 3718348SEric.Yu@Sun.COM 3728348SEric.Yu@Sun.COM *pollev |= POLLOUT; 3738348SEric.Yu@Sun.COM *sigev |= SOCKETSIG_WRITE; 3748348SEric.Yu@Sun.COM 3758348SEric.Yu@Sun.COM return (1); 3768348SEric.Yu@Sun.COM } else { 3778348SEric.Yu@Sun.COM return (0); 3788348SEric.Yu@Sun.COM } 3798348SEric.Yu@Sun.COM } 380