* waiting, treat this as a running call, and wait to destroy the
* connection later when the call completes. */
if ((conn->type == RX_CLIENT_CONNECTION)
- && (conn->flags & RX_CONN_MAKECALL_WAITING)) {
+ && (conn->flags & (RX_CONN_MAKECALL_WAITING|RX_CONN_MAKECALL_ACTIVE))) {
conn->flags |= RX_CONN_DESTROY_ME;
MUTEX_EXIT(&conn->conn_data_lock);
USERPRI;
*/
MUTEX_ENTER(&conn->conn_call_lock);
MUTEX_ENTER(&conn->conn_data_lock);
- if (conn->makeCallWaiters) {
+ while (conn->flags & RX_CONN_MAKECALL_ACTIVE) {
+ conn->flags |= RX_CONN_MAKECALL_WAITING;
conn->makeCallWaiters++;
MUTEX_EXIT(&conn->conn_data_lock);
if (conn->makeCallWaiters == 0)
conn->flags &= ~RX_CONN_MAKECALL_WAITING;
}
+
+ /* We are now the active thread in rx_NewCall */
+ conn->flags |= RX_CONN_MAKECALL_ACTIVE;
MUTEX_EXIT(&conn->conn_data_lock);
for (;;) {
* effect on overall system performance.
*/
call->state = RX_STATE_RESET;
+ CALL_HOLD(call, RX_CALL_REFCOUNT_BEGIN);
MUTEX_EXIT(&conn->conn_call_lock);
rxi_ResetCall(call, 0);
(*call->callNumber)++;
MUTEX_EXIT(&call->lock);
MUTEX_ENTER(&conn->conn_call_lock);
MUTEX_ENTER(&call->lock);
+
if (call->state == RX_STATE_RESET)
break;
* Instead, cycle through one more time to see if
* we can find a call that can call our own.
*/
+ CALL_RELE(call, RX_CALL_REFCOUNT_BEGIN);
wait = 0;
}
MUTEX_EXIT(&call->lock);
} else {
/* rxi_NewCall returns with mutex locked */
call = rxi_NewCall(conn, i);
+ CALL_HOLD(call, RX_CALL_REFCOUNT_BEGIN);
break;
}
}
conn->flags &= ~RX_CONN_MAKECALL_WAITING;
MUTEX_EXIT(&conn->conn_data_lock);
}
- /*
- * Wake up anyone else who might be giving us a chance to
- * run (see code above that avoids resource starvation).
- */
-#ifdef RX_ENABLE_LOCKS
- CV_BROADCAST(&conn->conn_call_cv);
-#else
- osi_rxWakeup(conn);
-#endif
-
- CALL_HOLD(call, RX_CALL_REFCOUNT_BEGIN);
-
/* Client is initially in send mode */
call->state = RX_STATE_ACTIVE;
call->error = conn->error;
/* Turn on busy protocol. */
rxi_KeepAliveOn(call);
+
+ /*
+ * We are no longer the active thread in rx_NewCall
+ */
+ MUTEX_ENTER(&conn->conn_data_lock);
+ conn->flags &= ~RX_CONN_MAKECALL_ACTIVE;
+ MUTEX_EXIT(&conn->conn_data_lock);
+
+ /*
+ * Wake up anyone else who might be giving us a chance to
+ * run (see code above that avoids resource starvation).
+ */
+#ifdef RX_ENABLE_LOCKS
+ CV_BROADCAST(&conn->conn_call_cv);
+#else
+ osi_rxWakeup(conn);
+#endif
MUTEX_EXIT(&conn->conn_call_lock);
#ifdef AFS_GLOBAL_RXLOCK_KERNEL
#ifndef KDUMP_RX_LOCK
/* Flag bits for connection structure */
-#define RX_CONN_MAKECALL_WAITING 1 /* rx_MakeCall is waiting for a channel */
+#define RX_CONN_MAKECALL_WAITING 1 /* rx_NewCall is waiting for a channel */
#define RX_CONN_DESTROY_ME 2 /* Destroy *client* connection after last call */
#define RX_CONN_USING_PACKET_CKSUM 4 /* non-zero header.spare field seen */
#define RX_CONN_KNOW_WINDOW 8 /* window size negotiation works */
#define RX_CONN_RESET 16 /* connection is reset, remove */
#define RX_CONN_BUSY 32 /* connection is busy; don't delete */
#define RX_CONN_ATTACHWAIT 64 /* attach waiting for peer->lastReach */
+#define RX_CONN_MAKECALL_ACTIVE 128 /* a thread is actively in rx_NewCall */
/* Type of connection, client or server */
#define RX_CLIENT_CONNECTION 0