From: Nickolai Zeldovich Date: Wed, 14 Nov 2001 04:02:27 +0000 (+0000) Subject: rx-fix-resource-starvation-problem-20011113 X-Git-Tag: openafs-devel-1_3_0~125 X-Git-Url: https://git.openafs.org/?p=openafs.git;a=commitdiff_plain;h=54f065005264764f30ea44541d0b7eb5c3965d6a 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. --- diff --git a/src/rx/rx.c b/src/rx/rx.c index 1a503e3..ea98ff2 100644 --- a/src/rx/rx.c +++ b/src/rx/rx.c @@ -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; icall[i]; @@ -1030,11 +1045,24 @@ 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 } CALL_HOLD(call, RX_CALL_REFCOUNT_BEGIN); diff --git a/src/rx/rx.h b/src/rx/rx.h index a8d27bb..b85c279 100644 --- a/src/rx/rx.h +++ b/src/rx/rx.h @@ -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 */ };