xref: /onnv-gate/usr/src/uts/common/fs/sockfs/socknotify.c (revision 8348:4137e18bfaf0)
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