Skip to contentSkip to conversation

sched_rt.c: Avoid unnecessary dequeue and enqueue of pushable tasks in set_cpus_allowed_rt()

PATCH In review Kirill Tkhai 3 participants 11 messages Dec 1, 2011 – Apr 14, 2012 Scheduler

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 sched_rt.c: Avoid unnecessary dequeue and enqueue of pushable tasks in set_cpus_allowed_rt()

[PATCH]sched_rt.c: Avoid unnecessary dequeue and enqueue of pushable tasks in set_cpus_allowed_rt()

Migration status depends on a difference of weight from 0 and 1. If weight > 1 (<= 1) and old weight <= 1 (> 1) then task becomes pushable (not pushable). We are not insterested in exact values of it, is it 3 or 4, for example.

Now if we are changing affinity from a set of 3 cpus to a set of 4, the task will be dequeued and enqueued sequentially without important difference in comparison with initial state. The only difference is in internal representation of plist queue of pushable tasks and the fact that the task may won't be the first in a sequence of the same priority tasks. But it seems to me it gives nothing.

sched_rt.c renamed from sched_rt.c.orig +23 -29
@@ -1572,43 +1572,37 @@ static void set_cpus_allowed_rt(struct t
 				const struct cpumask *new_mask)
 {
 	int weight = cpumask_weight(new_mask);
+	struct rq *rq;
 
 	BUG_ON(!rt_task(p));
 
 	/*
-	 * Update the migration status of the RQ if we have an RT task
-	 * which is running AND changing its weight value.
+	 * Just exit if it's not necessary to change migration status
 	 */
-	if (p->on_rq && (weight != p->rt.nr_cpus_allowed)) {
-		struct rq *rq = task_rq(p);
+	if ((p->rt.nr_cpus_allowed <= 1 && weight <= 1)
+		|| (p->rt.nr_cpus_allowed > 1 && weight > 1))
+		return;
 
-		if (!task_current(rq, p)) {
-			/*
-			 * Make sure we dequeue this task from the pushable list
-			 * before going further.  It will either remain off of
-			 * the list because we are no longer pushable, or it
-			 * will be requeued.
-			 */
-			if (p->rt.nr_cpus_allowed > 1)
-				dequeue_pushable_task(rq, p);
-
-			/*
-			 * Requeue if our weight is changing and still > 1
-			 */
-			if (weight > 1)
-				enqueue_pushable_task(rq, p);
-
-		}
-
-		if ((p->rt.nr_cpus_allowed <= 1) && (weight > 1)) {
-			rq->rt.rt_nr_migratory++;
-		} else if ((p->rt.nr_cpus_allowed > 1) && (weight <= 1)) {
-			BUG_ON(!rq->rt.rt_nr_migratory);
-			rq->rt.rt_nr_migratory--;
-		}
+	if (!p->on_rq)
+		return;
 
-		update_rt_migration(&rq->rt);
+	rq = task_rq(p);
+
+	/*
+	 * Several cpus were allowed but now it's not so OR vice versa
+	 */
+	if (weight <= 1) {
+		if (!task_current(rq, p))
+			dequeue_pushable_task(rq, p);
+		BUG_ON(!rq->rt.rt_nr_migratory);
+		rq->rt.rt_nr_migratory--;
+	} else {
+		if (!task_current(rq, p))
+			enqueue_pushable_task(rq, p);
+		rq->rt.rt_nr_migratory++;
 	}
+
+	update_rt_migration(&rq->rt);
 }
 
 /* Assumes rq->lock is held */
#1 lore raw
Quoted 6 lines · Kirill Tkhai

Migration status depends on a difference of weight from 0 and 1. If weight > 1 (<= 1) and old weight <= 1 (> 1) then task becomes pushable (not pushable). We are not insterested in exact values of it, is it 3 or 4, for example.

Quoted 6 lines

Now if we are changing affinity from a set of 3 cpus to a set of 4, the task will be dequeued and enqueued sequentially without important difference in comparison with initial state. The only difference is in internal representation of plist queue of pushable tasks and the fact that the task may won't be the first in a sequence of the same priority tasks. But it seems to me it gives nothing.

Looks reasonable, although I can't say I really understand this code. Add Gregory.

sched_rt.c

Quoted 4 lines
sched_rt.c renamed from sched_rt.c.orig +0 -0

please use -p1

Quoted 8 lines
sched_rt.c renamed from sched_rt.c.orig +1 -0
@@ -1572,43 +1572,37 @@ static void set_cpus_allowed_rt(struct t
 				const struct cpumask *new_mask)
 {
 	int weight = cpumask_weight(new_mask);
+	struct rq *rq;
 
 	BUG_ON(!rt_task(p));
 

sched_rt.c static void set_cpus_allowed_rt(struct t · line 1584

Quoted 10 lines
sched_rt.c renamed from sched_rt.c.orig +4 -4
 	/*
-	 * Update the migration status of the RQ if we have an RT task
-	 * which is running AND changing its weight value.
+	 * Just exit if it's not necessary to change migration status
 	 */
-	if (p->on_rq && (weight != p->rt.nr_cpus_allowed)) {
-		struct rq *rq = task_rq(p);
+	if ((p->rt.nr_cpus_allowed <= 1 && weight <= 1)
+		|| (p->rt.nr_cpus_allowed > 1 && weight > 1))
+		return;

Subjective, but may be

	if ((p->rt.nr_cpus_allowed > 1) != (weight > 1))
		return;

looks more understandable?

Quoted 51 lines
sched_rt.c renamed from sched_rt.c.orig +18 -25
-		if (!task_current(rq, p)) {
-			/*
-			 * Make sure we dequeue this task from the pushable list
-			 * before going further.  It will either remain off of
-			 * the list because we are no longer pushable, or it
-			 * will be requeued.
-			 */
-			if (p->rt.nr_cpus_allowed > 1)
-				dequeue_pushable_task(rq, p);
-
-			/*
-			 * Requeue if our weight is changing and still > 1
-			 */
-			if (weight > 1)
-				enqueue_pushable_task(rq, p);
-
-		}
-
-		if ((p->rt.nr_cpus_allowed <= 1) && (weight > 1)) {
-			rq->rt.rt_nr_migratory++;
-		} else if ((p->rt.nr_cpus_allowed > 1) && (weight <= 1)) {
-			BUG_ON(!rq->rt.rt_nr_migratory);
-			rq->rt.rt_nr_migratory--;
-		}
+	if (!p->on_rq)
+		return;
 
-		update_rt_migration(&rq->rt);
+	rq = task_rq(p);
+
+	/*
+	 * Several cpus were allowed but now it's not so OR vice versa
+	 */
+	if (weight <= 1) {
+		if (!task_current(rq, p))
+			dequeue_pushable_task(rq, p);
+		BUG_ON(!rq->rt.rt_nr_migratory);
+		rq->rt.rt_nr_migratory--;
+	} else {
+		if (!task_current(rq, p))
+			enqueue_pushable_task(rq, p);
+		rq->rt.rt_nr_migratory++;
 	}
+
+	update_rt_migration(&rq->rt);
 }
 
 /* Assumes rq->lock is held */
 
#2 lore raw

20.12.2011, 21:44, "Oleg Nesterov" <[email protected]>:

Quoted 17 lines · Kirill Tkhai
Quoted 6 lines

 Migration status depends on a difference of weight from 0 and 1. If weight > 1 (<= 1) and old weight <= 1 (> 1) then task becomes pushable (not pushable). We are not insterested in exact values of it, is it 3 or 4, for example.

Quoted 6 lines

 Now if we are changing affinity from a set of 3 cpus to a set of 4, the task will be dequeued and enqueued sequentially without important difference in comparison with initial state. The only difference is in internal representation of plist queue of pushable tasks and the fact that the task may won't be the first in a sequence of the same priority tasks. But it seems to me it gives nothing.

Looks reasonable, although I can't say I really understand this code. Add Gregory.

Quoted 7 lines
Quoted 4 lines

 --- kernel/sched_rt.c.orig 2011-12-02 00:29:11.970243145 +0400 +++ kernel/sched_rt.c 2011-12-02 00:37:43.622846606 +0400

please use -p1

Sorry, this time I'm sending "git diffed" output.

Quoted 19 lines
Quoted 8 lines

 @@ -1572,43 +1572,37 @@ static void set_cpus_allowed_rt(struct t const struct cpumask *new_mask) {
          int weight = cpumask_weight(new_mask);
 + struct rq *rq;

          BUG_ON(!rt_task(p));

Quoted 10 lines

          /*
 - * Update the migration status of the RQ if we have an RT task
 - * which is running AND changing its weight value.
 + * Just exit if it's not necessary to change migration status */
 - if (p->on_rq && (weight != p->rt.nr_cpus_allowed)) {
 - struct rq *rq = task_rq(p);
 + if ((p->rt.nr_cpus_allowed <= 1 && weight <= 1)
 + || (p->rt.nr_cpus_allowed > 1 && weight > 1))
 + return;

Quoted 6 lines

Subjective, but may be

        if ((p->rt.nr_cpus_allowed > 1) != (weight > 1)) return;

looks more understandable?

Yes, thanks.

---

kernel/sched/rt.c +21 -28
index 3640ebb..4467f4d 100644
@@ -1774,43 +1774,36 @@ static void set_cpus_allowed_rt(struct task_struct *p,
 				const struct cpumask *new_mask)
 {
 	int weight = cpumask_weight(new_mask);
+	struct rq *rq;
 
 	BUG_ON(!rt_task(p));
 
 	/*
-	 * Update the migration status of the RQ if we have an RT task
-	 * which is running AND changing its weight value.
+	 * Just exit if it's not necessary to change migration status
 	 */
-	if (p->on_rq && (weight != p->rt.nr_cpus_allowed)) {
-		struct rq *rq = task_rq(p);
-
-		if (!task_current(rq, p)) {
-			/*
-			 * Make sure we dequeue this task from the pushable list
-			 * before going further.  It will either remain off of
-			 * the list because we are no longer pushable, or it
-			 * will be requeued.
-			 */
-			if (p->rt.nr_cpus_allowed > 1)
-				dequeue_pushable_task(rq, p);
-
-			/*
-			 * Requeue if our weight is changing and still > 1
-			 */
-			if (weight > 1)
-				enqueue_pushable_task(rq, p);
+	if ((p->rt.nr_cpus_allowed > 1) != (weight > 1))
+		return;
 
-		}
+	if (!p->on_rq)
+		return;
 
-		if ((p->rt.nr_cpus_allowed <= 1) && (weight > 1)) {
-			rq->rt.rt_nr_migratory++;
-		} else if ((p->rt.nr_cpus_allowed > 1) && (weight <= 1)) {
-			BUG_ON(!rq->rt.rt_nr_migratory);
-			rq->rt.rt_nr_migratory--;
-		}
+	rq = task_rq(p);
 
-		update_rt_migration(&rq->rt);
+	/*
+	 * Several cpus were allowed but now it's not so OR vice versa
+	 */
+	if (weight <= 1) {
+		if (!task_current(rq, p))
+			dequeue_pushable_task(rq, p);
+		BUG_ON(!rq->rt.rt_nr_migratory);
+		rq->rt.rt_nr_migratory--;
+	} else {
+		if (!task_current(rq, p))
+			enqueue_pushable_task(rq, p);
+		rq->rt.rt_nr_migratory++;
 	}
+
+	update_rt_migration(&rq->rt);
 }
 
 /* Assumes rq->lock is held */
#3 lore raw

Again, right patch

21.12.2011, 00:28, "Tkhai Kirill" <[email protected]>:

Quoted 112 lines

20.12.2011, 21:44, "Oleg Nesterov" <[email protected]>:

Quoted 12 lines · Kirill Tkhai
Quoted 11 lines

  Migration status depends on a difference of weight from 0 and 1. If weight > 1 (<= 1) and old weight <= 1 (> 1) then task becomes pushable (not pushable). We are not insterested in exact values of it, is it 3 or 4, for example.

  Now if we are changing affinity from a set of 3 cpus to a set of 4, the task will be dequeued and enqueued sequentially without important difference in comparison with initial state. The only difference is in internal representation of plist queue of pushable tasks and the fact that the task may won't be the first in a sequence of the same priority tasks. But it seems to me it gives nothing.

Quoted 7 lines

 Looks reasonable, although I can't say I really understand this code. Add Gregory.

Quoted 4 lines

  --- kernel/sched_rt.c.orig 2011-12-02 00:29:11.970243145 +0400 +++ kernel/sched_rt.c 2011-12-02 00:37:43.622846606 +0400

 please use -p1

Sorry, this time I'm sending "git diffed" output.

Quoted 18 lines
Quoted 8 lines

  @@ -1572,43 +1572,37 @@ static void set_cpus_allowed_rt(struct t const struct cpumask *new_mask) {
           int weight = cpumask_weight(new_mask);
  + struct rq *rq;

           BUG_ON(!rt_task(p));

Quoted 10 lines

           /*
  - * Update the migration status of the RQ if we have an RT task
  - * which is running AND changing its weight value.
  + * Just exit if it's not necessary to change migration status */
  - if (p->on_rq && (weight != p->rt.nr_cpus_allowed)) {
  - struct rq *rq = task_rq(p);
  + if ((p->rt.nr_cpus_allowed <= 1 && weight <= 1)
  + || (p->rt.nr_cpus_allowed > 1 && weight > 1))
  + return;

Quoted 6 lines

 Subjective, but may be

         if ((p->rt.nr_cpus_allowed > 1) != (weight > 1)) return;

 looks more understandable?

Yes, thanks.

---

kernel/sched/rt.c +15 -28
index 3640ebb..4467f4d 100644
@@ -1774,43 +1774,36 @@ static void set_cpus_allowed_rt(struct task_struct *p,
                                  const struct cpumask *new_mask)
  {
          int weight = cpumask_weight(new_mask);
+ struct rq *rq;
 
          BUG_ON(!rt_task(p));
 
          /*
- * Update the migration status of the RQ if we have an RT task
- * which is running AND changing its weight value.
+ * Just exit if it's not necessary to change migration status
           */
- if (p->on_rq && (weight != p->rt.nr_cpus_allowed)) {
- struct rq *rq = task_rq(p);
-
- if (!task_current(rq, p)) {
- /*
- * Make sure we dequeue this task from the pushable list
- * before going further.  It will either remain off of
- * the list because we are no longer pushable, or it
- * will be requeued.
- */
- if (p->rt.nr_cpus_allowed > 1)
- dequeue_pushable_task(rq, p);
-
- /*
- * Requeue if our weight is changing and still > 1
- */
- if (weight > 1)
- enqueue_pushable_task(rq, p);
+ if ((p->rt.nr_cpus_allowed > 1) != (weight > 1))
+ return;
 
- }
+ if (!p->on_rq)
+ return;
 
- if ((p->rt.nr_cpus_allowed <= 1) && (weight > 1)) {
- rq->rt.rt_nr_migratory++;
- } else if ((p->rt.nr_cpus_allowed > 1) && (weight <= 1)) {
- BUG_ON(!rq->rt.rt_nr_migratory);
- rq->rt.rt_nr_migratory--;
- }
+ rq = task_rq(p);
 
- update_rt_migration(&rq->rt);
+ /*
+ * Several cpus were allowed but now it's not so OR vice versa
+ */
+ if (weight <= 1) {
+ if (!task_current(rq, p))
+ dequeue_pushable_task(rq, p);
+ BUG_ON(!rq->rt.rt_nr_migratory);
+ rq->rt.rt_nr_migratory--;

kernel/sched/rt.c static void set_cpus_allowed_rt(struct task_struct *p, · line 1809

Quoted 10 lines
kernel/sched/rt.c +6 -0
+ } else {
+ if (!task_current(rq, p))
+ enqueue_pushable_task(rq, p);
+ rq->rt.rt_nr_migratory++;
          }
+
+ update_rt_migration(&rq->rt);
  }
 
  /* Assumes rq->lock is held */

---

kernel/sched/rt.c +21 -28
index 3640ebb..bf48343 100644
@@ -1774,43 +1774,36 @@ static void set_cpus_allowed_rt(struct task_struct *p,
 				const struct cpumask *new_mask)
 {
 	int weight = cpumask_weight(new_mask);
+	struct rq *rq;
 
 	BUG_ON(!rt_task(p));
 
 	/*
-	 * Update the migration status of the RQ if we have an RT task
-	 * which is running AND changing its weight value.
+	 * Just exit if it's not necessary to change migration status
 	 */
-	if (p->on_rq && (weight != p->rt.nr_cpus_allowed)) {
-		struct rq *rq = task_rq(p);
-
-		if (!task_current(rq, p)) {
-			/*
-			 * Make sure we dequeue this task from the pushable list
-			 * before going further.  It will either remain off of
-			 * the list because we are no longer pushable, or it
-			 * will be requeued.
-			 */
-			if (p->rt.nr_cpus_allowed > 1)
-				dequeue_pushable_task(rq, p);
-
-			/*
-			 * Requeue if our weight is changing and still > 1
-			 */
-			if (weight > 1)
-				enqueue_pushable_task(rq, p);
+	if ((p->rt.nr_cpus_allowed > 1) == (weight > 1))
+		return;
 
-		}
+	if (!p->on_rq)
+		return;
 
-		if ((p->rt.nr_cpus_allowed <= 1) && (weight > 1)) {
-			rq->rt.rt_nr_migratory++;
-		} else if ((p->rt.nr_cpus_allowed > 1) && (weight <= 1)) {
-			BUG_ON(!rq->rt.rt_nr_migratory);
-			rq->rt.rt_nr_migratory--;
-		}
+	rq = task_rq(p);
 
-		update_rt_migration(&rq->rt);
+	/*
+	 * Several cpus were allowed but now it's not so OR vice versa
+	 */
+	if (weight <= 1) {
+		if (!task_current(rq, p))
+			dequeue_pushable_task(rq, p);
+		BUG_ON(!rq->rt.rt_nr_migratory);
+		rq->rt.rt_nr_migratory--;
+	} else {
+		if (!task_current(rq, p))
+			enqueue_pushable_task(rq, p);
+		rq->rt.rt_nr_migratory++;
 	}
+
+	update_rt_migration(&rq->rt);
 }
 
 /* Assumes rq->lock is held */
#4 lore raw
In reply to Kirill Tkhai

I wasn't on the Cc of the original message, but it was bounced to me awhile ago. I'm cleaning out my email and came across it.

Can you send me the latest version of this patch, either against latest Linus, or against tip/master.

Thanks,

-- Steve

P.S. I'll be at ELC this week so it may not get processed right away.

Quoted 94 lines · Kirill Tkhai

[PATCH]sched_rt.c: Avoid unnecessary dequeue and enqueue of pushable tasks in set_cpus_allowed_rt()

Migration status depends on a difference of weight from 0 and 1. If weight > 1 (<= 1) and old weight <= 1 (> 1) then task becomes pushable (not pushable). We are not insterested in exact values of it, is it 3 or 4, for example.

Now if we are changing affinity from a set of 3 cpus to a set of 4, the task will be dequeued and enqueued sequentially without important difference in comparison with initial state. The only difference is in internal representation of plist queue of pushable tasks and the fact that the task may won't be the first in a sequence of the same priority tasks. But it seems to me it gives nothing.

sched_rt.c renamed from sched_rt.c.orig +23 -30
@@ -1572,43 +1572,37 @@ static void set_cpus_allowed_rt(struct t
 				const struct cpumask *new_mask)
 {
 	int weight = cpumask_weight(new_mask);
+	struct rq *rq;
 
 	BUG_ON(!rt_task(p));
 
 	/*
-	 * Update the migration status of the RQ if we have an RT task
-	 * which is running AND changing its weight value.
+	 * Just exit if it's not necessary to change migration status
 	 */
-	if (p->on_rq && (weight != p->rt.nr_cpus_allowed)) {
-		struct rq *rq = task_rq(p);
+	if ((p->rt.nr_cpus_allowed <= 1 && weight <= 1)
+		|| (p->rt.nr_cpus_allowed > 1 && weight > 1))
+		return;
 
-		if (!task_current(rq, p)) {
-			/*
-			 * Make sure we dequeue this task from the pushable list
-			 * before going further.  It will either remain off of
-			 * the list because we are no longer pushable, or it
-			 * will be requeued.
-			 */
-			if (p->rt.nr_cpus_allowed > 1)
-				dequeue_pushable_task(rq, p);
-
-			/*
-			 * Requeue if our weight is changing and still > 1
-			 */
-			if (weight > 1)
-				enqueue_pushable_task(rq, p);
-
-		}
-
-		if ((p->rt.nr_cpus_allowed <= 1) && (weight > 1)) {
-			rq->rt.rt_nr_migratory++;
-		} else if ((p->rt.nr_cpus_allowed > 1) && (weight <= 1)) {
-			BUG_ON(!rq->rt.rt_nr_migratory);
-			rq->rt.rt_nr_migratory--;
-		}
+	if (!p->on_rq)
+		return;
 
-		update_rt_migration(&rq->rt);
+	rq = task_rq(p);
+
+	/*
+	 * Several cpus were allowed but now it's not so OR vice versa
+	 */
+	if (weight <= 1) {
+		if (!task_current(rq, p))
+			dequeue_pushable_task(rq, p);
+		BUG_ON(!rq->rt.rt_nr_migratory);
+		rq->rt.rt_nr_migratory--;
+	} else {
+		if (!task_current(rq, p))
+			enqueue_pushable_task(rq, p);
+		rq->rt.rt_nr_migratory++;
 	}
+
+	update_rt_migration(&rq->rt);
 }
 
 /* Assumes rq->lock is held */
 
 
 
--

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

#5 lore raw

13.02.2012, 21:23, "Steven Rostedt" <[email protected]>:

Quoted 12 lines

I wasn't on the Cc of the original message, but it was bounced to me awhile ago. I'm cleaning out my email and came across it.

Can you send me the latest version of this patch, either against latest Linus, or against tip/master.

Thanks,

-- Steve

P.S. I'll be at ELC this week so it may not get processed right away.

Migration status depends on a difference of weight from 0 and 1. If weight > 1 (<= 1) and old weight <= 1 (> 1) then task becomes pushable (or not pushable). We are not insterested in its exact values, is it 3 or 4, for example.

Now if we are changing affinity from a set of 3 cpus to a set of 4, the- task will be dequeued and enqueued sequentially without important difference in comparison with initial state. The only difference is in internal representation of plist queue of pushable tasks and the fact that the task may won't be the first in a sequence of the same priority tasks. But it seems to me it gives nothing.

---

kernel/sched/rt.c +21 -28
index 3640ebb..bf48343 100644
@@ -1779,43 +1779,36 @@ static void set_cpus_allowed_rt(struct task_struct *p,
 				const struct cpumask *new_mask)
 {
 	int weight = cpumask_weight(new_mask);
+	struct rq *rq;
 
 	BUG_ON(!rt_task(p));
 
 	/*
-	 * Update the migration status of the RQ if we have an RT task
-	 * which is running AND changing its weight value.
+	 * Just exit if it's not necessary to change migration status
 	 */
-	if (p->on_rq && (weight != p->rt.nr_cpus_allowed)) {
-		struct rq *rq = task_rq(p);
-
-		if (!task_current(rq, p)) {
-			/*
-			 * Make sure we dequeue this task from the pushable list
-			 * before going further.  It will either remain off of
-			 * the list because we are no longer pushable, or it
-			 * will be requeued.
-			 */
-			if (p->rt.nr_cpus_allowed > 1)
-				dequeue_pushable_task(rq, p);
-
-			/*
-			 * Requeue if our weight is changing and still > 1
-			 */
-			if (weight > 1)
-				enqueue_pushable_task(rq, p);
+	if ((p->rt.nr_cpus_allowed > 1) == (weight > 1))
+		return;
 
-		}
+	if (!p->on_rq)
+		return;
 
-		if ((p->rt.nr_cpus_allowed <= 1) && (weight > 1)) {
-			rq->rt.rt_nr_migratory++;
-		} else if ((p->rt.nr_cpus_allowed > 1) && (weight <= 1)) {
-			BUG_ON(!rq->rt.rt_nr_migratory);
-			rq->rt.rt_nr_migratory--;
-		}
+	rq = task_rq(p);
 
-		update_rt_migration(&rq->rt);
+	/*
+	 * Several cpus were allowed but now it's not so OR vice versa
+	 */
+	if (weight <= 1) {
+		if (!task_current(rq, p))
+			dequeue_pushable_task(rq, p);
+		BUG_ON(!rq->rt.rt_nr_migratory);
+		rq->rt.rt_nr_migratory--;
+	} else {
+		if (!task_current(rq, p))
+			enqueue_pushable_task(rq, p);
+		rq->rt.rt_nr_migratory++;
 	}
+
+	update_rt_migration(&rq->rt);
 }
 
 /* Assumes rq->lock is held */
#6 lore raw

Steven, what is about the patch from my previous message? Is everything ok?

Regards,
Kirill

19.02.2012, 18:17, "Kirill Tkhai" <[email protected]>:

Quoted 27 lines

13.02.2012, 21:23, "Steven Rostedt" <[email protected]>:

Quoted 11 lines

 I wasn't on the Cc of the original message, but it was bounced to me awhile ago. I'm cleaning out my email and came across it.

 Can you send me the latest version of this patch, either against latest Linus, or against tip/master.

 Thanks,

 -- Steve

 P.S. I'll be at ELC this week so it may not get processed right away.

Migration status depends on a difference of weight from 0 and 1. If weight > 1 (<= 1) and old weight <= 1 (> 1) then task becomes pushable (or not pushable). We are not insterested in its exact values, is it 3 or 4, for example.

Now if we are changing affinity from a set of 3 cpus to a set of 4, the- task will be dequeued and enqueued sequentially without important difference in comparison with initial state. The only difference is in internal representation of plist queue of pushable tasks and the fact that the task may won't be the first in a sequence of the same priority tasks. But it seems to me it gives nothing.

#7 lore raw
Quoted 1 line · Kirill Tkhai

Steven, what is about the patch from my previous message? Is everything ok?

You're timing is impeccable. I was in Chemnitz, Germany when you sent this, and it too was lost in the noise ;-)

I'll take a look at it today.

Thanks!

-- Steve

Quoted 32 lines

Regards,
Kirill

19.02.2012, 18:17, "Kirill Tkhai" <[email protected]>:

Quoted 27 lines

13.02.2012, 21:23, "Steven Rostedt" <[email protected]>:

Quoted 11 lines

I wasn't on the Cc of the original message, but it was bounced to me awhile ago. I'm cleaning out my email and came across it.

Can you send me the latest version of this patch, either against latest Linus, or against tip/master.

Thanks,

-- Steve

P.S. I'll be at ELC this week so it may not get processed right away.

Migration status depends on a difference of weight from 0 and 1. If weight > 1 (<= 1) and old weight <= 1 (> 1) then task becomes pushable (or not pushable). We are not insterested in its exact values, is it 3 or 4, for example.

Now if we are changing affinity from a set of 3 cpus to a set of 4, the- task will be dequeued and enqueued sequentially without important difference in comparison with initial state. The only difference is in internal representation of plist queue of pushable tasks and the fact that the task may won't be the first in a sequence of the same priority tasks. But it seems to me it gives nothing.

#8 lore raw
In reply to Kirill Tkhai

kernel/sched/rt.c static void set_cpus_allowed_rt(struct task_struct *p, · line 1781

Quoted 10 lines · Kirill Tkhai

---

kernel/sched/rt.c +0 -0
index 3640ebb..bf48343 100644
@@ -1779,43 +1779,36 @@ static void set_cpus_allowed_rt(struct task_struct *p,
 				const struct cpumask *new_mask)
 {
 	int weight = cpumask_weight(new_mask);

Lets move the assignment of weight down. Gcc may optimize, but I don't want to rely on it.

kernel/sched/rt.c static void set_cpus_allowed_rt(struct task_struct *p, · line 1787

Quoted 8 lines
kernel/sched/rt.c +2 -2
+	struct rq *rq;
 
 	BUG_ON(!rt_task(p));
 
 	/*
-	 * Update the migration status of the RQ if we have an RT task
-	 * which is running AND changing its weight value.
+	 * Just exit if it's not necessary to change migration status

Let's comment this better. Something like:

Only update if the process changes its state from whether it can migrate or not.

Quoted 15 lines
kernel/sched/rt.c +0 -14
 	 */
-	if (p->on_rq && (weight != p->rt.nr_cpus_allowed)) {
-		struct rq *rq = task_rq(p);
-
-		if (!task_current(rq, p)) {
-			/*
-			 * Make sure we dequeue this task from the pushable list
-			 * before going further.  It will either remain off of
-			 * the list because we are no longer pushable, or it
-			 * will be requeued.
-			 */
-			if (p->rt.nr_cpus_allowed > 1)
-				dequeue_pushable_task(rq, p);
-
-			/*

kernel/sched/rt.c static void set_cpus_allowed_rt(struct task_struct *p, · line 1793

Quoted 10 lines
kernel/sched/rt.c +4 -5
-			 * Requeue if our weight is changing and still > 1
-			 */
-			if (weight > 1)
-				enqueue_pushable_task(rq, p);
+	if ((p->rt.nr_cpus_allowed > 1) == (weight > 1))
+		return;
 
-		}
+	if (!p->on_rq)
+		return;

Make the on_rq check first, and move the weight calculation below it. Why calculate the weight if we don't plan on doing anything with it?

kernel/sched/rt.c static void set_cpus_allowed_rt(struct task_struct *p, · line 1798

Quoted 12 lines
kernel/sched/rt.c +3 -7
-		if ((p->rt.nr_cpus_allowed <= 1) && (weight > 1)) {
-			rq->rt.rt_nr_migratory++;
-		} else if ((p->rt.nr_cpus_allowed > 1) && (weight <= 1)) {
-			BUG_ON(!rq->rt.rt_nr_migratory);
-			rq->rt.rt_nr_migratory--;
-		}
+	rq = task_rq(p);
 
-		update_rt_migration(&rq->rt);
+	/*
+	 * Several cpus were allowed but now it's not so OR vice versa

I rather say:

The process use to be able to migrate OR it can now migrate

Otherwise, the patch looks good.

Thanks,

-- Steve

P.S. I don't have any more trips in the near future, so I should be much quicker in my responses ;-)

Quoted 16 lines
kernel/sched/rt.c +12 -0
+	 */
+	if (weight <= 1) {
+		if (!task_current(rq, p))
+			dequeue_pushable_task(rq, p);
+		BUG_ON(!rq->rt.rt_nr_migratory);
+		rq->rt.rt_nr_migratory--;
+	} else {
+		if (!task_current(rq, p))
+			enqueue_pushable_task(rq, p);
+		rq->rt.rt_nr_migratory++;
 	}
+
+	update_rt_migration(&rq->rt);
 }
 
 /* Assumes rq->lock is held */
#9 lore raw

Migration status depends on a difference of weight from 0 and 1. If weight > 1 (<= 1) and old weight <= 1 (> 1) then task becomes pushable (or not pushable). We are not insterested in its exact values, is it 3 or 4, for example.
Now if we are changing affinity from a set of 3 cpus to a set of 4, the- task will be dequeued and enqueued sequentially without important difference in comparison with initial state. The only difference is in internal representation of plist queue of pushable tasks and the fact that the task may won't be the first in a sequence of the same priority tasks. But it seems to me it gives nothing.

---
 kernel/sched/rt.c |   56 ++++++++++++++++++++++++----------------------------
 1 files changed, 26 insertions(+), 30 deletions(-)
kernel/sched/rt.c +26 -30
index 44af55e..c5565c3 100644
@@ -1803,44 +1803,40 @@ static void task_woken_rt(struct rq *rq, struct task_struct *p)
 static void set_cpus_allowed_rt(struct task_struct *p,
 				const struct cpumask *new_mask)
 {
-	int weight = cpumask_weight(new_mask);
+	struct rq *rq;
+	int weight;
 
 	BUG_ON(!rt_task(p));
 
-	/*
-	 * Update the migration status of the RQ if we have an RT task
-	 * which is running AND changing its weight value.
-	 */
-	if (p->on_rq && (weight != p->rt.nr_cpus_allowed)) {
-		struct rq *rq = task_rq(p);
-
-		if (!task_current(rq, p)) {
-			/*
-			 * Make sure we dequeue this task from the pushable list
-			 * before going further.  It will either remain off of
-			 * the list because we are no longer pushable, or it
-			 * will be requeued.
-			 */
-			if (p->rt.nr_cpus_allowed > 1)
-				dequeue_pushable_task(rq, p);
+	if (!p->on_rq)
+		return;
 
-			/*
-			 * Requeue if our weight is changing and still > 1
-			 */
-			if (weight > 1)
-				enqueue_pushable_task(rq, p);
+	weight = cpumask_weight(new_mask);
 
-		}
+	/*
+	 * Only update if the process changes its state from whether it
+	 * can migrate or not.
+	 */
+	if ((p->rt.nr_cpus_allowed > 1) == (weight > 1))
+		return;
 
-		if ((p->rt.nr_cpus_allowed <= 1) && (weight > 1)) {
-			rq->rt.rt_nr_migratory++;
-		} else if ((p->rt.nr_cpus_allowed > 1) && (weight <= 1)) {
-			BUG_ON(!rq->rt.rt_nr_migratory);
-			rq->rt.rt_nr_migratory--;
-		}
+	rq = task_rq(p);
 
-		update_rt_migration(&rq->rt);
+	/*
+	 * The process used to be able to migrate OR it can now migrate
+	 */
+	if (weight <= 1) {
+		if (!task_current(rq, p))
+			dequeue_pushable_task(rq, p);
+		BUG_ON(!rq->rt.rt_nr_migratory);
+		rq->rt.rt_nr_migratory--;
+	} else {
+		if (!task_current(rq, p))
+			enqueue_pushable_task(rq, p);
+		rq->rt.rt_nr_migratory++;
 	}
+
+	update_rt_migration(&rq->rt);
 }
 
 /* Assumes rq->lock is held */
#10 lore raw

[tip:sched/core] sched_rt: Avoid unnecessary dequeue and enqueue of pushable tasks in set_cpus_allowed_rt ()

Commit-ID:  8d3d5ada56a692d36a9d55858881147ec10cfeb6
Gitweb:     http://git.kernel.org/tip/8d3d5ada56a692d36a9d55858881147ec10cfeb6
Author:     Kirill Tkhai <[email protected]>
AuthorDate: Wed, 11 Apr 2012 09:06:04 +0400
Committer:  Steven Rostedt <[email protected]>
CommitDate: Thu, 12 Apr 2012 16:59:37 -0400

sched_rt: Avoid unnecessary dequeue and enqueue of pushable tasks in set_cpus_allowed_rt()

Migration status depends on a difference of weight from 0 and 1. If weight > 1 (<= 1) and old weight <= 1 (> 1) then task becomes pushable (or not pushable). We are not insterested in its exact values, is it 3 or 4, for example.
Now if we are changing affinity from a set of 3 cpus to a set of 4, the- task will be dequeued and enqueued sequentially without important difference in comparison with initial state. The only difference is in internal representation of plist queue of pushable tasks and the fact that the task may won't be the first in a sequence of the same priority tasks. But it seems to me it gives nothing.

---
 kernel/sched/rt.c |   56 ++++++++++++++++++++++++----------------------------
 1 files changed, 26 insertions(+), 30 deletions(-)
kernel/sched/rt.c +26 -30
index b60dad7..90607a9 100644
@@ -1803,44 +1803,40 @@ static void task_woken_rt(struct rq *rq, struct task_struct *p)
 static void set_cpus_allowed_rt(struct task_struct *p,
 				const struct cpumask *new_mask)
 {
-	int weight = cpumask_weight(new_mask);
+	struct rq *rq;
+	int weight;
 
 	BUG_ON(!rt_task(p));
 
-	/*
-	 * Update the migration status of the RQ if we have an RT task
-	 * which is running AND changing its weight value.
-	 */
-	if (p->on_rq && (weight != p->rt.nr_cpus_allowed)) {
-		struct rq *rq = task_rq(p);
-
-		if (!task_current(rq, p)) {
-			/*
-			 * Make sure we dequeue this task from the pushable list
-			 * before going further.  It will either remain off of
-			 * the list because we are no longer pushable, or it
-			 * will be requeued.
-			 */
-			if (p->rt.nr_cpus_allowed > 1)
-				dequeue_pushable_task(rq, p);
+	if (!p->on_rq)
+		return;
 
-			/*
-			 * Requeue if our weight is changing and still > 1
-			 */
-			if (weight > 1)
-				enqueue_pushable_task(rq, p);
+	weight = cpumask_weight(new_mask);
 
-		}
+	/*
+	 * Only update if the process changes its state from whether it
+	 * can migrate or not.
+	 */
+	if ((p->rt.nr_cpus_allowed > 1) == (weight > 1))
+		return;
 
-		if ((p->rt.nr_cpus_allowed <= 1) && (weight > 1)) {
-			rq->rt.rt_nr_migratory++;
-		} else if ((p->rt.nr_cpus_allowed > 1) && (weight <= 1)) {
-			BUG_ON(!rq->rt.rt_nr_migratory);
-			rq->rt.rt_nr_migratory--;
-		}
+	rq = task_rq(p);
 
-		update_rt_migration(&rq->rt);
+	/*
+	 * The process used to be able to migrate OR it can now migrate
+	 */
+	if (weight <= 1) {
+		if (!task_current(rq, p))
+			dequeue_pushable_task(rq, p);
+		BUG_ON(!rq->rt.rt_nr_migratory);
+		rq->rt.rt_nr_migratory--;
+	} else {
+		if (!task_current(rq, p))
+			enqueue_pushable_task(rq, p);
+		rq->rt.rt_nr_migratory++;
 	}
+
+	update_rt_migration(&rq->rt);
 }
 
 /* Assumes rq->lock is held */