diff options
author | Anders Persson <Anders.Persson@Sun.COM> | 2010-05-27 11:32:10 -0700 |
---|---|---|
committer | Anders Persson <Anders.Persson@Sun.COM> | 2010-05-27 11:32:10 -0700 |
commit | 9ee3959a9e59422575d29f2ec8ffb62ce0918ac8 (patch) | |
tree | 88a68f13218d9017fd8359af2639c4dbe8e10b01 /usr | |
parent | 05f9a513b6ce84a1c8ebdc256737b1e8bd5ea049 (diff) | |
download | illumos-gate-9ee3959a9e59422575d29f2ec8ffb62ce0918ac8.tar.gz |
6846669 squeue_synch_{enter,exit}() are unaware of squeue switching
Diffstat (limited to 'usr')
-rw-r--r-- | usr/src/uts/common/inet/squeue.c | 27 | ||||
-rw-r--r-- | usr/src/uts/common/inet/tcp/tcp_socket.c | 40 | ||||
-rw-r--r-- | usr/src/uts/common/sys/squeue.h | 7 |
3 files changed, 42 insertions, 32 deletions
diff --git a/usr/src/uts/common/inet/squeue.c b/usr/src/uts/common/inet/squeue.c index a58b445158..6d0bf70b2a 100644 --- a/usr/src/uts/common/inet/squeue.c +++ b/usr/src/uts/common/inet/squeue.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -1383,8 +1382,13 @@ squeue_wakeup_conn(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *dummy) } int -squeue_synch_enter(squeue_t *sqp, conn_t *connp, mblk_t *use_mp) +squeue_synch_enter(conn_t *connp, mblk_t *use_mp) { + squeue_t *sqp; + +again: + sqp = connp->conn_sqp; + mutex_enter(&sqp->sq_lock); if (sqp->sq_first == NULL && !(sqp->sq_state & SQS_PROC)) { /* @@ -1400,6 +1404,19 @@ squeue_synch_enter(squeue_t *sqp, conn_t *connp, mblk_t *use_mp) sqp->sq_run = curthread; mutex_exit(&sqp->sq_lock); + /* + * Handle squeue switching. The conn's squeue can only change + * while there is a thread in the squeue, which is why we do + * the check after entering the squeue. If it has changed, exit + * this squeue and redo everything with the new sqeueue. + */ + if (sqp != connp->conn_sqp) { + mutex_enter(&sqp->sq_lock); + sqp->sq_state &= ~SQS_PROC; + sqp->sq_run = NULL; + mutex_exit(&sqp->sq_lock); + goto again; + } #if SQUEUE_DEBUG sqp->sq_curmp = NULL; sqp->sq_curproc = NULL; @@ -1443,8 +1460,10 @@ squeue_synch_enter(squeue_t *sqp, conn_t *connp, mblk_t *use_mp) } void -squeue_synch_exit(squeue_t *sqp, conn_t *connp) +squeue_synch_exit(conn_t *connp) { + squeue_t *sqp = connp->conn_sqp; + mutex_enter(&sqp->sq_lock); if (sqp->sq_run == curthread) { ASSERT(sqp->sq_state & SQS_PROC); diff --git a/usr/src/uts/common/inet/tcp/tcp_socket.c b/usr/src/uts/common/inet/tcp/tcp_socket.c index 7f96a851ef..4b50c65cc6 100644 --- a/usr/src/uts/common/inet/tcp/tcp_socket.c +++ b/usr/src/uts/common/inet/tcp/tcp_socket.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ /* This file contains all TCP kernel socket related functions. */ @@ -156,15 +155,12 @@ tcp_bind(sock_lower_handle_t proto_handle, struct sockaddr *sa, { int error; conn_t *connp = (conn_t *)proto_handle; - squeue_t *sqp = connp->conn_sqp; /* All Solaris components should pass a cred for this operation. */ ASSERT(cr != NULL); - - ASSERT(sqp != NULL); ASSERT(connp->conn_upper_handle != NULL); - error = squeue_synch_enter(sqp, connp, NULL); + error = squeue_synch_enter(connp, NULL); if (error != 0) { /* failed to enter */ return (ENOSR); @@ -180,7 +176,7 @@ tcp_bind(sock_lower_handle_t proto_handle, struct sockaddr *sa, error = tcp_do_bind(connp, sa, len, cr, B_TRUE); } - squeue_synch_exit(sqp, connp); + squeue_synch_exit(connp); if (error < 0) { if (error == -TOUTSTATE) @@ -201,14 +197,13 @@ tcp_listen(sock_lower_handle_t proto_handle, int backlog, cred_t *cr) { conn_t *connp = (conn_t *)proto_handle; int error; - squeue_t *sqp = connp->conn_sqp; ASSERT(connp->conn_upper_handle != NULL); /* All Solaris components should pass a cred for this operation. */ ASSERT(cr != NULL); - error = squeue_synch_enter(sqp, connp, NULL); + error = squeue_synch_enter(connp, NULL); if (error != 0) { /* failed to enter */ return (ENOBUFS); @@ -224,7 +219,7 @@ tcp_listen(sock_lower_handle_t proto_handle, int backlog, cred_t *cr) else error = proto_tlitosyserr(-error); } - squeue_synch_exit(sqp, connp); + squeue_synch_exit(connp); return (error); } @@ -233,7 +228,6 @@ tcp_connect(sock_lower_handle_t proto_handle, const struct sockaddr *sa, socklen_t len, sock_connid_t *id, cred_t *cr) { conn_t *connp = (conn_t *)proto_handle; - squeue_t *sqp = connp->conn_sqp; int error; ASSERT(connp->conn_upper_handle != NULL); @@ -246,7 +240,7 @@ tcp_connect(sock_lower_handle_t proto_handle, const struct sockaddr *sa, return (error); } - error = squeue_synch_enter(sqp, connp, NULL); + error = squeue_synch_enter(connp, NULL); if (error != 0) { /* failed to enter */ return (ENOSR); @@ -289,7 +283,7 @@ tcp_connect(sock_lower_handle_t proto_handle, const struct sockaddr *sa, connp->conn_upper_handle, &sopp); } done: - squeue_synch_exit(sqp, connp); + squeue_synch_exit(connp); return ((error == 0) ? EINPROGRESS : error); } @@ -333,7 +327,6 @@ tcp_getsockopt(sock_lower_handle_t proto_handle, int level, int option_name, void *optvalp, socklen_t *optlen, cred_t *cr) { conn_t *connp = (conn_t *)proto_handle; - squeue_t *sqp = connp->conn_sqp; int error; t_uscalar_t max_optbuf_len; void *optvalp_buf; @@ -354,14 +347,14 @@ tcp_getsockopt(sock_lower_handle_t proto_handle, int level, int option_name, optvalp_buf = kmem_alloc(max_optbuf_len, KM_SLEEP); - error = squeue_synch_enter(sqp, connp, NULL); + error = squeue_synch_enter(connp, NULL); if (error == ENOMEM) { kmem_free(optvalp_buf, max_optbuf_len); return (ENOMEM); } len = tcp_opt_get(connp, level, option_name, optvalp_buf); - squeue_synch_exit(sqp, connp); + squeue_synch_exit(connp); if (len == -1) { kmem_free(optvalp_buf, max_optbuf_len); @@ -385,7 +378,6 @@ tcp_setsockopt(sock_lower_handle_t proto_handle, int level, int option_name, const void *optvalp, socklen_t optlen, cred_t *cr) { conn_t *connp = (conn_t *)proto_handle; - squeue_t *sqp = connp->conn_sqp; int error; ASSERT(connp->conn_upper_handle != NULL); @@ -409,7 +401,7 @@ tcp_setsockopt(sock_lower_handle_t proto_handle, int level, int option_name, } } - error = squeue_synch_enter(sqp, connp, NULL); + error = squeue_synch_enter(connp, NULL); if (error == ENOMEM) { return (ENOMEM); } @@ -423,14 +415,14 @@ tcp_setsockopt(sock_lower_handle_t proto_handle, int level, int option_name, if (error < 0) { error = proto_tlitosyserr(-error); } - squeue_synch_exit(sqp, connp); + squeue_synch_exit(connp); return (error); } error = tcp_opt_set(connp, SETFN_OPTCOM_NEGOTIATE, level, option_name, optlen, (uchar_t *)optvalp, (uint_t *)&optlen, (uchar_t *)optvalp, NULL, cr); - squeue_synch_exit(sqp, connp); + squeue_synch_exit(connp); ASSERT(error >= 0); @@ -581,7 +573,7 @@ tcp_clr_flowctrl(sock_lower_handle_t proto_handle) tcp->tcp_rsrv_mp = NULL; mutex_exit(&tcp->tcp_rsrv_mp_lock); - error = squeue_synch_enter(connp->conn_sqp, connp, mp); + error = squeue_synch_enter(connp, mp); ASSERT(error == 0); mutex_enter(&tcp->tcp_rsrv_mp_lock); @@ -606,7 +598,7 @@ tcp_clr_flowctrl(sock_lower_handle_t proto_handle) } } - squeue_synch_exit(connp->conn_sqp, connp); + squeue_synch_exit(connp); } /* ARGSUSED */ @@ -771,7 +763,7 @@ tcp_fallback(sock_lower_handle_t proto_handle, queue_t *q, /* * Enter the squeue so that no new packets can come in */ - error = squeue_synch_enter(connp->conn_sqp, connp, NULL); + error = squeue_synch_enter(connp, NULL); if (error != 0) { /* failed to enter, free all the pre-allocated messages. */ freeb(stropt_mp); @@ -814,7 +806,7 @@ tcp_fallback(sock_lower_handle_t proto_handle, queue_t *q, * There should be atleast two ref's (IP + TCP) */ ASSERT(connp->conn_ref >= 2); - squeue_synch_exit(connp->conn_sqp, connp); + squeue_synch_exit(connp); return (0); } diff --git a/usr/src/uts/common/sys/squeue.h b/usr/src/uts/common/sys/squeue.h index de0f18bd4d..f1bd429815 100644 --- a/usr/src/uts/common/sys/squeue.h +++ b/usr/src/uts/common/sys/squeue.h @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _SYS_SQUEUE_H @@ -85,8 +84,8 @@ extern void squeue_enter(squeue_t *, mblk_t *, mblk_t *, extern uintptr_t *squeue_getprivate(squeue_t *, sqprivate_t); struct conn_s; -extern int squeue_synch_enter(squeue_t *, struct conn_s *, mblk_t *); -extern void squeue_synch_exit(squeue_t *, struct conn_s *); +extern int squeue_synch_enter(struct conn_s *, mblk_t *); +extern void squeue_synch_exit(struct conn_s *); #ifdef __cplusplus } |