1*8348SEric.Yu@Sun.COM /* 2*8348SEric.Yu@Sun.COM * CDDL HEADER START 3*8348SEric.Yu@Sun.COM * 4*8348SEric.Yu@Sun.COM * The contents of this file are subject to the terms of the 5*8348SEric.Yu@Sun.COM * Common Development and Distribution License (the "License"). 6*8348SEric.Yu@Sun.COM * You may not use this file except in compliance with the License. 7*8348SEric.Yu@Sun.COM * 8*8348SEric.Yu@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*8348SEric.Yu@Sun.COM * or http://www.opensolaris.org/os/licensing. 10*8348SEric.Yu@Sun.COM * See the License for the specific language governing permissions 11*8348SEric.Yu@Sun.COM * and limitations under the License. 12*8348SEric.Yu@Sun.COM * 13*8348SEric.Yu@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 14*8348SEric.Yu@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*8348SEric.Yu@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 16*8348SEric.Yu@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 17*8348SEric.Yu@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 18*8348SEric.Yu@Sun.COM * 19*8348SEric.Yu@Sun.COM * CDDL HEADER END 20*8348SEric.Yu@Sun.COM */ 21*8348SEric.Yu@Sun.COM 22*8348SEric.Yu@Sun.COM /* 23*8348SEric.Yu@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24*8348SEric.Yu@Sun.COM * Use is subject to license terms. 25*8348SEric.Yu@Sun.COM */ 26*8348SEric.Yu@Sun.COM 27*8348SEric.Yu@Sun.COM #include <sys/types.h> 28*8348SEric.Yu@Sun.COM #include <sys/param.h> 29*8348SEric.Yu@Sun.COM #include <sys/systm.h> 30*8348SEric.Yu@Sun.COM #include <sys/stropts.h> 31*8348SEric.Yu@Sun.COM #include <sys/socketvar.h> 32*8348SEric.Yu@Sun.COM #include <sys/ksocket.h> 33*8348SEric.Yu@Sun.COM #include <io/ksocket/ksocket_impl.h> 34*8348SEric.Yu@Sun.COM #include <fs/sockfs/sockcommon.h> 35*8348SEric.Yu@Sun.COM 36*8348SEric.Yu@Sun.COM /* 37*8348SEric.Yu@Sun.COM * There can only be a single thread waiting for data (enforced by 38*8348SEric.Yu@Sun.COM * so_lock_read()), whereas for write there might be multiple threads 39*8348SEric.Yu@Sun.COM * waiting for transmit buffers. So therefore we use cv_broadcast for 40*8348SEric.Yu@Sun.COM * write and cv_signal for read. 41*8348SEric.Yu@Sun.COM */ 42*8348SEric.Yu@Sun.COM #define SO_WAKEUP_READER(so) { \ 43*8348SEric.Yu@Sun.COM if ((so)->so_rcv_wakeup) { \ 44*8348SEric.Yu@Sun.COM (so)->so_rcv_wakeup = B_FALSE; \ 45*8348SEric.Yu@Sun.COM cv_signal(&(so)->so_rcv_cv); \ 46*8348SEric.Yu@Sun.COM } \ 47*8348SEric.Yu@Sun.COM } 48*8348SEric.Yu@Sun.COM 49*8348SEric.Yu@Sun.COM #define SO_WAKEUP_WRITER(so) { \ 50*8348SEric.Yu@Sun.COM if ((so)->so_snd_wakeup) { \ 51*8348SEric.Yu@Sun.COM (so)->so_snd_wakeup = B_FALSE; \ 52*8348SEric.Yu@Sun.COM cv_broadcast(&(so)->so_snd_cv); \ 53*8348SEric.Yu@Sun.COM } \ 54*8348SEric.Yu@Sun.COM } 55*8348SEric.Yu@Sun.COM 56*8348SEric.Yu@Sun.COM static int i_so_notify_last_rx(struct sonode *, int *, int *); 57*8348SEric.Yu@Sun.COM static int i_so_notify_last_tx(struct sonode *, int *, int *); 58*8348SEric.Yu@Sun.COM 59*8348SEric.Yu@Sun.COM /* 60*8348SEric.Yu@Sun.COM * The notification functions must be called with so_lock held, 61*8348SEric.Yu@Sun.COM * and they will all *drop* so_lock before returning. 62*8348SEric.Yu@Sun.COM */ 63*8348SEric.Yu@Sun.COM 64*8348SEric.Yu@Sun.COM /* 65*8348SEric.Yu@Sun.COM * Wake up anyone waiting for the connection to be established. 66*8348SEric.Yu@Sun.COM */ 67*8348SEric.Yu@Sun.COM void 68*8348SEric.Yu@Sun.COM so_notify_connected(struct sonode *so) 69*8348SEric.Yu@Sun.COM { 70*8348SEric.Yu@Sun.COM ASSERT(MUTEX_HELD(&so->so_lock)); 71*8348SEric.Yu@Sun.COM 72*8348SEric.Yu@Sun.COM if (IS_KERNEL_SOCKET(so)) { 73*8348SEric.Yu@Sun.COM KSOCKET_CALLBACK(so, connected, 0); 74*8348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 75*8348SEric.Yu@Sun.COM } else { 76*8348SEric.Yu@Sun.COM socket_sendsig(so, SOCKETSIG_WRITE); 77*8348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 78*8348SEric.Yu@Sun.COM pollwakeup(&so->so_poll_list, POLLOUT); 79*8348SEric.Yu@Sun.COM } 80*8348SEric.Yu@Sun.COM 81*8348SEric.Yu@Sun.COM ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 82*8348SEric.Yu@Sun.COM } 83*8348SEric.Yu@Sun.COM 84*8348SEric.Yu@Sun.COM /* 85*8348SEric.Yu@Sun.COM * The socket is disconnecting, so no more data can be sent. Wake up 86*8348SEric.Yu@Sun.COM * anyone that is waiting to send data. 87*8348SEric.Yu@Sun.COM */ 88*8348SEric.Yu@Sun.COM void 89*8348SEric.Yu@Sun.COM so_notify_disconnecting(struct sonode *so) 90*8348SEric.Yu@Sun.COM { 91*8348SEric.Yu@Sun.COM int pollev = 0; 92*8348SEric.Yu@Sun.COM int sigev = 0; 93*8348SEric.Yu@Sun.COM 94*8348SEric.Yu@Sun.COM ASSERT(MUTEX_HELD(&so->so_lock)); 95*8348SEric.Yu@Sun.COM 96*8348SEric.Yu@Sun.COM if (IS_KERNEL_SOCKET(so)) { 97*8348SEric.Yu@Sun.COM SO_WAKEUP_WRITER(so); 98*8348SEric.Yu@Sun.COM KSOCKET_CALLBACK(so, cantsendmore, 0); 99*8348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 100*8348SEric.Yu@Sun.COM } else if (i_so_notify_last_tx(so, &pollev, &sigev)) { 101*8348SEric.Yu@Sun.COM socket_sendsig(so, sigev); 102*8348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 103*8348SEric.Yu@Sun.COM pollwakeup(&so->so_poll_list, pollev); 104*8348SEric.Yu@Sun.COM } else { 105*8348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 106*8348SEric.Yu@Sun.COM } 107*8348SEric.Yu@Sun.COM 108*8348SEric.Yu@Sun.COM ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 109*8348SEric.Yu@Sun.COM } 110*8348SEric.Yu@Sun.COM 111*8348SEric.Yu@Sun.COM /* 112*8348SEric.Yu@Sun.COM * The socket is disconnected, so not more data can be sent or received. 113*8348SEric.Yu@Sun.COM * Wake up anyone that is waiting to send or receive data. 114*8348SEric.Yu@Sun.COM */ 115*8348SEric.Yu@Sun.COM void 116*8348SEric.Yu@Sun.COM so_notify_disconnected(struct sonode *so, int error) 117*8348SEric.Yu@Sun.COM { 118*8348SEric.Yu@Sun.COM int pollev = 0; 119*8348SEric.Yu@Sun.COM int sigev = 0; 120*8348SEric.Yu@Sun.COM 121*8348SEric.Yu@Sun.COM ASSERT(MUTEX_HELD(&so->so_lock)); 122*8348SEric.Yu@Sun.COM 123*8348SEric.Yu@Sun.COM (void) i_so_notify_last_tx(so, &pollev, &sigev); 124*8348SEric.Yu@Sun.COM (void) i_so_notify_last_rx(so, &pollev, &sigev); 125*8348SEric.Yu@Sun.COM 126*8348SEric.Yu@Sun.COM if (IS_KERNEL_SOCKET(so)) { 127*8348SEric.Yu@Sun.COM KSOCKET_CALLBACK(so, disconnected, error); 128*8348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 129*8348SEric.Yu@Sun.COM } else { 130*8348SEric.Yu@Sun.COM if (sigev != 0) 131*8348SEric.Yu@Sun.COM socket_sendsig(so, sigev); 132*8348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 133*8348SEric.Yu@Sun.COM if (pollev != 0) 134*8348SEric.Yu@Sun.COM pollwakeup(&so->so_poll_list, pollev); 135*8348SEric.Yu@Sun.COM } 136*8348SEric.Yu@Sun.COM 137*8348SEric.Yu@Sun.COM ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 138*8348SEric.Yu@Sun.COM } 139*8348SEric.Yu@Sun.COM 140*8348SEric.Yu@Sun.COM /* 141*8348SEric.Yu@Sun.COM * The socket is writeable. Wake up anyone waiting to send data. 142*8348SEric.Yu@Sun.COM */ 143*8348SEric.Yu@Sun.COM void 144*8348SEric.Yu@Sun.COM so_notify_writable(struct sonode *so) 145*8348SEric.Yu@Sun.COM { 146*8348SEric.Yu@Sun.COM ASSERT(MUTEX_HELD(&so->so_lock)); 147*8348SEric.Yu@Sun.COM 148*8348SEric.Yu@Sun.COM SO_WAKEUP_WRITER(so); 149*8348SEric.Yu@Sun.COM 150*8348SEric.Yu@Sun.COM if (IS_KERNEL_SOCKET(so)) { 151*8348SEric.Yu@Sun.COM KSOCKET_CALLBACK(so, cansend, 0); 152*8348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 153*8348SEric.Yu@Sun.COM } else { 154*8348SEric.Yu@Sun.COM socket_sendsig(so, SOCKETSIG_WRITE); 155*8348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 156*8348SEric.Yu@Sun.COM pollwakeup(&so->so_poll_list, POLLOUT); 157*8348SEric.Yu@Sun.COM } 158*8348SEric.Yu@Sun.COM 159*8348SEric.Yu@Sun.COM ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 160*8348SEric.Yu@Sun.COM } 161*8348SEric.Yu@Sun.COM 162*8348SEric.Yu@Sun.COM /* 163*8348SEric.Yu@Sun.COM * Data is available, so wake up anyone waiting for data. 164*8348SEric.Yu@Sun.COM */ 165*8348SEric.Yu@Sun.COM void 166*8348SEric.Yu@Sun.COM so_notify_data(struct sonode *so, size_t qlen) 167*8348SEric.Yu@Sun.COM { 168*8348SEric.Yu@Sun.COM ASSERT(MUTEX_HELD(&so->so_lock)); 169*8348SEric.Yu@Sun.COM 170*8348SEric.Yu@Sun.COM SO_WAKEUP_READER(so); 171*8348SEric.Yu@Sun.COM 172*8348SEric.Yu@Sun.COM if (IS_KERNEL_SOCKET(so)) { 173*8348SEric.Yu@Sun.COM KSOCKET_CALLBACK(so, newdata, qlen); 174*8348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 175*8348SEric.Yu@Sun.COM } else { 176*8348SEric.Yu@Sun.COM socket_sendsig(so, SOCKETSIG_READ); 177*8348SEric.Yu@Sun.COM if (so->so_pollev & (SO_POLLEV_IN|SO_POLLEV_ALWAYS)) { 178*8348SEric.Yu@Sun.COM so->so_pollev &= ~SO_POLLEV_IN; 179*8348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 180*8348SEric.Yu@Sun.COM pollwakeup(&so->so_poll_list, POLLIN|POLLRDNORM); 181*8348SEric.Yu@Sun.COM } else { 182*8348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 183*8348SEric.Yu@Sun.COM } 184*8348SEric.Yu@Sun.COM } 185*8348SEric.Yu@Sun.COM 186*8348SEric.Yu@Sun.COM ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 187*8348SEric.Yu@Sun.COM } 188*8348SEric.Yu@Sun.COM 189*8348SEric.Yu@Sun.COM /* 190*8348SEric.Yu@Sun.COM * Transient error. Wake up anyone waiting to send or receive data. 191*8348SEric.Yu@Sun.COM */ 192*8348SEric.Yu@Sun.COM void 193*8348SEric.Yu@Sun.COM so_notify_error(struct sonode *so) 194*8348SEric.Yu@Sun.COM { 195*8348SEric.Yu@Sun.COM ASSERT(MUTEX_HELD(&so->so_lock)); 196*8348SEric.Yu@Sun.COM 197*8348SEric.Yu@Sun.COM SO_WAKEUP_WRITER(so); 198*8348SEric.Yu@Sun.COM SO_WAKEUP_READER(so); 199*8348SEric.Yu@Sun.COM 200*8348SEric.Yu@Sun.COM if (IS_KERNEL_SOCKET(so)) { 201*8348SEric.Yu@Sun.COM KSOCKET_CALLBACK(so, error, 0); 202*8348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 203*8348SEric.Yu@Sun.COM } else { 204*8348SEric.Yu@Sun.COM socket_sendsig(so, SOCKETSIG_WRITE|SOCKETSIG_READ); 205*8348SEric.Yu@Sun.COM so->so_pollev &= ~SO_POLLEV_IN; 206*8348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 207*8348SEric.Yu@Sun.COM pollwakeup(&so->so_poll_list, POLLOUT|POLLIN|POLLRDNORM); 208*8348SEric.Yu@Sun.COM } 209*8348SEric.Yu@Sun.COM 210*8348SEric.Yu@Sun.COM ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 211*8348SEric.Yu@Sun.COM } 212*8348SEric.Yu@Sun.COM 213*8348SEric.Yu@Sun.COM /* 214*8348SEric.Yu@Sun.COM * Out-of-band data is incoming, notify any interested parties. 215*8348SEric.Yu@Sun.COM */ 216*8348SEric.Yu@Sun.COM void 217*8348SEric.Yu@Sun.COM so_notify_oobsig(struct sonode *so) 218*8348SEric.Yu@Sun.COM { 219*8348SEric.Yu@Sun.COM socket_sendsig(so, SOCKETSIG_URG); 220*8348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 221*8348SEric.Yu@Sun.COM pollwakeup(&so->so_poll_list, POLLRDBAND); 222*8348SEric.Yu@Sun.COM } 223*8348SEric.Yu@Sun.COM 224*8348SEric.Yu@Sun.COM /* 225*8348SEric.Yu@Sun.COM * Received out-of-band data. If the OOB data is delivered inline, then 226*8348SEric.Yu@Sun.COM * in addition of regular OOB notification, anyone waiting for normal 227*8348SEric.Yu@Sun.COM * data is also notified. 228*8348SEric.Yu@Sun.COM */ 229*8348SEric.Yu@Sun.COM void 230*8348SEric.Yu@Sun.COM so_notify_oobdata(struct sonode *so, boolean_t oob_inline) 231*8348SEric.Yu@Sun.COM { 232*8348SEric.Yu@Sun.COM ASSERT(MUTEX_HELD(&so->so_lock)); 233*8348SEric.Yu@Sun.COM SOD_UIOAFINI(so->so_direct); 234*8348SEric.Yu@Sun.COM 235*8348SEric.Yu@Sun.COM if (IS_KERNEL_SOCKET(so)) { 236*8348SEric.Yu@Sun.COM if (oob_inline) 237*8348SEric.Yu@Sun.COM SO_WAKEUP_READER(so); 238*8348SEric.Yu@Sun.COM KSOCKET_CALLBACK(so, oobdata, 0); 239*8348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 240*8348SEric.Yu@Sun.COM } else { 241*8348SEric.Yu@Sun.COM if (oob_inline) { 242*8348SEric.Yu@Sun.COM socket_sendsig(so, SOCKETSIG_READ); 243*8348SEric.Yu@Sun.COM so->so_pollev &= ~SO_POLLEV_IN; 244*8348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 245*8348SEric.Yu@Sun.COM pollwakeup(&so->so_poll_list, 246*8348SEric.Yu@Sun.COM POLLRDBAND|POLLIN|POLLRDNORM); 247*8348SEric.Yu@Sun.COM 248*8348SEric.Yu@Sun.COM SO_WAKEUP_READER(so); 249*8348SEric.Yu@Sun.COM } else { 250*8348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 251*8348SEric.Yu@Sun.COM pollwakeup(&so->so_poll_list, POLLRDBAND); 252*8348SEric.Yu@Sun.COM } 253*8348SEric.Yu@Sun.COM } 254*8348SEric.Yu@Sun.COM 255*8348SEric.Yu@Sun.COM ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 256*8348SEric.Yu@Sun.COM } 257*8348SEric.Yu@Sun.COM 258*8348SEric.Yu@Sun.COM /* 259*8348SEric.Yu@Sun.COM * End-of-file has been reach, so peer will send no new data. Wake up 260*8348SEric.Yu@Sun.COM * anyone that is waiting for data. 261*8348SEric.Yu@Sun.COM */ 262*8348SEric.Yu@Sun.COM void 263*8348SEric.Yu@Sun.COM so_notify_eof(struct sonode *so) 264*8348SEric.Yu@Sun.COM { 265*8348SEric.Yu@Sun.COM int pollev = 0; 266*8348SEric.Yu@Sun.COM int sigev = 0; 267*8348SEric.Yu@Sun.COM 268*8348SEric.Yu@Sun.COM ASSERT(MUTEX_HELD(&so->so_lock)); 269*8348SEric.Yu@Sun.COM 270*8348SEric.Yu@Sun.COM (void) i_so_notify_last_rx(so, &pollev, &sigev); 271*8348SEric.Yu@Sun.COM 272*8348SEric.Yu@Sun.COM if (IS_KERNEL_SOCKET(so)) { 273*8348SEric.Yu@Sun.COM SO_WAKEUP_READER(so); 274*8348SEric.Yu@Sun.COM KSOCKET_CALLBACK(so, cantrecvmore, 0); 275*8348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 276*8348SEric.Yu@Sun.COM } else { 277*8348SEric.Yu@Sun.COM if (sigev != 0) 278*8348SEric.Yu@Sun.COM socket_sendsig(so, sigev); 279*8348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 280*8348SEric.Yu@Sun.COM if (pollev != 0) 281*8348SEric.Yu@Sun.COM pollwakeup(&so->so_poll_list, pollev); 282*8348SEric.Yu@Sun.COM 283*8348SEric.Yu@Sun.COM } 284*8348SEric.Yu@Sun.COM 285*8348SEric.Yu@Sun.COM ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 286*8348SEric.Yu@Sun.COM } 287*8348SEric.Yu@Sun.COM 288*8348SEric.Yu@Sun.COM /* 289*8348SEric.Yu@Sun.COM * Wake up anyone waiting for a new connection. 290*8348SEric.Yu@Sun.COM */ 291*8348SEric.Yu@Sun.COM void 292*8348SEric.Yu@Sun.COM so_notify_newconn(struct sonode *so) 293*8348SEric.Yu@Sun.COM { 294*8348SEric.Yu@Sun.COM ASSERT(MUTEX_HELD(&so->so_lock)); 295*8348SEric.Yu@Sun.COM 296*8348SEric.Yu@Sun.COM if (IS_KERNEL_SOCKET(so)) { 297*8348SEric.Yu@Sun.COM KSOCKET_CALLBACK(so, newconn, so->so_rcv_queued); 298*8348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 299*8348SEric.Yu@Sun.COM } else { 300*8348SEric.Yu@Sun.COM socket_sendsig(so, SOCKETSIG_READ); 301*8348SEric.Yu@Sun.COM if (so->so_pollev & (SO_POLLEV_IN|SO_POLLEV_ALWAYS)) { 302*8348SEric.Yu@Sun.COM so->so_pollev &= ~SO_POLLEV_IN; 303*8348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 304*8348SEric.Yu@Sun.COM pollwakeup(&so->so_poll_list, POLLIN|POLLRDNORM); 305*8348SEric.Yu@Sun.COM } else { 306*8348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 307*8348SEric.Yu@Sun.COM } 308*8348SEric.Yu@Sun.COM } 309*8348SEric.Yu@Sun.COM 310*8348SEric.Yu@Sun.COM ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 311*8348SEric.Yu@Sun.COM } 312*8348SEric.Yu@Sun.COM 313*8348SEric.Yu@Sun.COM /* 314*8348SEric.Yu@Sun.COM * User initated shutdown/close, wake anyone that is trying to do 315*8348SEric.Yu@Sun.COM * an operation that is no longer possible. 316*8348SEric.Yu@Sun.COM */ 317*8348SEric.Yu@Sun.COM void 318*8348SEric.Yu@Sun.COM so_notify_shutdown(struct sonode *so) 319*8348SEric.Yu@Sun.COM { 320*8348SEric.Yu@Sun.COM int pollev = 0; 321*8348SEric.Yu@Sun.COM int sigev = 0; 322*8348SEric.Yu@Sun.COM 323*8348SEric.Yu@Sun.COM ASSERT(MUTEX_HELD(&so->so_lock)); 324*8348SEric.Yu@Sun.COM ASSERT(so->so_state & (SS_CANTSENDMORE|SS_CANTRCVMORE)); 325*8348SEric.Yu@Sun.COM 326*8348SEric.Yu@Sun.COM if (so->so_state & SS_CANTSENDMORE) 327*8348SEric.Yu@Sun.COM (void) i_so_notify_last_tx(so, &pollev, &sigev); 328*8348SEric.Yu@Sun.COM if (so->so_state & SS_CANTRCVMORE) 329*8348SEric.Yu@Sun.COM (void) i_so_notify_last_rx(so, &pollev, &sigev); 330*8348SEric.Yu@Sun.COM 331*8348SEric.Yu@Sun.COM if (sigev != 0) 332*8348SEric.Yu@Sun.COM socket_sendsig(so, sigev); 333*8348SEric.Yu@Sun.COM mutex_exit(&so->so_lock); 334*8348SEric.Yu@Sun.COM if (pollev != 0) 335*8348SEric.Yu@Sun.COM pollwakeup(&so->so_poll_list, pollev); 336*8348SEric.Yu@Sun.COM 337*8348SEric.Yu@Sun.COM ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 338*8348SEric.Yu@Sun.COM } 339*8348SEric.Yu@Sun.COM 340*8348SEric.Yu@Sun.COM /* 341*8348SEric.Yu@Sun.COM * No more data will be coming in, and this will be the last notification 342*8348SEric.Yu@Sun.COM * made. 343*8348SEric.Yu@Sun.COM */ 344*8348SEric.Yu@Sun.COM static int 345*8348SEric.Yu@Sun.COM i_so_notify_last_rx(struct sonode *so, int *pollev, int *sigev) 346*8348SEric.Yu@Sun.COM { 347*8348SEric.Yu@Sun.COM if (!(so->so_state & SS_SENTLASTREADSIG)) { 348*8348SEric.Yu@Sun.COM SOCKET_TIMER_CANCEL(so); 349*8348SEric.Yu@Sun.COM SO_WAKEUP_READER(so); 350*8348SEric.Yu@Sun.COM so->so_state |= SS_SENTLASTREADSIG; 351*8348SEric.Yu@Sun.COM so->so_pollev &= ~SO_POLLEV_IN; 352*8348SEric.Yu@Sun.COM 353*8348SEric.Yu@Sun.COM *pollev |= POLLIN|POLLRDNORM; 354*8348SEric.Yu@Sun.COM *sigev |= SOCKETSIG_READ; 355*8348SEric.Yu@Sun.COM 356*8348SEric.Yu@Sun.COM return (1); 357*8348SEric.Yu@Sun.COM } else { 358*8348SEric.Yu@Sun.COM return (0); 359*8348SEric.Yu@Sun.COM } 360*8348SEric.Yu@Sun.COM } 361*8348SEric.Yu@Sun.COM 362*8348SEric.Yu@Sun.COM /* 363*8348SEric.Yu@Sun.COM * The socket is un-writeable. Make one last notification. 364*8348SEric.Yu@Sun.COM */ 365*8348SEric.Yu@Sun.COM static int 366*8348SEric.Yu@Sun.COM i_so_notify_last_tx(struct sonode *so, int *pollev, int *sigev) 367*8348SEric.Yu@Sun.COM { 368*8348SEric.Yu@Sun.COM if (!(so->so_state & SS_SENTLASTWRITESIG)) { 369*8348SEric.Yu@Sun.COM SO_WAKEUP_WRITER(so); 370*8348SEric.Yu@Sun.COM so->so_state |= SS_SENTLASTWRITESIG; 371*8348SEric.Yu@Sun.COM 372*8348SEric.Yu@Sun.COM *pollev |= POLLOUT; 373*8348SEric.Yu@Sun.COM *sigev |= SOCKETSIG_WRITE; 374*8348SEric.Yu@Sun.COM 375*8348SEric.Yu@Sun.COM return (1); 376*8348SEric.Yu@Sun.COM } else { 377*8348SEric.Yu@Sun.COM return (0); 378*8348SEric.Yu@Sun.COM } 379*8348SEric.Yu@Sun.COM } 380