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