diff options
-rw-r--r-- | src/core/lib/iomgr/resource_quota.c | 35 |
1 files changed, 30 insertions, 5 deletions
diff --git a/src/core/lib/iomgr/resource_quota.c b/src/core/lib/iomgr/resource_quota.c index 511ffdcdf1..3a0fd5d81a 100644 --- a/src/core/lib/iomgr/resource_quota.c +++ b/src/core/lib/iomgr/resource_quota.c @@ -246,7 +246,8 @@ static void rulist_remove(grpc_resource_user *resource_user, grpc_rulist list) { */ static bool rq_alloc(grpc_exec_ctx *exec_ctx, - grpc_resource_quota *resource_quota); + grpc_resource_quota *resource_quota, + bool check_memory_usage); static bool rq_reclaim_from_per_user_free_pool( grpc_exec_ctx *exec_ctx, grpc_resource_quota *resource_quota); static bool rq_reclaim(grpc_exec_ctx *exec_ctx, @@ -256,11 +257,20 @@ static void rq_step(grpc_exec_ctx *exec_ctx, void *rq, grpc_error *error) { grpc_resource_quota *resource_quota = rq; resource_quota->step_scheduled = false; do { - if (rq_alloc(exec_ctx, resource_quota)) goto done; + if (rq_alloc(exec_ctx, resource_quota, false)) goto done; } while (rq_reclaim_from_per_user_free_pool(exec_ctx, resource_quota)); if (!rq_reclaim(exec_ctx, resource_quota, false)) { - rq_reclaim(exec_ctx, resource_quota, true); + if (!rq_reclaim(exec_ctx, resource_quota, true)) { + /* no reclaimation possible, but we've still got allocation requests: + start satisfying them without regard to memory utilization to avoid + infinitely stuck requests */ + gpr_log(GPR_DEBUG, + "ResourceQuota WARNING: allocating requests without free pool " + "available"); + while (!rq_alloc(exec_ctx, resource_quota, true)) + ; + } } done: @@ -286,15 +296,22 @@ static void rq_update_estimate(grpc_resource_quota *resource_quota) { MEMORY_USAGE_ESTIMATION_MAX)); } +static bool fits_pool(int64_t want, int64_t have, bool check) { + if (!check) return true; + return want <= have; +} + /* returns true if all allocations are completed */ static bool rq_alloc(grpc_exec_ctx *exec_ctx, - grpc_resource_quota *resource_quota) { + grpc_resource_quota *resource_quota, + bool check_memory_usage) { grpc_resource_user *resource_user; while ((resource_user = rulist_pop_head(resource_quota, GRPC_RULIST_AWAITING_ALLOCATION))) { gpr_mu_lock(&resource_user->mu); if (resource_user->free_pool < 0 && - -resource_user->free_pool <= resource_quota->free_pool) { + fits_pool(-resource_user->free_pool, resource_quota->free_pool, + check_memory_usage)) { int64_t amt = -resource_user->free_pool; resource_user->free_pool = 0; resource_quota->free_pool -= amt; @@ -314,6 +331,11 @@ static bool rq_alloc(grpc_exec_ctx *exec_ctx, grpc_closure_list_sched(exec_ctx, &resource_user->on_allocated); gpr_mu_unlock(&resource_user->mu); } else { + gpr_log(GPR_DEBUG, "RQ %s %s: delay alloc %" PRId64 + " bytes; rq_free_pool = %" PRId64, + resource_quota->name, resource_user->name, + -resource_user->free_pool, resource_quota->free_pool); + GPR_ASSERT(check_memory_usage); rulist_add_head(resource_user, GRPC_RULIST_AWAITING_ALLOCATION); gpr_mu_unlock(&resource_user->mu); return false; @@ -333,6 +355,9 @@ static bool rq_reclaim_from_per_user_free_pool( int64_t amt = resource_user->free_pool; resource_user->free_pool = 0; resource_quota->free_pool += amt; + if (resource_quota->free_pool > resource_quota->size) { + resource_quota->free_pool = resource_quota->size; + } rq_update_estimate(resource_quota); if (grpc_resource_quota_trace) { gpr_log(GPR_DEBUG, "RQ %s %s: reclaim_from_per_user_free_pool %" PRId64 |