summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_rctl.c
diff options
context:
space:
mode:
authortrasz <trasz@FreeBSD.org>2012-10-26 16:01:08 +0000
committertrasz <trasz@FreeBSD.org>2012-10-26 16:01:08 +0000
commitd97338334a7696793856e52982abcf531ba728cf (patch)
tree842a8cfc3ef8239e42a28dbb369918bc9a00b13e /sys/kern/kern_rctl.c
parent5f08f2efa84de1e44eed353961807024d5b221aa (diff)
downloadFreeBSD-src-d97338334a7696793856e52982abcf531ba728cf.zip
FreeBSD-src-d97338334a7696793856e52982abcf531ba728cf.tar.gz
Add CPU percentage limit enforcement to RCTL. The resouce name is "pcpu".
It was implemented by Rudolf Tomori during Google Summer of Code 2012.
Diffstat (limited to 'sys/kern/kern_rctl.c')
-rw-r--r--sys/kern/kern_rctl.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/sys/kern/kern_rctl.c b/sys/kern/kern_rctl.c
index 1d0a440..934327a 100644
--- a/sys/kern/kern_rctl.c
+++ b/sys/kern/kern_rctl.c
@@ -76,6 +76,8 @@ FEATURE(rctl, "Resource Limits");
#define RCTL_MAX_INBUFLEN 4096
#define RCTL_LOG_BUFSIZE 128
+#define RCTL_PCPU_SHIFT (10 * 1000000)
+
/*
* 'rctl_rule_link' connects a rule with every racct it's related to.
* For example, rule 'user:X:openfiles:deny=N/process' is linked
@@ -120,6 +122,7 @@ static struct dict resourcenames[] = {
{ "nshm", RACCT_NSHM },
{ "shmsize", RACCT_SHMSIZE },
{ "wallclock", RACCT_WALLCLOCK },
+ { "pcpu", RACCT_PCTCPU },
{ NULL, -1 }};
static struct dict actionnames[] = {
@@ -271,6 +274,51 @@ rctl_would_exceed(const struct proc *p, const struct rctl_rule *rule,
}
/*
+ * Special version of rctl_available() function for the %cpu resource.
+ * We slightly cheat here and return less than we normally would.
+ */
+int64_t
+rctl_pcpu_available(const struct proc *p) {
+ struct rctl_rule *rule;
+ struct rctl_rule_link *link;
+ int64_t available, minavailable, limit;
+
+ minavailable = INT64_MAX;
+ 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 != RACCT_PCTCPU)
+ continue;
+ 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 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);
+}
+
+/*
* Check whether the proc 'p' can allocate 'amount' of 'resource' in addition
* to what it keeps allocated now. Returns non-zero if the allocation should
* be denied, 0 otherwise.
OpenPOWER on IntegriCloud