summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorJerry Jelinek <jerry.jelinek@joyent.com>2012-07-25 15:43:15 +0000
committerJerry Jelinek <jerry.jelinek@joyent.com>2012-07-25 15:43:15 +0000
commit2453263d59c2317dbe88d1c9e12893a32abd91b8 (patch)
tree8e0941ac5a20e5d2f56f011cc452816ddb6f358f /usr/src
parent87be0498f4e05c54a8c9d1e905a9c55a327a9191 (diff)
downloadillumos-joyent-2453263d59c2317dbe88d1c9e12893a32abd91b8.tar.gz
OS-1405 CPU caps can throttle performance more than intended2012072620120626release-20120726release-20120626
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/disp/cpucaps.c43
1 files changed, 41 insertions, 2 deletions
diff --git a/usr/src/uts/common/disp/cpucaps.c b/usr/src/uts/common/disp/cpucaps.c
index 26067235a9..68be78a84f 100644
--- a/usr/src/uts/common/disp/cpucaps.c
+++ b/usr/src/uts/common/disp/cpucaps.c
@@ -578,8 +578,47 @@ cap_poke_waitq(cpucap_t *cap, int64_t gen)
cap->cap_below++;
- if (!waitq_isempty(wq))
- waitq_runone(wq);
+ if (!waitq_isempty(wq)) {
+ int i, ndequeue, p;
+
+ /*
+ * Since this function is only called once per tick,
+ * we can hit a situation where we have artificially
+ * limited the project/zone below its cap. This would
+ * happen if we have multiple threads queued up but
+ * only dequeued one thread/tick. To avoid this we
+ * dequeue multiple threads, calculated based on the
+ * usage percentage of the cap. It is possible that we
+ * could dequeue too many threads and some of them
+ * might be put back on the wait queue quickly, but
+ * since we know that threads are on the wait queue
+ * because we're capping, we know that there is unused
+ * CPU cycles anyway, so this extra work would not
+ * hurt. Also, the ndequeue number is only an upper
+ * bound and we might dequeue less, depending on how
+ * many threads are actually in the wait queue. The
+ * ndequeue values are empirically derived and could be
+ * adjusted or calculated in another way if necessary.
+ */
+ p = (int)((100 * cap->cap_usage) / cap->cap_chk_value);
+ if (p >= 98)
+ ndequeue = 10;
+ else if (p >= 95)
+ ndequeue = 20;
+ else if (p >= 90)
+ ndequeue = 40;
+ else if (p >= 85)
+ ndequeue = 80;
+ else
+ ndequeue = 160;
+
+ for (i = 0; i < ndequeue; i++) {
+ waitq_runone(wq);
+ if (waitq_isempty(wq))
+ break;
+ }
+ DTRACE_PROBE2(cpucaps__pokeq, int, p, int, i);
+ }
}
}