xref: /onnv-gate/usr/src/uts/common/fs/sockfs/socknotify.c (revision 9752:bcdc8630445d)
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 /*
239491SAnders.Persson@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
248348SEric.Yu@Sun.COM  * Use is subject to license terms.
258348SEric.Yu@Sun.COM  */
268348SEric.Yu@Sun.COM 
278348SEric.Yu@Sun.COM #include <sys/types.h>
288348SEric.Yu@Sun.COM #include <sys/param.h>
298348SEric.Yu@Sun.COM #include <sys/systm.h>
308348SEric.Yu@Sun.COM #include <sys/stropts.h>
318348SEric.Yu@Sun.COM #include <sys/socketvar.h>
328348SEric.Yu@Sun.COM #include <sys/ksocket.h>
338348SEric.Yu@Sun.COM #include <io/ksocket/ksocket_impl.h>
348348SEric.Yu@Sun.COM #include <fs/sockfs/sockcommon.h>
359491SAnders.Persson@Sun.COM #include <fs/sockfs/sodirect.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
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 	}
818348SEric.Yu@Sun.COM 
828348SEric.Yu@Sun.COM 	ASSERT(MUTEX_NOT_HELD(&so->so_lock));
838348SEric.Yu@Sun.COM }
848348SEric.Yu@Sun.COM 
858348SEric.Yu@Sun.COM /*
868348SEric.Yu@Sun.COM  * The socket is disconnecting, so no more data can be sent. Wake up
878348SEric.Yu@Sun.COM  * anyone that is waiting to send data.
888348SEric.Yu@Sun.COM  */
898348SEric.Yu@Sun.COM void
908348SEric.Yu@Sun.COM so_notify_disconnecting(struct sonode *so)
918348SEric.Yu@Sun.COM {
928348SEric.Yu@Sun.COM 	int pollev = 0;
938348SEric.Yu@Sun.COM 	int sigev = 0;
948348SEric.Yu@Sun.COM 
958348SEric.Yu@Sun.COM 	ASSERT(MUTEX_HELD(&so->so_lock));
968348SEric.Yu@Sun.COM 
978348SEric.Yu@Sun.COM 	if (IS_KERNEL_SOCKET(so)) {
988348SEric.Yu@Sun.COM 		SO_WAKEUP_WRITER(so);
998348SEric.Yu@Sun.COM 		KSOCKET_CALLBACK(so, cantsendmore, 0);
1008348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
1018348SEric.Yu@Sun.COM 	} else if (i_so_notify_last_tx(so, &pollev, &sigev)) {
1028348SEric.Yu@Sun.COM 		socket_sendsig(so, sigev);
1038348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
1048348SEric.Yu@Sun.COM 		pollwakeup(&so->so_poll_list, pollev);
1058348SEric.Yu@Sun.COM 	} else {
1068348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
1078348SEric.Yu@Sun.COM 	}
1088348SEric.Yu@Sun.COM 
1098348SEric.Yu@Sun.COM 	ASSERT(MUTEX_NOT_HELD(&so->so_lock));
1108348SEric.Yu@Sun.COM }
1118348SEric.Yu@Sun.COM 
1128348SEric.Yu@Sun.COM /*
1138348SEric.Yu@Sun.COM  * The socket is disconnected, so not more data can be sent or received.
1148348SEric.Yu@Sun.COM  * Wake up anyone that is waiting to send or receive data.
1158348SEric.Yu@Sun.COM  */
1168348SEric.Yu@Sun.COM void
1178348SEric.Yu@Sun.COM so_notify_disconnected(struct sonode *so, int error)
1188348SEric.Yu@Sun.COM {
1198348SEric.Yu@Sun.COM 	int pollev = 0;
1208348SEric.Yu@Sun.COM 	int sigev = 0;
1218348SEric.Yu@Sun.COM 
1228348SEric.Yu@Sun.COM 	ASSERT(MUTEX_HELD(&so->so_lock));
1238348SEric.Yu@Sun.COM 
1248348SEric.Yu@Sun.COM 	(void) i_so_notify_last_tx(so, &pollev, &sigev);
1258348SEric.Yu@Sun.COM 	(void) i_so_notify_last_rx(so, &pollev, &sigev);
1268348SEric.Yu@Sun.COM 
1278348SEric.Yu@Sun.COM 	if (IS_KERNEL_SOCKET(so)) {
1288348SEric.Yu@Sun.COM 		KSOCKET_CALLBACK(so, disconnected, error);
1298348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
1308348SEric.Yu@Sun.COM 	} else {
1318348SEric.Yu@Sun.COM 		if (sigev != 0)
1328348SEric.Yu@Sun.COM 			socket_sendsig(so, sigev);
1338348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
1348348SEric.Yu@Sun.COM 		if (pollev != 0)
1358348SEric.Yu@Sun.COM 			pollwakeup(&so->so_poll_list, pollev);
1368348SEric.Yu@Sun.COM 	}
1378348SEric.Yu@Sun.COM 
1388348SEric.Yu@Sun.COM 	ASSERT(MUTEX_NOT_HELD(&so->so_lock));
1398348SEric.Yu@Sun.COM }
1408348SEric.Yu@Sun.COM 
1418348SEric.Yu@Sun.COM /*
1428348SEric.Yu@Sun.COM  * The socket is writeable. Wake up anyone waiting to send data.
1438348SEric.Yu@Sun.COM  */
1448348SEric.Yu@Sun.COM void
1458348SEric.Yu@Sun.COM so_notify_writable(struct sonode *so)
1468348SEric.Yu@Sun.COM {
1478348SEric.Yu@Sun.COM 	ASSERT(MUTEX_HELD(&so->so_lock));
1488348SEric.Yu@Sun.COM 
1498348SEric.Yu@Sun.COM 	SO_WAKEUP_WRITER(so);
1508348SEric.Yu@Sun.COM 
1518348SEric.Yu@Sun.COM 	if (IS_KERNEL_SOCKET(so)) {
1528348SEric.Yu@Sun.COM 		KSOCKET_CALLBACK(so, cansend, 0);
1538348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
1548348SEric.Yu@Sun.COM 	} else {
1558348SEric.Yu@Sun.COM 		socket_sendsig(so, SOCKETSIG_WRITE);
1568348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
1578348SEric.Yu@Sun.COM 		pollwakeup(&so->so_poll_list, POLLOUT);
1588348SEric.Yu@Sun.COM 	}
1598348SEric.Yu@Sun.COM 
1608348SEric.Yu@Sun.COM 	ASSERT(MUTEX_NOT_HELD(&so->so_lock));
1618348SEric.Yu@Sun.COM }
1628348SEric.Yu@Sun.COM 
1638348SEric.Yu@Sun.COM /*
1648348SEric.Yu@Sun.COM  * Data is available, so wake up anyone waiting for data.
1658348SEric.Yu@Sun.COM  */
1668348SEric.Yu@Sun.COM void
1678348SEric.Yu@Sun.COM so_notify_data(struct sonode *so, size_t qlen)
1688348SEric.Yu@Sun.COM {
1698348SEric.Yu@Sun.COM 	ASSERT(MUTEX_HELD(&so->so_lock));
1708348SEric.Yu@Sun.COM 
1718348SEric.Yu@Sun.COM 	SO_WAKEUP_READER(so);
1728348SEric.Yu@Sun.COM 
1738348SEric.Yu@Sun.COM 	if (IS_KERNEL_SOCKET(so)) {
1748348SEric.Yu@Sun.COM 		KSOCKET_CALLBACK(so, newdata, qlen);
1758348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
1768348SEric.Yu@Sun.COM 	} else {
1778348SEric.Yu@Sun.COM 		socket_sendsig(so, SOCKETSIG_READ);
1788348SEric.Yu@Sun.COM 		if (so->so_pollev & (SO_POLLEV_IN|SO_POLLEV_ALWAYS)) {
1798348SEric.Yu@Sun.COM 			so->so_pollev &= ~SO_POLLEV_IN;
1808348SEric.Yu@Sun.COM 			mutex_exit(&so->so_lock);
1818348SEric.Yu@Sun.COM 			pollwakeup(&so->so_poll_list, POLLIN|POLLRDNORM);
1828348SEric.Yu@Sun.COM 		} else {
1838348SEric.Yu@Sun.COM 			mutex_exit(&so->so_lock);
1848348SEric.Yu@Sun.COM 		}
1858348SEric.Yu@Sun.COM 	}
1868348SEric.Yu@Sun.COM 
1878348SEric.Yu@Sun.COM 	ASSERT(MUTEX_NOT_HELD(&so->so_lock));
1888348SEric.Yu@Sun.COM }
1898348SEric.Yu@Sun.COM 
1908348SEric.Yu@Sun.COM /*
1918348SEric.Yu@Sun.COM  * Transient error. Wake up anyone waiting to send or receive data.
1928348SEric.Yu@Sun.COM  */
1938348SEric.Yu@Sun.COM void
1948348SEric.Yu@Sun.COM so_notify_error(struct sonode *so)
1958348SEric.Yu@Sun.COM {
1968348SEric.Yu@Sun.COM 	ASSERT(MUTEX_HELD(&so->so_lock));
1978348SEric.Yu@Sun.COM 
1988348SEric.Yu@Sun.COM 	SO_WAKEUP_WRITER(so);
1998348SEric.Yu@Sun.COM 	SO_WAKEUP_READER(so);
2008348SEric.Yu@Sun.COM 
2018348SEric.Yu@Sun.COM 	if (IS_KERNEL_SOCKET(so)) {
2028348SEric.Yu@Sun.COM 		KSOCKET_CALLBACK(so, error, 0);
2038348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
2048348SEric.Yu@Sun.COM 	} else {
2058348SEric.Yu@Sun.COM 		socket_sendsig(so, SOCKETSIG_WRITE|SOCKETSIG_READ);
2068348SEric.Yu@Sun.COM 		so->so_pollev &= ~SO_POLLEV_IN;
2078348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
2088348SEric.Yu@Sun.COM 		pollwakeup(&so->so_poll_list, POLLOUT|POLLIN|POLLRDNORM);
2098348SEric.Yu@Sun.COM 	}
2108348SEric.Yu@Sun.COM 
2118348SEric.Yu@Sun.COM 	ASSERT(MUTEX_NOT_HELD(&so->so_lock));
2128348SEric.Yu@Sun.COM }
2138348SEric.Yu@Sun.COM 
2148348SEric.Yu@Sun.COM /*
2158348SEric.Yu@Sun.COM  * Out-of-band data is incoming, notify any interested parties.
2168348SEric.Yu@Sun.COM  */
2178348SEric.Yu@Sun.COM void
2188348SEric.Yu@Sun.COM so_notify_oobsig(struct sonode *so)
2198348SEric.Yu@Sun.COM {
2208348SEric.Yu@Sun.COM 	socket_sendsig(so, SOCKETSIG_URG);
2218348SEric.Yu@Sun.COM 	mutex_exit(&so->so_lock);
2228348SEric.Yu@Sun.COM 	pollwakeup(&so->so_poll_list, POLLRDBAND);
2238348SEric.Yu@Sun.COM }
2248348SEric.Yu@Sun.COM 
2258348SEric.Yu@Sun.COM /*
2268348SEric.Yu@Sun.COM  * Received out-of-band data. If the OOB data is delivered inline, then
2278348SEric.Yu@Sun.COM  * in addition of regular OOB notification, anyone waiting for normal
2288348SEric.Yu@Sun.COM  * data is also notified.
2298348SEric.Yu@Sun.COM  */
2308348SEric.Yu@Sun.COM void
2318348SEric.Yu@Sun.COM so_notify_oobdata(struct sonode *so, boolean_t oob_inline)
2328348SEric.Yu@Sun.COM {
2338348SEric.Yu@Sun.COM 	ASSERT(MUTEX_HELD(&so->so_lock));
2349491SAnders.Persson@Sun.COM 	if (so->so_direct != NULL)
2359491SAnders.Persson@Sun.COM 		SOD_UIOAFINI(so->so_direct);
2368348SEric.Yu@Sun.COM 
237*9752SAnders.Persson@Sun.COM 	SO_WAKEUP_READER(so);
238*9752SAnders.Persson@Sun.COM 
2398348SEric.Yu@Sun.COM 	if (IS_KERNEL_SOCKET(so)) {
2408348SEric.Yu@Sun.COM 		KSOCKET_CALLBACK(so, oobdata, 0);
2418348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
2428348SEric.Yu@Sun.COM 	} else {
2438348SEric.Yu@Sun.COM 		if (oob_inline) {
2448348SEric.Yu@Sun.COM 			socket_sendsig(so, SOCKETSIG_READ);
2458348SEric.Yu@Sun.COM 			so->so_pollev &= ~SO_POLLEV_IN;
2468348SEric.Yu@Sun.COM 			mutex_exit(&so->so_lock);
2478348SEric.Yu@Sun.COM 			pollwakeup(&so->so_poll_list,
2488348SEric.Yu@Sun.COM 			    POLLRDBAND|POLLIN|POLLRDNORM);
2498348SEric.Yu@Sun.COM 		} else {
2508348SEric.Yu@Sun.COM 			mutex_exit(&so->so_lock);
2518348SEric.Yu@Sun.COM 			pollwakeup(&so->so_poll_list, POLLRDBAND);
2528348SEric.Yu@Sun.COM 		}
2538348SEric.Yu@Sun.COM 	}
2548348SEric.Yu@Sun.COM 
2558348SEric.Yu@Sun.COM 	ASSERT(MUTEX_NOT_HELD(&so->so_lock));
2568348SEric.Yu@Sun.COM }
2578348SEric.Yu@Sun.COM 
2588348SEric.Yu@Sun.COM /*
2598348SEric.Yu@Sun.COM  * End-of-file has been reach, so peer will send no new data. Wake up
2608348SEric.Yu@Sun.COM  * anyone that is waiting for data.
2618348SEric.Yu@Sun.COM  */
2628348SEric.Yu@Sun.COM void
2638348SEric.Yu@Sun.COM so_notify_eof(struct sonode *so)
2648348SEric.Yu@Sun.COM {
2658348SEric.Yu@Sun.COM 	int pollev = 0;
2668348SEric.Yu@Sun.COM 	int sigev = 0;
2678348SEric.Yu@Sun.COM 
2688348SEric.Yu@Sun.COM 	ASSERT(MUTEX_HELD(&so->so_lock));
2698348SEric.Yu@Sun.COM 
2708348SEric.Yu@Sun.COM 	(void) i_so_notify_last_rx(so, &pollev, &sigev);
2718348SEric.Yu@Sun.COM 
2728348SEric.Yu@Sun.COM 	if (IS_KERNEL_SOCKET(so)) {
2738348SEric.Yu@Sun.COM 		SO_WAKEUP_READER(so);
2748348SEric.Yu@Sun.COM 		KSOCKET_CALLBACK(so, cantrecvmore, 0);
2758348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
2768348SEric.Yu@Sun.COM 	} else {
2778348SEric.Yu@Sun.COM 		if (sigev != 0)
2788348SEric.Yu@Sun.COM 			socket_sendsig(so, sigev);
2798348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
2808348SEric.Yu@Sun.COM 		if (pollev != 0)
2818348SEric.Yu@Sun.COM 			pollwakeup(&so->so_poll_list, pollev);
2828348SEric.Yu@Sun.COM 
2838348SEric.Yu@Sun.COM 	}
2848348SEric.Yu@Sun.COM 
2858348SEric.Yu@Sun.COM 	ASSERT(MUTEX_NOT_HELD(&so->so_lock));
2868348SEric.Yu@Sun.COM }
2878348SEric.Yu@Sun.COM 
2888348SEric.Yu@Sun.COM /*
2898348SEric.Yu@Sun.COM  * Wake up anyone waiting for a new connection.
2908348SEric.Yu@Sun.COM  */
2918348SEric.Yu@Sun.COM void
2928348SEric.Yu@Sun.COM so_notify_newconn(struct sonode *so)
2938348SEric.Yu@Sun.COM {
2948348SEric.Yu@Sun.COM 	ASSERT(MUTEX_HELD(&so->so_lock));
2958348SEric.Yu@Sun.COM 
2968348SEric.Yu@Sun.COM 	if (IS_KERNEL_SOCKET(so)) {
2978348SEric.Yu@Sun.COM 		KSOCKET_CALLBACK(so, newconn, so->so_rcv_queued);
2988348SEric.Yu@Sun.COM 		mutex_exit(&so->so_lock);
2998348SEric.Yu@Sun.COM 	} else {
3008348SEric.Yu@Sun.COM 		socket_sendsig(so, SOCKETSIG_READ);
3018348SEric.Yu@Sun.COM 		if (so->so_pollev & (SO_POLLEV_IN|SO_POLLEV_ALWAYS)) {
3028348SEric.Yu@Sun.COM 			so->so_pollev &= ~SO_POLLEV_IN;
3038348SEric.Yu@Sun.COM 			mutex_exit(&so->so_lock);
3048348SEric.Yu@Sun.COM 			pollwakeup(&so->so_poll_list, POLLIN|POLLRDNORM);
3058348SEric.Yu@Sun.COM 		} else {
3068348SEric.Yu@Sun.COM 			mutex_exit(&so->so_lock);
3078348SEric.Yu@Sun.COM 		}
3088348SEric.Yu@Sun.COM 	}
3098348SEric.Yu@Sun.COM 
3108348SEric.Yu@Sun.COM 	ASSERT(MUTEX_NOT_HELD(&so->so_lock));
3118348SEric.Yu@Sun.COM }
3128348SEric.Yu@Sun.COM 
3138348SEric.Yu@Sun.COM /*
3148348SEric.Yu@Sun.COM  * User initated shutdown/close, wake anyone that is trying to do
3158348SEric.Yu@Sun.COM  * an operation that is no longer possible.
3168348SEric.Yu@Sun.COM  */
3178348SEric.Yu@Sun.COM void
3188348SEric.Yu@Sun.COM so_notify_shutdown(struct sonode *so)
3198348SEric.Yu@Sun.COM {
3208348SEric.Yu@Sun.COM 	int pollev = 0;
3218348SEric.Yu@Sun.COM 	int sigev = 0;
3228348SEric.Yu@Sun.COM 
3238348SEric.Yu@Sun.COM 	ASSERT(MUTEX_HELD(&so->so_lock));
3248348SEric.Yu@Sun.COM 	ASSERT(so->so_state & (SS_CANTSENDMORE|SS_CANTRCVMORE));
3258348SEric.Yu@Sun.COM 
3268348SEric.Yu@Sun.COM 	if (so->so_state & SS_CANTSENDMORE)
3278348SEric.Yu@Sun.COM 		(void) i_so_notify_last_tx(so, &pollev, &sigev);
3288348SEric.Yu@Sun.COM 	if (so->so_state & SS_CANTRCVMORE)
3298348SEric.Yu@Sun.COM 		(void) i_so_notify_last_rx(so, &pollev, &sigev);
3308348SEric.Yu@Sun.COM 
3318348SEric.Yu@Sun.COM 	if (sigev != 0)
3328348SEric.Yu@Sun.COM 		socket_sendsig(so, sigev);
3338348SEric.Yu@Sun.COM 	mutex_exit(&so->so_lock);
3348348SEric.Yu@Sun.COM 	if (pollev != 0)
3358348SEric.Yu@Sun.COM 		pollwakeup(&so->so_poll_list, pollev);
3368348SEric.Yu@Sun.COM 
3378348SEric.Yu@Sun.COM 	ASSERT(MUTEX_NOT_HELD(&so->so_lock));
3388348SEric.Yu@Sun.COM }
3398348SEric.Yu@Sun.COM 
3408348SEric.Yu@Sun.COM /*
3418348SEric.Yu@Sun.COM  * No more data will be coming in, and this will be the last notification
3428348SEric.Yu@Sun.COM  * made.
3438348SEric.Yu@Sun.COM  */
3448348SEric.Yu@Sun.COM static int
3458348SEric.Yu@Sun.COM i_so_notify_last_rx(struct sonode *so, int *pollev, int *sigev)
3468348SEric.Yu@Sun.COM {
3478348SEric.Yu@Sun.COM 	if (!(so->so_state & SS_SENTLASTREADSIG)) {
3488348SEric.Yu@Sun.COM 		SOCKET_TIMER_CANCEL(so);
3498348SEric.Yu@Sun.COM 		SO_WAKEUP_READER(so);
3508348SEric.Yu@Sun.COM 		so->so_state |= SS_SENTLASTREADSIG;
3518348SEric.Yu@Sun.COM 		so->so_pollev &= ~SO_POLLEV_IN;
3528348SEric.Yu@Sun.COM 
3538348SEric.Yu@Sun.COM 		*pollev |= POLLIN|POLLRDNORM;
3548348SEric.Yu@Sun.COM 		*sigev |= SOCKETSIG_READ;
3558348SEric.Yu@Sun.COM 
3568348SEric.Yu@Sun.COM 		return (1);
3578348SEric.Yu@Sun.COM 	} else {
3588348SEric.Yu@Sun.COM 		return (0);
3598348SEric.Yu@Sun.COM 	}
3608348SEric.Yu@Sun.COM }
3618348SEric.Yu@Sun.COM 
3628348SEric.Yu@Sun.COM /*
3638348SEric.Yu@Sun.COM  * The socket is un-writeable. Make one last notification.
3648348SEric.Yu@Sun.COM  */
3658348SEric.Yu@Sun.COM static int
3668348SEric.Yu@Sun.COM i_so_notify_last_tx(struct sonode *so, int *pollev, int *sigev)
3678348SEric.Yu@Sun.COM {
3688348SEric.Yu@Sun.COM 	if (!(so->so_state & SS_SENTLASTWRITESIG)) {
3698348SEric.Yu@Sun.COM 		SO_WAKEUP_WRITER(so);
3708348SEric.Yu@Sun.COM 		so->so_state |= SS_SENTLASTWRITESIG;
3718348SEric.Yu@Sun.COM 
3728348SEric.Yu@Sun.COM 		*pollev |= POLLOUT;
3738348SEric.Yu@Sun.COM 		*sigev |= SOCKETSIG_WRITE;
3748348SEric.Yu@Sun.COM 
3758348SEric.Yu@Sun.COM 		return (1);
3768348SEric.Yu@Sun.COM 	} else {
3778348SEric.Yu@Sun.COM 		return (0);
3788348SEric.Yu@Sun.COM 	}
3798348SEric.Yu@Sun.COM }
380