dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / kernel / fs / sockfs / socknotify.c
blobd50e37681db90ccc8af59f5bf79b6675d1ffafa0
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
27 * Copyright (c) 2014, Joyent, Inc. All rights reserved.
30 #include <sys/types.h>
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/stropts.h>
34 #include <sys/socketvar.h>
35 #include <sys/ksocket.h>
36 #include <io/ksocket/ksocket_impl.h>
37 #include "sockcommon.h"
38 #include "sodirect.h"
39 #include "sockfilter_impl.h"
42 * There can only be a single thread waiting for data (enforced by
43 * so_lock_read()), whereas for write there might be multiple threads
44 * waiting for transmit buffers. So therefore we use cv_broadcast for
45 * write and cv_signal for read.
47 #define SO_WAKEUP_READER(so) { \
48 if ((so)->so_rcv_wakeup) { \
49 (so)->so_rcv_wakeup = B_FALSE; \
50 cv_signal(&(so)->so_rcv_cv); \
51 } \
54 #define SO_WAKEUP_WRITER(so) { \
55 if ((so)->so_snd_wakeup) { \
56 (so)->so_snd_wakeup = B_FALSE; \
57 cv_broadcast(&(so)->so_snd_cv); \
58 } \
61 static int i_so_notify_last_rx(struct sonode *, int *, int *);
62 static int i_so_notify_last_tx(struct sonode *, int *, int *);
65 * The notification functions must be called with so_lock held,
66 * and they will all *drop* so_lock before returning.
70 * Wake up anyone waiting for the connection to be established.
72 void
73 so_notify_connected(struct sonode *so)
75 ASSERT(MUTEX_HELD(&so->so_lock));
77 if (IS_KERNEL_SOCKET(so)) {
78 KSOCKET_CALLBACK(so, connected, 0);
79 mutex_exit(&so->so_lock);
80 } else {
81 socket_sendsig(so, SOCKETSIG_WRITE);
82 mutex_exit(&so->so_lock);
83 pollwakeup(&so->so_poll_list, POLLOUT);
85 sof_sonode_notify_filters(so, SOF_EV_CONNECTED, 0);
87 ASSERT(MUTEX_NOT_HELD(&so->so_lock));
91 * The socket is disconnecting, so no more data can be sent. Wake up
92 * anyone that is waiting to send data.
94 void
95 so_notify_disconnecting(struct sonode *so)
97 int pollev = 0;
98 int sigev = 0;
100 ASSERT(MUTEX_HELD(&so->so_lock));
101 (void) i_so_notify_last_tx(so, &pollev, &sigev);
103 if (IS_KERNEL_SOCKET(so)) {
104 KSOCKET_CALLBACK(so, cantsendmore, 0);
105 mutex_exit(&so->so_lock);
106 } else {
107 if (sigev != 0)
108 socket_sendsig(so, sigev);
109 mutex_exit(&so->so_lock);
111 if (pollev != 0)
112 pollwakeup(&so->so_poll_list, pollev);
114 sof_sonode_notify_filters(so, SOF_EV_CANTSENDMORE, 0);
116 ASSERT(MUTEX_NOT_HELD(&so->so_lock));
120 * The socket is disconnected, so not more data can be sent or received.
121 * Wake up anyone that is waiting to send or receive data.
123 void
124 so_notify_disconnected(struct sonode *so, boolean_t connfailed, int error)
126 int pollev = 0;
127 int sigev = 0;
129 ASSERT(MUTEX_HELD(&so->so_lock));
131 (void) i_so_notify_last_tx(so, &pollev, &sigev);
132 (void) i_so_notify_last_rx(so, &pollev, &sigev);
134 if (IS_KERNEL_SOCKET(so)) {
135 if (connfailed) {
136 KSOCKET_CALLBACK(so, disconnected, error);
137 } else {
138 KSOCKET_CALLBACK(so, connectfailed, error);
140 mutex_exit(&so->so_lock);
141 } else {
142 if (sigev != 0)
143 socket_sendsig(so, sigev);
144 mutex_exit(&so->so_lock);
147 * If we're here because the socket has become disconnected,
148 * we explicitly set POLLHUP. At the same time, we also clear
149 * POLLOUT, as POLLOUT and POLLHUP are defined to be mutually
150 * exclusive with respect to one another.
152 if (!connfailed)
153 pollev = (pollev | POLLHUP) & ~POLLOUT;
155 if (pollev != 0)
156 pollwakeup(&so->so_poll_list, pollev);
158 sof_sonode_notify_filters(so, (connfailed) ? SOF_EV_CONNECTFAILED :
159 SOF_EV_DISCONNECTED, error);
161 ASSERT(MUTEX_NOT_HELD(&so->so_lock));
165 * The socket is writeable. Wake up anyone waiting to send data.
167 void
168 so_notify_writable(struct sonode *so)
170 ASSERT(MUTEX_HELD(&so->so_lock));
172 SO_WAKEUP_WRITER(so);
174 if (IS_KERNEL_SOCKET(so)) {
175 KSOCKET_CALLBACK(so, cansend, 0);
176 mutex_exit(&so->so_lock);
177 } else {
178 socket_sendsig(so, SOCKETSIG_WRITE);
179 mutex_exit(&so->so_lock);
180 pollwakeup(&so->so_poll_list, POLLOUT);
183 ASSERT(MUTEX_NOT_HELD(&so->so_lock));
185 /* filters can start injecting data */
186 if (so->so_filter_active > 0)
187 sof_sonode_notify_filters(so, SOF_EV_INJECT_DATA_OUT_OK, 0);
191 * Data is available, so wake up anyone waiting for data.
193 void
194 so_notify_data(struct sonode *so, size_t qlen)
196 ASSERT(MUTEX_HELD(&so->so_lock));
198 SO_WAKEUP_READER(so);
200 if (IS_KERNEL_SOCKET(so)) {
201 KSOCKET_CALLBACK(so, newdata, qlen);
202 mutex_exit(&so->so_lock);
203 } else {
204 socket_sendsig(so, SOCKETSIG_READ);
205 if (so->so_pollev & (SO_POLLEV_IN|SO_POLLEV_ALWAYS)) {
206 so->so_pollev &= ~SO_POLLEV_IN;
207 mutex_exit(&so->so_lock);
208 pollwakeup(&so->so_poll_list, POLLIN|POLLRDNORM);
209 } else {
210 mutex_exit(&so->so_lock);
214 ASSERT(MUTEX_NOT_HELD(&so->so_lock));
218 * Transient error. Wake up anyone waiting to send or receive data.
220 void
221 so_notify_error(struct sonode *so)
223 ASSERT(MUTEX_HELD(&so->so_lock));
225 SO_WAKEUP_WRITER(so);
226 SO_WAKEUP_READER(so);
228 if (IS_KERNEL_SOCKET(so)) {
229 KSOCKET_CALLBACK(so, error, 0);
230 mutex_exit(&so->so_lock);
231 } else {
232 socket_sendsig(so, SOCKETSIG_WRITE|SOCKETSIG_READ);
233 so->so_pollev &= ~SO_POLLEV_IN;
234 mutex_exit(&so->so_lock);
235 pollwakeup(&so->so_poll_list, POLLOUT|POLLIN|POLLRDNORM);
238 ASSERT(MUTEX_NOT_HELD(&so->so_lock));
242 * Out-of-band data is incoming, notify any interested parties.
244 void
245 so_notify_oobsig(struct sonode *so)
247 socket_sendsig(so, SOCKETSIG_URG);
248 mutex_exit(&so->so_lock);
249 pollwakeup(&so->so_poll_list, POLLRDBAND);
253 * Received out-of-band data. If the OOB data is delivered inline, then
254 * in addition of regular OOB notification, anyone waiting for normal
255 * data is also notified.
257 void
258 so_notify_oobdata(struct sonode *so, boolean_t oob_inline)
260 ASSERT(MUTEX_HELD(&so->so_lock));
261 if (so->so_direct != NULL)
262 SOD_UIOAFINI(so->so_direct);
264 SO_WAKEUP_READER(so);
266 if (IS_KERNEL_SOCKET(so)) {
267 KSOCKET_CALLBACK(so, oobdata, 0);
268 mutex_exit(&so->so_lock);
269 } else {
270 if (oob_inline) {
271 socket_sendsig(so, SOCKETSIG_READ);
272 so->so_pollev &= ~SO_POLLEV_IN;
273 mutex_exit(&so->so_lock);
274 pollwakeup(&so->so_poll_list,
275 POLLRDBAND|POLLIN|POLLRDNORM);
276 } else {
277 mutex_exit(&so->so_lock);
278 pollwakeup(&so->so_poll_list, POLLRDBAND);
282 ASSERT(MUTEX_NOT_HELD(&so->so_lock));
286 * End-of-file has been reach, so peer will send no new data. Wake up
287 * anyone that is waiting for data.
289 void
290 so_notify_eof(struct sonode *so)
292 int pollev = 0;
293 int sigev = 0;
295 ASSERT(MUTEX_HELD(&so->so_lock));
297 (void) i_so_notify_last_rx(so, &pollev, &sigev);
299 if (IS_KERNEL_SOCKET(so)) {
300 KSOCKET_CALLBACK(so, cantrecvmore, 0);
301 mutex_exit(&so->so_lock);
302 } else {
303 if (sigev != 0)
304 socket_sendsig(so, sigev);
305 mutex_exit(&so->so_lock);
306 if (pollev != 0)
307 pollwakeup(&so->so_poll_list, pollev);
310 sof_sonode_notify_filters(so, SOF_EV_CANTRECVMORE, 0);
312 ASSERT(MUTEX_NOT_HELD(&so->so_lock));
316 * Wake up anyone waiting for a new connection.
318 void
319 so_notify_newconn(struct sonode *so)
321 ASSERT(MUTEX_HELD(&so->so_lock));
323 if (IS_KERNEL_SOCKET(so)) {
324 KSOCKET_CALLBACK(so, newconn, 0);
325 mutex_exit(&so->so_lock);
326 } else {
327 socket_sendsig(so, SOCKETSIG_READ);
328 if (so->so_pollev & (SO_POLLEV_IN|SO_POLLEV_ALWAYS)) {
329 so->so_pollev &= ~SO_POLLEV_IN;
330 mutex_exit(&so->so_lock);
331 pollwakeup(&so->so_poll_list, POLLIN|POLLRDNORM);
332 } else {
333 mutex_exit(&so->so_lock);
337 ASSERT(MUTEX_NOT_HELD(&so->so_lock));
341 * User initated shutdown/close, wake anyone that is trying to do
342 * an operation that is no longer possible.
344 void
345 so_notify_shutdown(struct sonode *so)
347 int pollev = 0;
348 int sigev = 0;
350 ASSERT(MUTEX_HELD(&so->so_lock));
351 ASSERT(so->so_state & (SS_CANTSENDMORE|SS_CANTRCVMORE));
353 if (so->so_state & SS_CANTSENDMORE)
354 (void) i_so_notify_last_tx(so, &pollev, &sigev);
355 if (so->so_state & SS_CANTRCVMORE)
356 (void) i_so_notify_last_rx(so, &pollev, &sigev);
358 if (sigev != 0)
359 socket_sendsig(so, sigev);
360 mutex_exit(&so->so_lock);
361 if (pollev != 0)
362 pollwakeup(&so->so_poll_list, pollev);
364 ASSERT(MUTEX_NOT_HELD(&so->so_lock));
368 * No more data will be coming in, and this will be the last notification
369 * made.
371 static int
372 i_so_notify_last_rx(struct sonode *so, int *pollev, int *sigev)
374 if (!(so->so_state & SS_SENTLASTREADSIG)) {
375 SOCKET_TIMER_CANCEL(so);
376 SO_WAKEUP_READER(so);
377 so->so_state |= SS_SENTLASTREADSIG;
378 so->so_pollev &= ~SO_POLLEV_IN;
380 *pollev |= POLLIN|POLLRDNORM|POLLRDHUP;
381 *sigev |= SOCKETSIG_READ;
383 return (1);
384 } else {
385 return (0);
390 * The socket is un-writeable. Make one last notification.
392 static int
393 i_so_notify_last_tx(struct sonode *so, int *pollev, int *sigev)
395 if (!(so->so_state & SS_SENTLASTWRITESIG)) {
396 SO_WAKEUP_WRITER(so);
397 so->so_state |= SS_SENTLASTWRITESIG;
399 *pollev |= POLLOUT;
400 *sigev |= SOCKETSIG_WRITE;
402 return (1);
403 } else {
404 return (0);