xref: /onnv-gate/usr/src/uts/common/fs/sockfs/socknotify.c (revision 12643:044ff822d212)
18348SEric.Yu@Sun.COM /*
28348SEric.Yu@Sun.COM  * CDDL HEADER START
38348SEric.Yu@Sun.COM  *
48348SEric.Yu@Sun.COM  * The contents of this file are subject to the terms of the
58348SEric.Yu@Sun.COM  * Common Development and Distribution License (the "License").
68348SEric.Yu@Sun.COM  * You may not use this file except in compliance with the License.
78348SEric.Yu@Sun.COM  *
88348SEric.Yu@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98348SEric.Yu@Sun.COM  * or http://www.opensolaris.org/os/licensing.
108348SEric.Yu@Sun.COM  * See the License for the specific language governing permissions
118348SEric.Yu@Sun.COM  * and limitations under the License.
128348SEric.Yu@Sun.COM  *
138348SEric.Yu@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
148348SEric.Yu@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158348SEric.Yu@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
168348SEric.Yu@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
178348SEric.Yu@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
188348SEric.Yu@Sun.COM  *
198348SEric.Yu@Sun.COM  * CDDL HEADER END
208348SEric.Yu@Sun.COM  */
218348SEric.Yu@Sun.COM 
228348SEric.Yu@Sun.COM /*
23*12643SAnders.Persson@Sun.COM  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
248348SEric.Yu@Sun.COM  */
258348SEric.Yu@Sun.COM 
268348SEric.Yu@Sun.COM #include <sys/types.h>
278348SEric.Yu@Sun.COM #include <sys/param.h>
288348SEric.Yu@Sun.COM #include <sys/systm.h>
298348SEric.Yu@Sun.COM #include <sys/stropts.h>
308348SEric.Yu@Sun.COM #include <sys/socketvar.h>
318348SEric.Yu@Sun.COM #include <sys/ksocket.h>
328348SEric.Yu@Sun.COM #include <io/ksocket/ksocket_impl.h>
338348SEric.Yu@Sun.COM #include <fs/sockfs/sockcommon.h>
349491SAnders.Persson@Sun.COM #include <fs/sockfs/sodirect.h>
35*12643SAnders.Persson@Sun.COM #include <fs/sockfs/sockfilter_impl.h>
368348SEric.Yu@Sun.COM 
378348SEric.Yu@Sun.COM /*
388348SEric.Yu@Sun.COM  * There can only be a single thread waiting for data (enforced by
398348SEric.Yu@Sun.COM  * so_lock_read()), whereas for write there might be multiple threads
408348SEric.Yu@Sun.COM  * waiting for transmit buffers. So therefore we use cv_broadcast for
418348SEric.Yu@Sun.COM  * write and cv_signal for read.
428348SEric.Yu@Sun.COM  */
438348SEric.Yu@Sun.COM #define	SO_WAKEUP_READER(so) {				\
448348SEric.Yu@Sun.COM 	if ((so)->so_rcv_wakeup) {			\
458348SEric.Yu@Sun.COM 		(so)->so_rcv_wakeup = B_FALSE;		\
468348SEric.Yu@Sun.COM 		cv_signal(&(so)->so_rcv_cv);		\
478348SEric.Yu@Sun.COM 	}						\
488348SEric.Yu@Sun.COM }
498348SEric.Yu@Sun.COM 
508348SEric.Yu@Sun.COM #define	SO_WAKEUP_WRITER(so) {			\
518348SEric.Yu@Sun.COM 	if ((so)->so_snd_wakeup) {		\
528348SEric.Yu@Sun.COM 		(so)->so_snd_wakeup = B_FALSE;	\
538348SEric.Yu@Sun.COM 		cv_broadcast(&(so)->so_snd_cv);	\
548348SEric.Yu@Sun.COM 	}					\
558348SEric.Yu@Sun.COM }
568348SEric.Yu@Sun.COM 
578348SEric.Yu@Sun.COM static int i_so_notify_last_rx(struct sonode *, int *, int *);
588348SEric.Yu@Sun.COM static int i_so_notify_last_tx(struct sonode *, int *, int *);
598348SEric.Yu@Sun.COM 
608348SEric.Yu@Sun.COM /*
618348SEric.Yu@Sun.COM  * The notification functions must be called with so_lock held,
628348SEric.Yu@Sun.COM  * and they will all *drop* so_lock before returning.
638348SEric.Yu@Sun.COM  */
648348SEric.Yu@Sun.COM 
658348SEric.Yu@Sun.COM /*
668348SEric.Yu@Sun.COM  * Wake up anyone waiting for the connection to be established.
678348SEric.Yu@Sun.COM  */
688348SEric.Yu@Sun.COM void
so_notify_connected(struct sonode * so)698348SEric.Yu@Sun.COM so_notify_connected(struct sonode *so)
708348SEric.Yu@Sun.COM {
718348SEric.Yu@Sun.COM 	ASSERT(MUTEX_HELD(&so->so_lock));
728348SEric.Yu@Sun.COM 
738348SEric.Yu@Sun.COM 	if (IS_KERNEL_SOCKET(so)) {
748348SEric.Yu@Sun.COM 		KSOCKET_CALLBACK(so, connected, 0);
758348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
768348SEric.Yu@Sun.COM 	} else {
778348SEric.Yu@Sun.COM 		socket_sendsig(so, SOCKETSIG_WRITE);
788348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
798348SEric.Yu@Sun.COM 		pollwakeup(&so->so_poll_list, POLLOUT);
808348SEric.Yu@Sun.COM 	}
81*12643SAnders.Persson@Sun.COM 	sof_sonode_notify_filters(so, SOF_EV_CONNECTED, 0);
828348SEric.Yu@Sun.COM 
838348SEric.Yu@Sun.COM 	ASSERT(MUTEX_NOT_HELD(&so->so_lock));
848348SEric.Yu@Sun.COM }
858348SEric.Yu@Sun.COM 
868348SEric.Yu@Sun.COM /*
878348SEric.Yu@Sun.COM  * The socket is disconnecting, so no more data can be sent. Wake up
888348SEric.Yu@Sun.COM  * anyone that is waiting to send data.
898348SEric.Yu@Sun.COM  */
908348SEric.Yu@Sun.COM void
so_notify_disconnecting(struct sonode * so)918348SEric.Yu@Sun.COM so_notify_disconnecting(struct sonode *so)
928348SEric.Yu@Sun.COM {
938348SEric.Yu@Sun.COM 	int pollev = 0;
948348SEric.Yu@Sun.COM 	int sigev = 0;
958348SEric.Yu@Sun.COM 
968348SEric.Yu@Sun.COM 	ASSERT(MUTEX_HELD(&so->so_lock));
97*12643SAnders.Persson@Sun.COM 	(void) i_so_notify_last_tx(so, &pollev, &sigev);
988348SEric.Yu@Sun.COM 
998348SEric.Yu@Sun.COM 	if (IS_KERNEL_SOCKET(so)) {
1008348SEric.Yu@Sun.COM 		KSOCKET_CALLBACK(so, cantsendmore, 0);
1018348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
102*12643SAnders.Persson@Sun.COM 	} else {
103*12643SAnders.Persson@Sun.COM 		if (sigev != 0)
104*12643SAnders.Persson@Sun.COM 			socket_sendsig(so, sigev);
1058348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
106*12643SAnders.Persson@Sun.COM 		if (pollev != 0)
107*12643SAnders.Persson@Sun.COM 			pollwakeup(&so->so_poll_list, pollev);
1088348SEric.Yu@Sun.COM 	}
109*12643SAnders.Persson@Sun.COM 	sof_sonode_notify_filters(so, SOF_EV_CANTSENDMORE, 0);
1108348SEric.Yu@Sun.COM 
1118348SEric.Yu@Sun.COM 	ASSERT(MUTEX_NOT_HELD(&so->so_lock));
1128348SEric.Yu@Sun.COM }
1138348SEric.Yu@Sun.COM 
1148348SEric.Yu@Sun.COM /*
1158348SEric.Yu@Sun.COM  * The socket is disconnected, so not more data can be sent or received.
1168348SEric.Yu@Sun.COM  * Wake up anyone that is waiting to send or receive data.
1178348SEric.Yu@Sun.COM  */
1188348SEric.Yu@Sun.COM void
so_notify_disconnected(struct sonode * so,boolean_t connfailed,int error)119*12643SAnders.Persson@Sun.COM so_notify_disconnected(struct sonode *so, boolean_t connfailed, int error)
1208348SEric.Yu@Sun.COM {
1218348SEric.Yu@Sun.COM 	int pollev = 0;
1228348SEric.Yu@Sun.COM 	int sigev = 0;
1238348SEric.Yu@Sun.COM 
1248348SEric.Yu@Sun.COM 	ASSERT(MUTEX_HELD(&so->so_lock));
1258348SEric.Yu@Sun.COM 
1268348SEric.Yu@Sun.COM 	(void) i_so_notify_last_tx(so, &pollev, &sigev);
1278348SEric.Yu@Sun.COM 	(void) i_so_notify_last_rx(so, &pollev, &sigev);
1288348SEric.Yu@Sun.COM 
1298348SEric.Yu@Sun.COM 	if (IS_KERNEL_SOCKET(so)) {
130*12643SAnders.Persson@Sun.COM 		if (connfailed) {
131*12643SAnders.Persson@Sun.COM 			KSOCKET_CALLBACK(so, disconnected, error);
132*12643SAnders.Persson@Sun.COM 		} else {
133*12643SAnders.Persson@Sun.COM 			KSOCKET_CALLBACK(so, connectfailed, error);
134*12643SAnders.Persson@Sun.COM 		}
1358348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
1368348SEric.Yu@Sun.COM 	} else {
1378348SEric.Yu@Sun.COM 		if (sigev != 0)
1388348SEric.Yu@Sun.COM 			socket_sendsig(so, sigev);
1398348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
1408348SEric.Yu@Sun.COM 		if (pollev != 0)
1418348SEric.Yu@Sun.COM 			pollwakeup(&so->so_poll_list, pollev);
1428348SEric.Yu@Sun.COM 	}
143*12643SAnders.Persson@Sun.COM 	sof_sonode_notify_filters(so, (connfailed) ? SOF_EV_CONNECTFAILED :
144*12643SAnders.Persson@Sun.COM 	    SOF_EV_DISCONNECTED, error);
1458348SEric.Yu@Sun.COM 
1468348SEric.Yu@Sun.COM 	ASSERT(MUTEX_NOT_HELD(&so->so_lock));
1478348SEric.Yu@Sun.COM }
1488348SEric.Yu@Sun.COM 
1498348SEric.Yu@Sun.COM /*
1508348SEric.Yu@Sun.COM  * The socket is writeable. Wake up anyone waiting to send data.
1518348SEric.Yu@Sun.COM  */
1528348SEric.Yu@Sun.COM void
so_notify_writable(struct sonode * so)1538348SEric.Yu@Sun.COM so_notify_writable(struct sonode *so)
1548348SEric.Yu@Sun.COM {
1558348SEric.Yu@Sun.COM 	ASSERT(MUTEX_HELD(&so->so_lock));
1568348SEric.Yu@Sun.COM 
1578348SEric.Yu@Sun.COM 	SO_WAKEUP_WRITER(so);
1588348SEric.Yu@Sun.COM 
1598348SEric.Yu@Sun.COM 	if (IS_KERNEL_SOCKET(so)) {
1608348SEric.Yu@Sun.COM 		KSOCKET_CALLBACK(so, cansend, 0);
1618348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
1628348SEric.Yu@Sun.COM 	} else {
1638348SEric.Yu@Sun.COM 		socket_sendsig(so, SOCKETSIG_WRITE);
1648348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
1658348SEric.Yu@Sun.COM 		pollwakeup(&so->so_poll_list, POLLOUT);
1668348SEric.Yu@Sun.COM 	}
1678348SEric.Yu@Sun.COM 
1688348SEric.Yu@Sun.COM 	ASSERT(MUTEX_NOT_HELD(&so->so_lock));
169*12643SAnders.Persson@Sun.COM 
170*12643SAnders.Persson@Sun.COM 	/* filters can start injecting data */
171*12643SAnders.Persson@Sun.COM 	if (so->so_filter_active > 0)
172*12643SAnders.Persson@Sun.COM 		sof_sonode_notify_filters(so, SOF_EV_INJECT_DATA_OUT_OK, 0);
1738348SEric.Yu@Sun.COM }
1748348SEric.Yu@Sun.COM 
1758348SEric.Yu@Sun.COM /*
1768348SEric.Yu@Sun.COM  * Data is available, so wake up anyone waiting for data.
1778348SEric.Yu@Sun.COM  */
1788348SEric.Yu@Sun.COM void
so_notify_data(struct sonode * so,size_t qlen)1798348SEric.Yu@Sun.COM so_notify_data(struct sonode *so, size_t qlen)
1808348SEric.Yu@Sun.COM {
1818348SEric.Yu@Sun.COM 	ASSERT(MUTEX_HELD(&so->so_lock));
1828348SEric.Yu@Sun.COM 
1838348SEric.Yu@Sun.COM 	SO_WAKEUP_READER(so);
1848348SEric.Yu@Sun.COM 
1858348SEric.Yu@Sun.COM 	if (IS_KERNEL_SOCKET(so)) {
1868348SEric.Yu@Sun.COM 		KSOCKET_CALLBACK(so, newdata, qlen);
1878348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
1888348SEric.Yu@Sun.COM 	} else {
1898348SEric.Yu@Sun.COM 		socket_sendsig(so, SOCKETSIG_READ);
1908348SEric.Yu@Sun.COM 		if (so->so_pollev & (SO_POLLEV_IN|SO_POLLEV_ALWAYS)) {
1918348SEric.Yu@Sun.COM 			so->so_pollev &= ~SO_POLLEV_IN;
1928348SEric.Yu@Sun.COM 			mutex_exit(&so->so_lock);
1938348SEric.Yu@Sun.COM 			pollwakeup(&so->so_poll_list, POLLIN|POLLRDNORM);
1948348SEric.Yu@Sun.COM 		} else {
1958348SEric.Yu@Sun.COM 			mutex_exit(&so->so_lock);
1968348SEric.Yu@Sun.COM 		}
1978348SEric.Yu@Sun.COM 	}
1988348SEric.Yu@Sun.COM 
1998348SEric.Yu@Sun.COM 	ASSERT(MUTEX_NOT_HELD(&so->so_lock));
2008348SEric.Yu@Sun.COM }
2018348SEric.Yu@Sun.COM 
2028348SEric.Yu@Sun.COM /*
2038348SEric.Yu@Sun.COM  * Transient error. Wake up anyone waiting to send or receive data.
2048348SEric.Yu@Sun.COM  */
2058348SEric.Yu@Sun.COM void
so_notify_error(struct sonode * so)2068348SEric.Yu@Sun.COM so_notify_error(struct sonode *so)
2078348SEric.Yu@Sun.COM {
2088348SEric.Yu@Sun.COM 	ASSERT(MUTEX_HELD(&so->so_lock));
2098348SEric.Yu@Sun.COM 
2108348SEric.Yu@Sun.COM 	SO_WAKEUP_WRITER(so);
2118348SEric.Yu@Sun.COM 	SO_WAKEUP_READER(so);
2128348SEric.Yu@Sun.COM 
2138348SEric.Yu@Sun.COM 	if (IS_KERNEL_SOCKET(so)) {
2148348SEric.Yu@Sun.COM 		KSOCKET_CALLBACK(so, error, 0);
2158348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
2168348SEric.Yu@Sun.COM 	} else {
2178348SEric.Yu@Sun.COM 		socket_sendsig(so, SOCKETSIG_WRITE|SOCKETSIG_READ);
2188348SEric.Yu@Sun.COM 		so->so_pollev &= ~SO_POLLEV_IN;
2198348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
2208348SEric.Yu@Sun.COM 		pollwakeup(&so->so_poll_list, POLLOUT|POLLIN|POLLRDNORM);
2218348SEric.Yu@Sun.COM 	}
2228348SEric.Yu@Sun.COM 
2238348SEric.Yu@Sun.COM 	ASSERT(MUTEX_NOT_HELD(&so->so_lock));
2248348SEric.Yu@Sun.COM }
2258348SEric.Yu@Sun.COM 
2268348SEric.Yu@Sun.COM /*
2278348SEric.Yu@Sun.COM  * Out-of-band data is incoming, notify any interested parties.
2288348SEric.Yu@Sun.COM  */
2298348SEric.Yu@Sun.COM void
so_notify_oobsig(struct sonode * so)2308348SEric.Yu@Sun.COM so_notify_oobsig(struct sonode *so)
2318348SEric.Yu@Sun.COM {
2328348SEric.Yu@Sun.COM 	socket_sendsig(so, SOCKETSIG_URG);
2338348SEric.Yu@Sun.COM 	mutex_exit(&so->so_lock);
2348348SEric.Yu@Sun.COM 	pollwakeup(&so->so_poll_list, POLLRDBAND);
2358348SEric.Yu@Sun.COM }
2368348SEric.Yu@Sun.COM 
2378348SEric.Yu@Sun.COM /*
2388348SEric.Yu@Sun.COM  * Received out-of-band data. If the OOB data is delivered inline, then
2398348SEric.Yu@Sun.COM  * in addition of regular OOB notification, anyone waiting for normal
2408348SEric.Yu@Sun.COM  * data is also notified.
2418348SEric.Yu@Sun.COM  */
2428348SEric.Yu@Sun.COM void
so_notify_oobdata(struct sonode * so,boolean_t oob_inline)2438348SEric.Yu@Sun.COM so_notify_oobdata(struct sonode *so, boolean_t oob_inline)
2448348SEric.Yu@Sun.COM {
2458348SEric.Yu@Sun.COM 	ASSERT(MUTEX_HELD(&so->so_lock));
2469491SAnders.Persson@Sun.COM 	if (so->so_direct != NULL)
2479491SAnders.Persson@Sun.COM 		SOD_UIOAFINI(so->so_direct);
2488348SEric.Yu@Sun.COM 
2499752SAnders.Persson@Sun.COM 	SO_WAKEUP_READER(so);
2509752SAnders.Persson@Sun.COM 
2518348SEric.Yu@Sun.COM 	if (IS_KERNEL_SOCKET(so)) {
2528348SEric.Yu@Sun.COM 		KSOCKET_CALLBACK(so, oobdata, 0);
2538348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
2548348SEric.Yu@Sun.COM 	} else {
2558348SEric.Yu@Sun.COM 		if (oob_inline) {
2568348SEric.Yu@Sun.COM 			socket_sendsig(so, SOCKETSIG_READ);
2578348SEric.Yu@Sun.COM 			so->so_pollev &= ~SO_POLLEV_IN;
2588348SEric.Yu@Sun.COM 			mutex_exit(&so->so_lock);
2598348SEric.Yu@Sun.COM 			pollwakeup(&so->so_poll_list,
2608348SEric.Yu@Sun.COM 			    POLLRDBAND|POLLIN|POLLRDNORM);
2618348SEric.Yu@Sun.COM 		} else {
2628348SEric.Yu@Sun.COM 			mutex_exit(&so->so_lock);
2638348SEric.Yu@Sun.COM 			pollwakeup(&so->so_poll_list, POLLRDBAND);
2648348SEric.Yu@Sun.COM 		}
2658348SEric.Yu@Sun.COM 	}
2668348SEric.Yu@Sun.COM 
2678348SEric.Yu@Sun.COM 	ASSERT(MUTEX_NOT_HELD(&so->so_lock));
2688348SEric.Yu@Sun.COM }
2698348SEric.Yu@Sun.COM 
2708348SEric.Yu@Sun.COM /*
2718348SEric.Yu@Sun.COM  * End-of-file has been reach, so peer will send no new data. Wake up
2728348SEric.Yu@Sun.COM  * anyone that is waiting for data.
2738348SEric.Yu@Sun.COM  */
2748348SEric.Yu@Sun.COM void
so_notify_eof(struct sonode * so)2758348SEric.Yu@Sun.COM so_notify_eof(struct sonode *so)
2768348SEric.Yu@Sun.COM {
2778348SEric.Yu@Sun.COM 	int pollev = 0;
2788348SEric.Yu@Sun.COM 	int sigev = 0;
2798348SEric.Yu@Sun.COM 
2808348SEric.Yu@Sun.COM 	ASSERT(MUTEX_HELD(&so->so_lock));
2818348SEric.Yu@Sun.COM 
2828348SEric.Yu@Sun.COM 	(void) i_so_notify_last_rx(so, &pollev, &sigev);
2838348SEric.Yu@Sun.COM 
2848348SEric.Yu@Sun.COM 	if (IS_KERNEL_SOCKET(so)) {
2858348SEric.Yu@Sun.COM 		KSOCKET_CALLBACK(so, cantrecvmore, 0);
2868348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
2878348SEric.Yu@Sun.COM 	} else {
2888348SEric.Yu@Sun.COM 		if (sigev != 0)
2898348SEric.Yu@Sun.COM 			socket_sendsig(so, sigev);
2908348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
2918348SEric.Yu@Sun.COM 		if (pollev != 0)
2928348SEric.Yu@Sun.COM 			pollwakeup(&so->so_poll_list, pollev);
2938348SEric.Yu@Sun.COM 
2948348SEric.Yu@Sun.COM 	}
295*12643SAnders.Persson@Sun.COM 	sof_sonode_notify_filters(so, SOF_EV_CANTRECVMORE, 0);
2968348SEric.Yu@Sun.COM 
2978348SEric.Yu@Sun.COM 	ASSERT(MUTEX_NOT_HELD(&so->so_lock));
2988348SEric.Yu@Sun.COM }
2998348SEric.Yu@Sun.COM 
3008348SEric.Yu@Sun.COM /*
3018348SEric.Yu@Sun.COM  * Wake up anyone waiting for a new connection.
3028348SEric.Yu@Sun.COM  */
3038348SEric.Yu@Sun.COM void
so_notify_newconn(struct sonode * so)3048348SEric.Yu@Sun.COM so_notify_newconn(struct sonode *so)
3058348SEric.Yu@Sun.COM {
3068348SEric.Yu@Sun.COM 	ASSERT(MUTEX_HELD(&so->so_lock));
3078348SEric.Yu@Sun.COM 
3088348SEric.Yu@Sun.COM 	if (IS_KERNEL_SOCKET(so)) {
309*12643SAnders.Persson@Sun.COM 		KSOCKET_CALLBACK(so, newconn, 0);
3108348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
3118348SEric.Yu@Sun.COM 	} else {
3128348SEric.Yu@Sun.COM 		socket_sendsig(so, SOCKETSIG_READ);
3138348SEric.Yu@Sun.COM 		if (so->so_pollev & (SO_POLLEV_IN|SO_POLLEV_ALWAYS)) {
3148348SEric.Yu@Sun.COM 			so->so_pollev &= ~SO_POLLEV_IN;
3158348SEric.Yu@Sun.COM 			mutex_exit(&so->so_lock);
3168348SEric.Yu@Sun.COM 			pollwakeup(&so->so_poll_list, POLLIN|POLLRDNORM);
3178348SEric.Yu@Sun.COM 		} else {
3188348SEric.Yu@Sun.COM 			mutex_exit(&so->so_lock);
3198348SEric.Yu@Sun.COM 		}
3208348SEric.Yu@Sun.COM 	}
3218348SEric.Yu@Sun.COM 
3228348SEric.Yu@Sun.COM 	ASSERT(MUTEX_NOT_HELD(&so->so_lock));
3238348SEric.Yu@Sun.COM }
3248348SEric.Yu@Sun.COM 
3258348SEric.Yu@Sun.COM /*
3268348SEric.Yu@Sun.COM  * User initated shutdown/close, wake anyone that is trying to do
3278348SEric.Yu@Sun.COM  * an operation that is no longer possible.
3288348SEric.Yu@Sun.COM  */
3298348SEric.Yu@Sun.COM void
so_notify_shutdown(struct sonode * so)3308348SEric.Yu@Sun.COM so_notify_shutdown(struct sonode *so)
3318348SEric.Yu@Sun.COM {
3328348SEric.Yu@Sun.COM 	int pollev = 0;
3338348SEric.Yu@Sun.COM 	int sigev = 0;
3348348SEric.Yu@Sun.COM 
3358348SEric.Yu@Sun.COM 	ASSERT(MUTEX_HELD(&so->so_lock));
3368348SEric.Yu@Sun.COM 	ASSERT(so->so_state & (SS_CANTSENDMORE|SS_CANTRCVMORE));
3378348SEric.Yu@Sun.COM 
3388348SEric.Yu@Sun.COM 	if (so->so_state & SS_CANTSENDMORE)
3398348SEric.Yu@Sun.COM 		(void) i_so_notify_last_tx(so, &pollev, &sigev);
3408348SEric.Yu@Sun.COM 	if (so->so_state & SS_CANTRCVMORE)
3418348SEric.Yu@Sun.COM 		(void) i_so_notify_last_rx(so, &pollev, &sigev);
3428348SEric.Yu@Sun.COM 
3438348SEric.Yu@Sun.COM 	if (sigev != 0)
3448348SEric.Yu@Sun.COM 		socket_sendsig(so, sigev);
3458348SEric.Yu@Sun.COM 	mutex_exit(&so->so_lock);
3468348SEric.Yu@Sun.COM 	if (pollev != 0)
3478348SEric.Yu@Sun.COM 		pollwakeup(&so->so_poll_list, pollev);
3488348SEric.Yu@Sun.COM 
3498348SEric.Yu@Sun.COM 	ASSERT(MUTEX_NOT_HELD(&so->so_lock));
3508348SEric.Yu@Sun.COM }
3518348SEric.Yu@Sun.COM 
3528348SEric.Yu@Sun.COM /*
3538348SEric.Yu@Sun.COM  * No more data will be coming in, and this will be the last notification
3548348SEric.Yu@Sun.COM  * made.
3558348SEric.Yu@Sun.COM  */
3568348SEric.Yu@Sun.COM static int
i_so_notify_last_rx(struct sonode * so,int * pollev,int * sigev)3578348SEric.Yu@Sun.COM i_so_notify_last_rx(struct sonode *so, int *pollev, int *sigev)
3588348SEric.Yu@Sun.COM {
3598348SEric.Yu@Sun.COM 	if (!(so->so_state & SS_SENTLASTREADSIG)) {
3608348SEric.Yu@Sun.COM 		SOCKET_TIMER_CANCEL(so);
3618348SEric.Yu@Sun.COM 		SO_WAKEUP_READER(so);
3628348SEric.Yu@Sun.COM 		so->so_state |= SS_SENTLASTREADSIG;
3638348SEric.Yu@Sun.COM 		so->so_pollev &= ~SO_POLLEV_IN;
3648348SEric.Yu@Sun.COM 
3658348SEric.Yu@Sun.COM 		*pollev |= POLLIN|POLLRDNORM;
3668348SEric.Yu@Sun.COM 		*sigev |= SOCKETSIG_READ;
3678348SEric.Yu@Sun.COM 
3688348SEric.Yu@Sun.COM 		return (1);
3698348SEric.Yu@Sun.COM 	} else {
3708348SEric.Yu@Sun.COM 		return (0);
3718348SEric.Yu@Sun.COM 	}
3728348SEric.Yu@Sun.COM }
3738348SEric.Yu@Sun.COM 
3748348SEric.Yu@Sun.COM /*
3758348SEric.Yu@Sun.COM  * The socket is un-writeable. Make one last notification.
3768348SEric.Yu@Sun.COM  */
3778348SEric.Yu@Sun.COM static int
i_so_notify_last_tx(struct sonode * so,int * pollev,int * sigev)3788348SEric.Yu@Sun.COM i_so_notify_last_tx(struct sonode *so, int *pollev, int *sigev)
3798348SEric.Yu@Sun.COM {
3808348SEric.Yu@Sun.COM 	if (!(so->so_state & SS_SENTLASTWRITESIG)) {
3818348SEric.Yu@Sun.COM 		SO_WAKEUP_WRITER(so);
3828348SEric.Yu@Sun.COM 		so->so_state |= SS_SENTLASTWRITESIG;
3838348SEric.Yu@Sun.COM 
3848348SEric.Yu@Sun.COM 		*pollev |= POLLOUT;
3858348SEric.Yu@Sun.COM 		*sigev |= SOCKETSIG_WRITE;
3868348SEric.Yu@Sun.COM 
3878348SEric.Yu@Sun.COM 		return (1);
3888348SEric.Yu@Sun.COM 	} else {
3898348SEric.Yu@Sun.COM 		return (0);
3908348SEric.Yu@Sun.COM 	}
3918348SEric.Yu@Sun.COM }
392