* effect on overall system performance.
*/
call->state = RX_STATE_RESET;
+ CALL_HOLD(call, RX_CALL_REFCOUNT_BEGIN);
+ (*call->callNumber)++;
MUTEX_EXIT(&conn->conn_call_lock);
CALL_HOLD(call, RX_CALL_REFCOUNT_BEGIN);
rxi_ResetCall(call, 0);
- (*call->callNumber)++;
if (MUTEX_TRYENTER(&conn->conn_call_lock))
break;
SPLVAR;
NETPRI;
+ MUTEX_ENTER(&aconn->conn_call_lock);
for (i = 0; i < RX_MAXCALLS; i++) {
if ((tcall = aconn->call[i]) && (tcall->state == RX_STATE_DALLY))
aint32s[i] = aconn->callNumber[i] + 1;
else
aint32s[i] = aconn->callNumber[i];
}
+ MUTEX_EXIT(&aconn->conn_call_lock);
USERPRI;
return 0;
}
SPLVAR;
NETPRI;
+ MUTEX_ENTER(&aconn->conn_call_lock);
for (i = 0; i < RX_MAXCALLS; i++) {
if ((tcall = aconn->call[i]) && (tcall->state == RX_STATE_DALLY))
aconn->callNumber[i] = aint32s[i] - 1;
else
aconn->callNumber[i] = aint32s[i];
}
+ MUTEX_EXIT(&aconn->conn_call_lock);
USERPRI;
return 0;
}
*
* call->lock amd rx_refcnt_mutex are held upon entry.
* haveCTLock is set when called from rxi_ReapConnections.
+ *
+ * return 1 if the call is freed, 0 if not.
*/
-static void
+static int
rxi_FreeCall(struct rx_call *call, int haveCTLock)
{
int channel = call->channel;
struct rx_connection *conn = call->conn;
+ u_char state = call->state;
-
- if (call->state == RX_STATE_DALLY || call->state == RX_STATE_HOLD)
- (*call->callNumber)++;
/*
* We are setting the state to RX_STATE_RESET to
* ensure that no one else will attempt to use this
MUTEX_EXIT(&rx_refcnt_mutex);
rxi_ResetCall(call, 0);
- MUTEX_ENTER(&conn->conn_call_lock);
- if (call->conn->call[channel] == call)
- call->conn->call[channel] = 0;
- MUTEX_EXIT(&conn->conn_call_lock);
+ if (MUTEX_TRYENTER(&conn->conn_call_lock))
+ {
+ if (state == RX_STATE_DALLY || state == RX_STATE_HOLD)
+ (*call->callNumber)++;
+
+ if (call->conn->call[channel] == call)
+ call->conn->call[channel] = 0;
+ MUTEX_EXIT(&conn->conn_call_lock);
+ } else {
+ /*
+ * We couldn't obtain the conn_call_lock so we can't
+ * disconnect the call from the connection. Set the
+ * call state to dally so that the call can be reused.
+ */
+ MUTEX_ENTER(&rx_refcnt_mutex);
+ call->state = RX_STATE_DALLY;
+ return 0;
+ }
MUTEX_ENTER(&rx_freeCallQueue_lock);
SET_CALL_QUEUE_LOCK(call, &rx_freeCallQueue_lock);
MUTEX_EXIT(&conn->conn_data_lock);
}
MUTEX_ENTER(&rx_refcnt_mutex);
+ return 1;
}
rx_atomic_t rxi_Allocsize = RX_ATOMIC_INIT(0);
int channel = call->channel;
int freechannel = 0;
int i;
- afs_uint32 callNumber = *call->callNumber;
+ afs_uint32 callNumber;
MUTEX_EXIT(&call->lock);
MUTEX_ENTER(&conn->conn_call_lock);
+ callNumber = *call->callNumber;
/* Are there any other call slots on this conn that we should try? Look for
* slots that are empty and are either non-busy, or were marked as busy
}
}
- MUTEX_EXIT(&conn->conn_call_lock);
-
MUTEX_ENTER(&call->lock);
/* Since the call->lock and conn->conn_call_lock have been released it is
rxi_CallError(call, RX_CALL_BUSY);
}
+ MUTEX_EXIT(&conn->conn_call_lock);
}
/* There are two packet tracing routines available for testing and monitoring
}
channel = np->header.cid & RX_CHANNELMASK;
+ MUTEX_ENTER(&conn->conn_call_lock);
call = conn->call[channel];
if (call) {
MUTEX_ENTER(&call->lock);
currentCallNumber = conn->callNumber[channel];
+ MUTEX_EXIT(&conn->conn_call_lock);
} else if (type == RX_SERVER_CONNECTION) { /* No call allocated */
- MUTEX_ENTER(&conn->conn_call_lock);
call = conn->call[channel];
if (call) {
MUTEX_ENTER(&call->lock);
- MUTEX_EXIT(&conn->conn_call_lock);
currentCallNumber = conn->callNumber[channel];
+ MUTEX_EXIT(&conn->conn_call_lock);
} else {
call = rxi_NewCall(conn, channel); /* returns locked call */
- MUTEX_EXIT(&conn->conn_call_lock);
*call->callNumber = currentCallNumber = np->header.callNumber;
+ MUTEX_EXIT(&conn->conn_call_lock);
#ifdef RXDEBUG
if (np->header.callNumber == 0)
dpf(("RecPacket call 0 %d %s: %x.%u.%u.%u.%u.%u.%u flags %d, packet %"AFS_PTR_FMT" len %d\n",
return tp;
}
rxi_ResetCall(call, 0);
+ /*
+ * The conn_call_lock is not held but no one else should be
+ * using this call channel while we are processing this incoming
+ * packet. This assignment should be safe.
+ */
*call->callNumber = np->header.callNumber;
#ifdef RXDEBUG
if (np->header.callNumber == 0)
rxevent_Cancel(&call->growMTUEvent, call,
RX_CALL_REFCOUNT_ALIVE);
MUTEX_ENTER(&rx_refcnt_mutex);
- if (call->refCount == 0) {
- rxi_FreeCall(call, haveCTLock);
+ /* if rxi_FreeCall returns 1 it has freed the call */
+ if (call->refCount == 0 &&
+ rxi_FreeCall(call, haveCTLock))
+ {
MUTEX_EXIT(&rx_refcnt_mutex);
- return -2;
+ return -2;
}
MUTEX_EXIT(&rx_refcnt_mutex);
return -1;