summaryrefslogtreecommitdiff
path: root/usr
diff options
context:
space:
mode:
authorAnders Persson <Anders.Persson@Sun.COM>2010-05-27 11:32:10 -0700
committerAnders Persson <Anders.Persson@Sun.COM>2010-05-27 11:32:10 -0700
commit9ee3959a9e59422575d29f2ec8ffb62ce0918ac8 (patch)
tree88a68f13218d9017fd8359af2639c4dbe8e10b01 /usr
parent05f9a513b6ce84a1c8ebdc256737b1e8bd5ea049 (diff)
downloadillumos-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.c27
-rw-r--r--usr/src/uts/common/inet/tcp/tcp_socket.c40
-rw-r--r--usr/src/uts/common/sys/squeue.h7
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
}