|
@@ -1608,21 +1608,42 @@ static inline void update_shares_locked(struct rq *rq, struct sched_domain *sd)
|
|
|
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
+#ifdef CONFIG_PREEMPT
|
|
|
|
+
|
|
/*
|
|
/*
|
|
- * double_lock_balance - lock the busiest runqueue, this_rq is locked already.
|
|
|
|
|
|
+ * fair double_lock_balance: Safely acquires both rq->locks in a fair
|
|
|
|
+ * way at the expense of forcing extra atomic operations in all
|
|
|
|
+ * invocations. This assures that the double_lock is acquired using the
|
|
|
|
+ * same underlying policy as the spinlock_t on this architecture, which
|
|
|
|
+ * reduces latency compared to the unfair variant below. However, it
|
|
|
|
+ * also adds more overhead and therefore may reduce throughput.
|
|
*/
|
|
*/
|
|
-static int double_lock_balance(struct rq *this_rq, struct rq *busiest)
|
|
|
|
|
|
+static inline int _double_lock_balance(struct rq *this_rq, struct rq *busiest)
|
|
|
|
+ __releases(this_rq->lock)
|
|
|
|
+ __acquires(busiest->lock)
|
|
|
|
+ __acquires(this_rq->lock)
|
|
|
|
+{
|
|
|
|
+ spin_unlock(&this_rq->lock);
|
|
|
|
+ double_rq_lock(this_rq, busiest);
|
|
|
|
+
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#else
|
|
|
|
+/*
|
|
|
|
+ * Unfair double_lock_balance: Optimizes throughput at the expense of
|
|
|
|
+ * latency by eliminating extra atomic operations when the locks are
|
|
|
|
+ * already in proper order on entry. This favors lower cpu-ids and will
|
|
|
|
+ * grant the double lock to lower cpus over higher ids under contention,
|
|
|
|
+ * regardless of entry order into the function.
|
|
|
|
+ */
|
|
|
|
+static int _double_lock_balance(struct rq *this_rq, struct rq *busiest)
|
|
__releases(this_rq->lock)
|
|
__releases(this_rq->lock)
|
|
__acquires(busiest->lock)
|
|
__acquires(busiest->lock)
|
|
__acquires(this_rq->lock)
|
|
__acquires(this_rq->lock)
|
|
{
|
|
{
|
|
int ret = 0;
|
|
int ret = 0;
|
|
|
|
|
|
- if (unlikely(!irqs_disabled())) {
|
|
|
|
- /* printk() doesn't work good under rq->lock */
|
|
|
|
- spin_unlock(&this_rq->lock);
|
|
|
|
- BUG_ON(1);
|
|
|
|
- }
|
|
|
|
if (unlikely(!spin_trylock(&busiest->lock))) {
|
|
if (unlikely(!spin_trylock(&busiest->lock))) {
|
|
if (busiest < this_rq) {
|
|
if (busiest < this_rq) {
|
|
spin_unlock(&this_rq->lock);
|
|
spin_unlock(&this_rq->lock);
|
|
@@ -1635,6 +1656,22 @@ static int double_lock_balance(struct rq *this_rq, struct rq *busiest)
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#endif /* CONFIG_PREEMPT */
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * double_lock_balance - lock the busiest runqueue, this_rq is locked already.
|
|
|
|
+ */
|
|
|
|
+static int double_lock_balance(struct rq *this_rq, struct rq *busiest)
|
|
|
|
+{
|
|
|
|
+ if (unlikely(!irqs_disabled())) {
|
|
|
|
+ /* printk() doesn't work good under rq->lock */
|
|
|
|
+ spin_unlock(&this_rq->lock);
|
|
|
|
+ BUG_ON(1);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return _double_lock_balance(this_rq, busiest);
|
|
|
|
+}
|
|
|
|
+
|
|
static inline void double_unlock_balance(struct rq *this_rq, struct rq *busiest)
|
|
static inline void double_unlock_balance(struct rq *this_rq, struct rq *busiest)
|
|
__releases(busiest->lock)
|
|
__releases(busiest->lock)
|
|
{
|
|
{
|