aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/kern_rctl.c
diff options
context:
space:
mode:
authorEdward Tomasz Napierala <trasz@FreeBSD.org>2012-10-26 16:01:08 +0000
committerEdward Tomasz Napierala <trasz@FreeBSD.org>2012-10-26 16:01:08 +0000
commit36af98697d92141dcd4f4cca56da38a426ccb089 (patch)
tree842a8cfc3ef8239e42a28dbb369918bc9a00b13e /sys/kern/kern_rctl.c
parent6cff4e07c15477db7747f98dc7ecbedfe7563d40 (diff)
downloadsrc-36af98697d92141dcd4f4cca56da38a426ccb089.tar.gz
src-36af98697d92141dcd4f4cca56da38a426ccb089.zip
Add CPU percentage limit enforcement to RCTL. The resouce name is "pcpu".
It was implemented by Rudolf Tomori during Google Summer of Code 2012.
Notes
Notes: svn path=/head/; revision=242139
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 1d0a440da7a2..934327a41d82 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.