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