From owner-svn-soc-all@FreeBSD.ORG Sun Aug 5 21:32:54 2012 Return-Path: Delivered-To: svn-soc-all@FreeBSD.org Received: from socsvn.FreeBSD.org (unknown [IPv6:2001:4f8:fff6::2f]) by hub.freebsd.org (Postfix) with SMTP id 55BE5106564A for ; Sun, 5 Aug 2012 21:32:52 +0000 (UTC) (envelope-from rudot@FreeBSD.org) Received: by socsvn.FreeBSD.org (sSMTP sendmail emulation); Sun, 05 Aug 2012 21:32:52 +0000 Date: Sun, 05 Aug 2012 21:32:52 +0000 From: rudot@FreeBSD.org To: svn-soc-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Message-Id: <20120805213252.55BE5106564A@hub.freebsd.org> Cc: Subject: socsvn commit: r240116 - in soc2012/rudot/sys: kern sys X-BeenThere: svn-soc-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the entire Summer of Code repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 05 Aug 2012 21:32:54 -0000 Author: rudot Date: Sun Aug 5 21:32:51 2012 New Revision: 240116 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=240116 Log: when limiting %cpu, we act sooner than the limits are exceeded already. This makes exceeding %cpu limits less likely Modified: soc2012/rudot/sys/kern/kern_racct.c soc2012/rudot/sys/kern/kern_rctl.c soc2012/rudot/sys/sys/rctl.h Modified: soc2012/rudot/sys/kern/kern_racct.c ============================================================================== --- soc2012/rudot/sys/kern/kern_racct.c Sun Aug 5 20:19:27 2012 (r240115) +++ soc2012/rudot/sys/kern/kern_racct.c Sun Aug 5 21:32:51 2012 (r240116) @@ -66,8 +66,19 @@ FEATURE(racct, "Resource Accounting"); +/* + * Do not block processes that have their %cpu usage <= RACCT_PCTCPU_IGNORE + */ #define RACCT_PCTCPU_IGNORE 1 +/* + * How many seconds it takes to use the scheduler %cpu calculations. When a + * process starts, we compute its %cpu usage by dividing its runtime by the + * process wall clock time. After RACCT_PCPU_SECS pass, we use the value + * provided by the scheduler. + */ +#define RACCT_PCPU_SECS 3 + struct mtx racct_lock; MTX_SYSINIT(racct_lock, &racct_lock, "racct lock", MTX_DEF); @@ -298,7 +309,7 @@ swtime = (ticks - p->p_swtick) / hz; if ((swtime == 0) || ((p->p_flag & P_INMEM) == 0)) return (0); - if (swtime < 20) { + if (swtime < RACCT_PCPU_SECS) { /* * For short-lived processes, the sched_pctcpu() returns small * values even for cpu intensive processes. Therefore we use @@ -568,8 +579,7 @@ static int racct_set_check_locked(struct proc *p, int resource, uint64_t amount) { - int64_t diff; - int over_limit; + int64_t diff, available; SDT_PROBE(racct, kernel, rusage, set, p, resource, amount, 0, 0); @@ -587,9 +597,9 @@ ("racct_set: usage of non-reclaimable resource %d dropping", resource)); #endif - over_limit = 0; + available = INT64_MAX; #ifdef RCTL - over_limit = rctl_over_limit(p, resource, diff); + available = rctl_pcpu_available(p); #endif racct_alloc_resource(p->p_racct, resource, diff); if (diff > 0) @@ -597,7 +607,7 @@ else if (diff < 0) racct_sub_cred_locked(p->p_ucred, resource, -diff); - return (over_limit); + return (available <= diff); } static int @@ -1052,7 +1062,8 @@ wallclock.tv_usec); pct = racct_getpcpu(p, pct_estimate); mtx_lock(&racct_lock); - over_limits = racct_set_check_locked(p, RACCT_PCTCPU, pct); + over_limits = racct_set_check_locked(p, RACCT_PCTCPU, + pct); if (over_limits) { racct_proc_disable(p); } else if (racct_proc_disabled(p)) { Modified: soc2012/rudot/sys/kern/kern_rctl.c ============================================================================== --- soc2012/rudot/sys/kern/kern_rctl.c Sun Aug 5 20:19:27 2012 (r240115) +++ soc2012/rudot/sys/kern/kern_rctl.c Sun Aug 5 21:32:51 2012 (r240116) @@ -76,6 +76,8 @@ #define RCTL_MAX_INBUFLEN 4096 #define RCTL_LOG_BUFSIZE 128 +#define RCTL_PCPU_SHIFT 10 + /* * 'rctl_rule_link' connects a rule with every racct it's related to. * For example, rule 'user:X:openfiles:deny=N/process' is linked @@ -272,31 +274,48 @@ } /* - * Return non-zero if allocating 'amount' by proc 'p' would exceed - * 'resource' limit specified by any rule applicable to the process 'p'. - * The 'amount' can be negative. + * Special version of rctl_available() function for the %cpu resource. + * We slightly cheat here and return less than we normally would. */ -int -rctl_over_limit(const struct proc *p, int resource, int64_t amount) { +int64_t +rctl_pcpu_available(const struct proc *p) { struct rctl_rule *rule; struct rctl_rule_link *link; - int over_limit; + int64_t available, minavailable, limit; + + minavailable = INT64_MAX; + limit = 0; - over_limit = 0; rw_rlock(&rctl_lock); LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) { rule = link->rrl_rule; - if (rule->rr_resource != resource) + if (rule->rr_resource != RACCT_PCTCPU) continue; - if (rctl_would_exceed(p, rule, amount)) { - over_limit = 1; - break; + if (rule->rr_action != RCTL_ACTION_DENY) + continue; + available = rctl_available_resource(p, rule); + if (available < minavailable) { + minavailable = available; + limit = rule->rr_amount; } } rw_runlock(&rctl_lock); - return (over_limit); + + /* + * Return slightly less than actual value of the available + * %cpu resource. This makes %cpu throttling more agressive + * and lets us act sooner than the limits are already exceeded. + */ + if (limit != 0) { + if (limit > 2 * RCTL_PCPU_SHIFT) + minavailable -= RCTL_PCPU_SHIFT; + else + minavailable -= (limit / 2); + } + + return (minavailable); } /* Modified: soc2012/rudot/sys/sys/rctl.h ============================================================================== --- soc2012/rudot/sys/sys/rctl.h Sun Aug 5 20:19:27 2012 (r240115) +++ soc2012/rudot/sys/sys/rctl.h Sun Aug 5 21:32:51 2012 (r240116) @@ -140,7 +140,7 @@ int rctl_rule_add(struct rctl_rule *rule); int rctl_rule_remove(struct rctl_rule *filter); int rctl_enforce(struct proc *p, int resource, uint64_t amount); -int rctl_over_limit(const struct proc *p, int resource, int64_t amount); +int64_t rctl_pcpu_available(const struct proc *p); uint64_t rctl_get_limit(struct proc *p, int resource); uint64_t rctl_get_available(struct proc *p, int resource); const char *rctl_resource_name(int resource);