rx-fix-resource-starvation-problem-20011113

This patch fixes a resource starvation condition in Rx.  The
  problem arises, for instance, when more than 4 daemons try to
  prefetch chunks of the same file at once.  The fifth daemon is
  stuck in MAKECALL_WAITING state, never getting a chance to run,
  because the other 4 daemons never yield to the scheduler after
  releasing the call, and just grab the call back again.
This commit is contained in:
Nickolai Zeldovich 2001-11-14 04:02:27 +00:00 committed by Derrick Brashear
parent 94bc1753e9
commit 54f0650052
2 changed files with 29 additions and 0 deletions

View File

@ -1006,6 +1006,21 @@ struct rx_call *rx_NewCall(conn)
clock_GetTime(&queueTime);
AFS_RXGLOCK();
MUTEX_ENTER(&conn->conn_call_lock);
/*
* Check if there are others waiting for a new call.
* If so, let them go first to avoid starving them.
* This is a fairly simple scheme, and might not be
* a complete solution for large numbers of waiters.
*/
if (conn->makeCallWaiters) {
#ifdef RX_ENABLE_LOCKS
CV_WAIT(&conn->conn_call_cv, &conn->conn_call_lock);
#else
osi_rxSleep(conn);
#endif
}
for (;;) {
for (i=0; i<RX_MAXCALLS; i++) {
call = conn->call[i];
@ -1030,10 +1045,23 @@ struct rx_call *rx_NewCall(conn)
MUTEX_ENTER(&conn->conn_data_lock);
conn->flags |= RX_CONN_MAKECALL_WAITING;
MUTEX_EXIT(&conn->conn_data_lock);
conn->makeCallWaiters++;
#ifdef RX_ENABLE_LOCKS
CV_WAIT(&conn->conn_call_cv, &conn->conn_call_lock);
#else
osi_rxSleep(conn);
#endif
conn->makeCallWaiters--;
/*
* 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
}

View File

@ -506,6 +506,7 @@ struct rx_connection {
u_short secondsUntilDead; /* Maximum silence from peer before RX_CALL_DEAD */
u_short hardDeadTime; /* hard max for call execution */
u_char ackRate; /* how many packets between ack requests */
u_char makeCallWaiters; /* how many rx_NewCalls are waiting */
int nSpecific; /* number entries in specific data */
void **specific; /* pointer to connection specific data */
};