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 SO_WAKEUP_READER(so); 238 239 if (IS_KERNEL_SOCKET(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 } else { 250 mutex_exit(&so->so_lock); 251 pollwakeup(&so->so_poll_list, POLLRDBAND); 252 } 253 } 254 255 ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 256 } 257 258 /* 259 * End-of-file has been reach, so peer will send no new data. Wake up 260 * anyone that is waiting for data. 261 */ 262 void 263 so_notify_eof(struct sonode *so) 264 { 265 int pollev = 0; 266 int sigev = 0; 267 268 ASSERT(MUTEX_HELD(&so->so_lock)); 269 270 (void) i_so_notify_last_rx(so, &pollev, &sigev); 271 272 if (IS_KERNEL_SOCKET(so)) { 273 SO_WAKEUP_READER(so); 274 KSOCKET_CALLBACK(so, cantrecvmore, 0); 275 mutex_exit(&so->so_lock); 276 } else { 277 if (sigev != 0) 278 socket_sendsig(so, sigev); 279 mutex_exit(&so->so_lock); 280 if (pollev != 0) 281 pollwakeup(&so->so_poll_list, pollev); 282 283 } 284 285 ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 286 } 287 288 /* 289 * Wake up anyone waiting for a new connection. 290 */ 291 void 292 so_notify_newconn(struct sonode *so) 293 { 294 ASSERT(MUTEX_HELD(&so->so_lock)); 295 296 if (IS_KERNEL_SOCKET(so)) { 297 KSOCKET_CALLBACK(so, newconn, so->so_rcv_queued); 298 mutex_exit(&so->so_lock); 299 } else { 300 socket_sendsig(so, SOCKETSIG_READ); 301 if (so->so_pollev & (SO_POLLEV_IN|SO_POLLEV_ALWAYS)) { 302 so->so_pollev &= ~SO_POLLEV_IN; 303 mutex_exit(&so->so_lock); 304 pollwakeup(&so->so_poll_list, POLLIN|POLLRDNORM); 305 } else { 306 mutex_exit(&so->so_lock); 307 } 308 } 309 310 ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 311 } 312 313 /* 314 * User initated shutdown/close, wake anyone that is trying to do 315 * an operation that is no longer possible. 316 */ 317 void 318 so_notify_shutdown(struct sonode *so) 319 { 320 int pollev = 0; 321 int sigev = 0; 322 323 ASSERT(MUTEX_HELD(&so->so_lock)); 324 ASSERT(so->so_state & (SS_CANTSENDMORE|SS_CANTRCVMORE)); 325 326 if (so->so_state & SS_CANTSENDMORE) 327 (void) i_so_notify_last_tx(so, &pollev, &sigev); 328 if (so->so_state & SS_CANTRCVMORE) 329 (void) i_so_notify_last_rx(so, &pollev, &sigev); 330 331 if (sigev != 0) 332 socket_sendsig(so, sigev); 333 mutex_exit(&so->so_lock); 334 if (pollev != 0) 335 pollwakeup(&so->so_poll_list, pollev); 336 337 ASSERT(MUTEX_NOT_HELD(&so->so_lock)); 338 } 339 340 /* 341 * No more data will be coming in, and this will be the last notification 342 * made. 343 */ 344 static int 345 i_so_notify_last_rx(struct sonode *so, int *pollev, int *sigev) 346 { 347 if (!(so->so_state & SS_SENTLASTREADSIG)) { 348 SOCKET_TIMER_CANCEL(so); 349 SO_WAKEUP_READER(so); 350 so->so_state |= SS_SENTLASTREADSIG; 351 so->so_pollev &= ~SO_POLLEV_IN; 352 353 *pollev |= POLLIN|POLLRDNORM; 354 *sigev |= SOCKETSIG_READ; 355 356 return (1); 357 } else { 358 return (0); 359 } 360 } 361 362 /* 363 * The socket is un-writeable. Make one last notification. 364 */ 365 static int 366 i_so_notify_last_tx(struct sonode *so, int *pollev, int *sigev) 367 { 368 if (!(so->so_state & SS_SENTLASTWRITESIG)) { 369 SO_WAKEUP_WRITER(so); 370 so->so_state |= SS_SENTLASTWRITESIG; 371 372 *pollev |= POLLOUT; 373 *sigev |= SOCKETSIG_WRITE; 374 375 return (1); 376 } else { 377 return (0); 378 } 379 } 380