[IPV6] IPSEC: Omit redirect for tunnelled packet.
[pandora-kernel.git] / kernel / sched_fair.c
index 892616b..67c67a8 100644 (file)
@@ -42,6 +42,14 @@ unsigned int sysctl_sched_latency __read_mostly = 20000000ULL;
  */
 unsigned int sysctl_sched_min_granularity __read_mostly = 2000000ULL;
 
+/*
+ * sys_sched_yield() compat mode
+ *
+ * This option switches the agressive yield implementation of the
+ * old scheduler back on.
+ */
+unsigned int __read_mostly sysctl_sched_compat_yield;
+
 /*
  * SCHED_BATCH wake-up granularity.
  * (default: 25 msec, units: nanoseconds)
@@ -631,6 +639,16 @@ static void enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se)
 
                se->block_start = 0;
                se->sum_sleep_runtime += delta;
+
+               /*
+                * Blocking time is in units of nanosecs, so shift by 20 to
+                * get a milliseconds-range estimation of the amount of
+                * time that the task spent sleeping:
+                */
+               if (unlikely(prof_on == SLEEP_PROFILING)) {
+                       profile_hits(SLEEP_PROFILING, (void *)get_wchan(tsk),
+                                    delta >> 20);
+               }
        }
 #endif
 }
@@ -897,19 +915,62 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int sleep)
 }
 
 /*
- * sched_yield() support is very simple - we dequeue and enqueue
+ * sched_yield() support is very simple - we dequeue and enqueue.
+ *
+ * If compat_yield is turned on then we requeue to the end of the tree.
  */
 static void yield_task_fair(struct rq *rq, struct task_struct *p)
 {
        struct cfs_rq *cfs_rq = task_cfs_rq(p);
+       struct rb_node **link = &cfs_rq->tasks_timeline.rb_node;
+       struct sched_entity *rightmost, *se = &p->se;
+       struct rb_node *parent;
 
-       __update_rq_clock(rq);
        /*
-        * Dequeue and enqueue the task to update its
-        * position within the tree:
+        * Are we the only task in the tree?
+        */
+       if (unlikely(cfs_rq->nr_running == 1))
+               return;
+
+       if (likely(!sysctl_sched_compat_yield)) {
+               __update_rq_clock(rq);
+               /*
+                * Dequeue and enqueue the task to update its
+                * position within the tree:
+                */
+               dequeue_entity(cfs_rq, &p->se, 0);
+               enqueue_entity(cfs_rq, &p->se, 0);
+
+               return;
+       }
+       /*
+        * Find the rightmost entry in the rbtree:
+        */
+       do {
+               parent = *link;
+               link = &parent->rb_right;
+       } while (*link);
+
+       rightmost = rb_entry(parent, struct sched_entity, run_node);
+       /*
+        * Already in the rightmost position?
         */
-       dequeue_entity(cfs_rq, &p->se, 0);
-       enqueue_entity(cfs_rq, &p->se, 0);
+       if (unlikely(rightmost == se))
+               return;
+
+       /*
+        * Minimally necessary key value to be last in the tree:
+        */
+       se->fair_key = rightmost->fair_key + 1;
+
+       if (cfs_rq->rb_leftmost == &se->run_node)
+               cfs_rq->rb_leftmost = rb_next(&se->run_node);
+       /*
+        * Relink the task to the rightmost position:
+        */
+       rb_erase(&se->run_node, &cfs_rq->tasks_timeline);
+       rb_link_node(&se->run_node, parent, link);
+       rb_insert_color(&se->run_node, &cfs_rq->tasks_timeline);
 }
 
 /*