{
        int prio;
 
-       if (task_has_rt_policy(p))
+       if (task_has_dl_policy(p))
+               prio = MAX_DL_PRIO-1;
+       else if (task_has_rt_policy(p))
                prio = MAX_RT_PRIO-1 - p->rt_priority;
        else
                prio = __normal_prio(p);
        memset(&p->se.statistics, 0, sizeof(p->se.statistics));
 #endif
 
+       RB_CLEAR_NODE(&p->dl.rb_node);
+       hrtimer_init(&p->dl.dl_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+       p->dl.dl_runtime = p->dl.runtime = 0;
+       p->dl.dl_deadline = p->dl.deadline = 0;
+       p->dl.flags = 0;
+
        INIT_LIST_HEAD(&p->rt.run_list);
 
 #ifdef CONFIG_PREEMPT_NOTIFIERS
 /*
  * fork()/clone()-time setup:
  */
-void sched_fork(unsigned long clone_flags, struct task_struct *p)
+int sched_fork(unsigned long clone_flags, struct task_struct *p)
 {
        unsigned long flags;
        int cpu = get_cpu();
         * Revert to default priority/policy on fork if requested.
         */
        if (unlikely(p->sched_reset_on_fork)) {
-               if (task_has_rt_policy(p)) {
+               if (task_has_dl_policy(p) || task_has_rt_policy(p)) {
                        p->policy = SCHED_NORMAL;
                        p->static_prio = NICE_TO_PRIO(0);
                        p->rt_priority = 0;
                p->sched_reset_on_fork = 0;
        }
 
-       if (!rt_prio(p->prio))
+       if (dl_prio(p->prio)) {
+               put_cpu();
+               return -EAGAIN;
+       } else if (rt_prio(p->prio)) {
+               p->sched_class = &rt_sched_class;
+       } else {
                p->sched_class = &fair_sched_class;
+       }
 
        if (p->sched_class->task_fork)
                p->sched_class->task_fork(p);
 #endif
 
        put_cpu();
+       return 0;
 }
 
 /*
        struct rq *rq;
        const struct sched_class *prev_class;
 
-       BUG_ON(prio < 0 || prio > MAX_PRIO);
+       BUG_ON(prio > MAX_PRIO);
 
        rq = __task_rq_lock(p);
 
        if (running)
                p->sched_class->put_prev_task(rq, p);
 
-       if (rt_prio(prio))
+       if (dl_prio(prio))
+               p->sched_class = &dl_sched_class;
+       else if (rt_prio(prio))
                p->sched_class = &rt_sched_class;
        else
                p->sched_class = &fair_sched_class;
         * The RT priorities are set via sched_setscheduler(), but we still
         * allow the 'normal' nice value to be set - but as expected
         * it wont have any effect on scheduling until the task is
-        * SCHED_FIFO/SCHED_RR:
+        * SCHED_DEADLINE, SCHED_FIFO or SCHED_RR:
         */
-       if (task_has_rt_policy(p)) {
+       if (task_has_dl_policy(p) || task_has_rt_policy(p)) {
                p->static_prio = NICE_TO_PRIO(nice);
                goto out_unlock;
        }
        return pid ? find_task_by_vpid(pid) : current;
 }
 
+/*
+ * This function initializes the sched_dl_entity of a newly becoming
+ * SCHED_DEADLINE task.
+ *
+ * Only the static values are considered here, the actual runtime and the
+ * absolute deadline will be properly calculated when the task is enqueued
+ * for the first time with its new policy.
+ */
+static void
+__setparam_dl(struct task_struct *p, const struct sched_attr *attr)
+{
+       struct sched_dl_entity *dl_se = &p->dl;
+
+       init_dl_task_timer(dl_se);
+       dl_se->dl_runtime = attr->sched_runtime;
+       dl_se->dl_deadline = attr->sched_deadline;
+       dl_se->flags = attr->sched_flags;
+       dl_se->dl_throttled = 0;
+       dl_se->dl_new = 1;
+}
+
 /* Actually do priority change: must hold pi & rq lock. */
 static void __setscheduler(struct rq *rq, struct task_struct *p,
                           const struct sched_attr *attr)
 
        p->policy = policy;
 
-       if (rt_policy(policy))
+       if (dl_policy(policy))
+               __setparam_dl(p, attr);
+       else if (rt_policy(policy))
                p->rt_priority = attr->sched_priority;
        else
                p->static_prio = NICE_TO_PRIO(attr->sched_nice);
        p->normal_prio = normal_prio(p);
        p->prio = rt_mutex_getprio(p);
 
-       if (rt_prio(p->prio))
+       if (dl_prio(p->prio))
+               p->sched_class = &dl_sched_class;
+       else if (rt_prio(p->prio))
                p->sched_class = &rt_sched_class;
        else
                p->sched_class = &fair_sched_class;
 
        set_load_weight(p);
 }
+
+static void
+__getparam_dl(struct task_struct *p, struct sched_attr *attr)
+{
+       struct sched_dl_entity *dl_se = &p->dl;
+
+       attr->sched_priority = p->rt_priority;
+       attr->sched_runtime = dl_se->dl_runtime;
+       attr->sched_deadline = dl_se->dl_deadline;
+       attr->sched_flags = dl_se->flags;
+}
+
+/*
+ * This function validates the new parameters of a -deadline task.
+ * We ask for the deadline not being zero, and greater or equal
+ * than the runtime.
+ */
+static bool
+__checkparam_dl(const struct sched_attr *attr)
+{
+       return attr && attr->sched_deadline != 0 &&
+              (s64)(attr->sched_deadline - attr->sched_runtime) >= 0;
+}
+
 /*
  * check the target process has a UID that matches the current process's
  */
                reset_on_fork = !!(policy & SCHED_RESET_ON_FORK);
                policy &= ~SCHED_RESET_ON_FORK;
 
-               if (policy != SCHED_FIFO && policy != SCHED_RR &&
+               if (policy != SCHED_DEADLINE &&
+                               policy != SCHED_FIFO && policy != SCHED_RR &&
                                policy != SCHED_NORMAL && policy != SCHED_BATCH &&
                                policy != SCHED_IDLE)
                        return -EINVAL;
            (p->mm && attr->sched_priority > MAX_USER_RT_PRIO-1) ||
            (!p->mm && attr->sched_priority > MAX_RT_PRIO-1))
                return -EINVAL;
-       if (rt_policy(policy) != (attr->sched_priority != 0))
+       if ((dl_policy(policy) && !__checkparam_dl(attr)) ||
+           (rt_policy(policy) != (attr->sched_priority != 0)))
                return -EINVAL;
 
        /*
                        goto change;
                if (rt_policy(policy) && attr->sched_priority != p->rt_priority)
                        goto change;
+               if (dl_policy(policy))
+                       goto change;
 
                task_rq_unlock(rq, p, &flags);
                return 0;
        if (retval)
                goto out_unlock;
 
+       if (task_has_dl_policy(p)) {
+               retval = -EINVAL;
+               goto out_unlock;
+       }
        lp.sched_priority = p->rt_priority;
        rcu_read_unlock();
 
 }
 
 /**
- * sys_sched_getattr - same as above, but with extended "sched_param"
+ * sys_sched_getattr - similar to sched_getparam, but with sched_attr
  * @pid: the pid in question.
  * @attr: structure containing the extended parameters.
  * @size: sizeof(attr) for fwd/bwd comp.
                goto out_unlock;
 
        attr.sched_policy = p->policy;
-       if (task_has_rt_policy(p))
+       if (task_has_dl_policy(p))
+               __getparam_dl(p, &attr);
+       else if (task_has_rt_policy(p))
                attr.sched_priority = p->rt_priority;
        else
                attr.sched_nice = TASK_NICE(p);
        case SCHED_RR:
                ret = MAX_USER_RT_PRIO-1;
                break;
+       case SCHED_DEADLINE:
        case SCHED_NORMAL:
        case SCHED_BATCH:
        case SCHED_IDLE:
        case SCHED_RR:
                ret = 1;
                break;
+       case SCHED_DEADLINE:
        case SCHED_NORMAL:
        case SCHED_BATCH:
        case SCHED_IDLE:
                rq->calc_load_update = jiffies + LOAD_FREQ;
                init_cfs_rq(&rq->cfs);
                init_rt_rq(&rq->rt, rq);
+               init_dl_rq(&rq->dl, rq);
 #ifdef CONFIG_FAIR_GROUP_SCHED
                root_task_group.shares = ROOT_TASK_GROUP_LOAD;
                INIT_LIST_HEAD(&rq->leaf_cfs_rq_list);
                p->se.statistics.block_start    = 0;
 #endif
 
-               if (!rt_task(p)) {
+               if (!dl_task(p) && !rt_task(p)) {
                        /*
                         * Renice negative nice level userspace
                         * tasks back to 0:
 
--- /dev/null
+/*
+ * Deadline Scheduling Class (SCHED_DEADLINE)
+ *
+ * Earliest Deadline First (EDF) + Constant Bandwidth Server (CBS).
+ *
+ * Tasks that periodically executes their instances for less than their
+ * runtime won't miss any of their deadlines.
+ * Tasks that are not periodic or sporadic or that tries to execute more
+ * than their reserved bandwidth will be slowed down (and may potentially
+ * miss some of their deadlines), and won't affect any other task.
+ *
+ * Copyright (C) 2012 Dario Faggioli <raistlin@linux.it>,
+ *                    Michael Trimarchi <michael@amarulasolutions.com>,
+ *                    Fabio Checconi <fchecconi@gmail.com>
+ */
+#include "sched.h"
+
+static inline int dl_time_before(u64 a, u64 b)
+{
+       return (s64)(a - b) < 0;
+}
+
+static inline struct task_struct *dl_task_of(struct sched_dl_entity *dl_se)
+{
+       return container_of(dl_se, struct task_struct, dl);
+}
+
+static inline struct rq *rq_of_dl_rq(struct dl_rq *dl_rq)
+{
+       return container_of(dl_rq, struct rq, dl);
+}
+
+static inline struct dl_rq *dl_rq_of_se(struct sched_dl_entity *dl_se)
+{
+       struct task_struct *p = dl_task_of(dl_se);
+       struct rq *rq = task_rq(p);
+
+       return &rq->dl;
+}
+
+static inline int on_dl_rq(struct sched_dl_entity *dl_se)
+{
+       return !RB_EMPTY_NODE(&dl_se->rb_node);
+}
+
+static inline int is_leftmost(struct task_struct *p, struct dl_rq *dl_rq)
+{
+       struct sched_dl_entity *dl_se = &p->dl;
+
+       return dl_rq->rb_leftmost == &dl_se->rb_node;
+}
+
+void init_dl_rq(struct dl_rq *dl_rq, struct rq *rq)
+{
+       dl_rq->rb_root = RB_ROOT;
+}
+
+static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags);
+static void __dequeue_task_dl(struct rq *rq, struct task_struct *p, int flags);
+static void check_preempt_curr_dl(struct rq *rq, struct task_struct *p,
+                                 int flags);
+
+/*
+ * We are being explicitly informed that a new instance is starting,
+ * and this means that:
+ *  - the absolute deadline of the entity has to be placed at
+ *    current time + relative deadline;
+ *  - the runtime of the entity has to be set to the maximum value.
+ *
+ * The capability of specifying such event is useful whenever a -deadline
+ * entity wants to (try to!) synchronize its behaviour with the scheduler's
+ * one, and to (try to!) reconcile itself with its own scheduling
+ * parameters.
+ */
+static inline void setup_new_dl_entity(struct sched_dl_entity *dl_se)
+{
+       struct dl_rq *dl_rq = dl_rq_of_se(dl_se);
+       struct rq *rq = rq_of_dl_rq(dl_rq);
+
+       WARN_ON(!dl_se->dl_new || dl_se->dl_throttled);
+
+       /*
+        * We use the regular wall clock time to set deadlines in the
+        * future; in fact, we must consider execution overheads (time
+        * spent on hardirq context, etc.).
+        */
+       dl_se->deadline = rq_clock(rq) + dl_se->dl_deadline;
+       dl_se->runtime = dl_se->dl_runtime;
+       dl_se->dl_new = 0;
+}
+
+/*
+ * Pure Earliest Deadline First (EDF) scheduling does not deal with the
+ * possibility of a entity lasting more than what it declared, and thus
+ * exhausting its runtime.
+ *
+ * Here we are interested in making runtime overrun possible, but we do
+ * not want a entity which is misbehaving to affect the scheduling of all
+ * other entities.
+ * Therefore, a budgeting strategy called Constant Bandwidth Server (CBS)
+ * is used, in order to confine each entity within its own bandwidth.
+ *
+ * This function deals exactly with that, and ensures that when the runtime
+ * of a entity is replenished, its deadline is also postponed. That ensures
+ * the overrunning entity can't interfere with other entity in the system and
+ * can't make them miss their deadlines. Reasons why this kind of overruns
+ * could happen are, typically, a entity voluntarily trying to overcome its
+ * runtime, or it just underestimated it during sched_setscheduler_ex().
+ */
+static void replenish_dl_entity(struct sched_dl_entity *dl_se)
+{
+       struct dl_rq *dl_rq = dl_rq_of_se(dl_se);
+       struct rq *rq = rq_of_dl_rq(dl_rq);
+
+       /*
+        * We keep moving the deadline away until we get some
+        * available runtime for the entity. This ensures correct
+        * handling of situations where the runtime overrun is
+        * arbitrary large.
+        */
+       while (dl_se->runtime <= 0) {
+               dl_se->deadline += dl_se->dl_deadline;
+               dl_se->runtime += dl_se->dl_runtime;
+       }
+
+       /*
+        * At this point, the deadline really should be "in
+        * the future" with respect to rq->clock. If it's
+        * not, we are, for some reason, lagging too much!
+        * Anyway, after having warn userspace abut that,
+        * we still try to keep the things running by
+        * resetting the deadline and the budget of the
+        * entity.
+        */
+       if (dl_time_before(dl_se->deadline, rq_clock(rq))) {
+               static bool lag_once = false;
+
+               if (!lag_once) {
+                       lag_once = true;
+                       printk_sched("sched: DL replenish lagged to much\n");
+               }
+               dl_se->deadline = rq_clock(rq) + dl_se->dl_deadline;
+               dl_se->runtime = dl_se->dl_runtime;
+       }
+}
+
+/*
+ * Here we check if --at time t-- an entity (which is probably being
+ * [re]activated or, in general, enqueued) can use its remaining runtime
+ * and its current deadline _without_ exceeding the bandwidth it is
+ * assigned (function returns true if it can't). We are in fact applying
+ * one of the CBS rules: when a task wakes up, if the residual runtime
+ * over residual deadline fits within the allocated bandwidth, then we
+ * can keep the current (absolute) deadline and residual budget without
+ * disrupting the schedulability of the system. Otherwise, we should
+ * refill the runtime and set the deadline a period in the future,
+ * because keeping the current (absolute) deadline of the task would
+ * result in breaking guarantees promised to other tasks.
+ *
+ * This function returns true if:
+ *
+ *   runtime / (deadline - t) > dl_runtime / dl_deadline ,
+ *
+ * IOW we can't recycle current parameters.
+ */
+static bool dl_entity_overflow(struct sched_dl_entity *dl_se, u64 t)
+{
+       u64 left, right;
+
+       /*
+        * left and right are the two sides of the equation above,
+        * after a bit of shuffling to use multiplications instead
+        * of divisions.
+        *
+        * Note that none of the time values involved in the two
+        * multiplications are absolute: dl_deadline and dl_runtime
+        * are the relative deadline and the maximum runtime of each
+        * instance, runtime is the runtime left for the last instance
+        * and (deadline - t), since t is rq->clock, is the time left
+        * to the (absolute) deadline. Even if overflowing the u64 type
+        * is very unlikely to occur in both cases, here we scale down
+        * as we want to avoid that risk at all. Scaling down by 10
+        * means that we reduce granularity to 1us. We are fine with it,
+        * since this is only a true/false check and, anyway, thinking
+        * of anything below microseconds resolution is actually fiction
+        * (but still we want to give the user that illusion >;).
+        */
+       left = (dl_se->dl_deadline >> 10) * (dl_se->runtime >> 10);
+       right = ((dl_se->deadline - t) >> 10) * (dl_se->dl_runtime >> 10);
+
+       return dl_time_before(right, left);
+}
+
+/*
+ * When a -deadline entity is queued back on the runqueue, its runtime and
+ * deadline might need updating.
+ *
+ * The policy here is that we update the deadline of the entity only if:
+ *  - the current deadline is in the past,
+ *  - using the remaining runtime with the current deadline would make
+ *    the entity exceed its bandwidth.
+ */
+static void update_dl_entity(struct sched_dl_entity *dl_se)
+{
+       struct dl_rq *dl_rq = dl_rq_of_se(dl_se);
+       struct rq *rq = rq_of_dl_rq(dl_rq);
+
+       /*
+        * The arrival of a new instance needs special treatment, i.e.,
+        * the actual scheduling parameters have to be "renewed".
+        */
+       if (dl_se->dl_new) {
+               setup_new_dl_entity(dl_se);
+               return;
+       }
+
+       if (dl_time_before(dl_se->deadline, rq_clock(rq)) ||
+           dl_entity_overflow(dl_se, rq_clock(rq))) {
+               dl_se->deadline = rq_clock(rq) + dl_se->dl_deadline;
+               dl_se->runtime = dl_se->dl_runtime;
+       }
+}
+
+/*
+ * If the entity depleted all its runtime, and if we want it to sleep
+ * while waiting for some new execution time to become available, we
+ * set the bandwidth enforcement timer to the replenishment instant
+ * and try to activate it.
+ *
+ * Notice that it is important for the caller to know if the timer
+ * actually started or not (i.e., the replenishment instant is in
+ * the future or in the past).
+ */
+static int start_dl_timer(struct sched_dl_entity *dl_se)
+{
+       struct dl_rq *dl_rq = dl_rq_of_se(dl_se);
+       struct rq *rq = rq_of_dl_rq(dl_rq);
+       ktime_t now, act;
+       ktime_t soft, hard;
+       unsigned long range;
+       s64 delta;
+
+       /*
+        * We want the timer to fire at the deadline, but considering
+        * that it is actually coming from rq->clock and not from
+        * hrtimer's time base reading.
+        */
+       act = ns_to_ktime(dl_se->deadline);
+       now = hrtimer_cb_get_time(&dl_se->dl_timer);
+       delta = ktime_to_ns(now) - rq_clock(rq);
+       act = ktime_add_ns(act, delta);
+
+       /*
+        * If the expiry time already passed, e.g., because the value
+        * chosen as the deadline is too small, don't even try to
+        * start the timer in the past!
+        */
+       if (ktime_us_delta(act, now) < 0)
+               return 0;
+
+       hrtimer_set_expires(&dl_se->dl_timer, act);
+
+       soft = hrtimer_get_softexpires(&dl_se->dl_timer);
+       hard = hrtimer_get_expires(&dl_se->dl_timer);
+       range = ktime_to_ns(ktime_sub(hard, soft));
+       __hrtimer_start_range_ns(&dl_se->dl_timer, soft,
+                                range, HRTIMER_MODE_ABS, 0);
+
+       return hrtimer_active(&dl_se->dl_timer);
+}
+
+/*
+ * This is the bandwidth enforcement timer callback. If here, we know
+ * a task is not on its dl_rq, since the fact that the timer was running
+ * means the task is throttled and needs a runtime replenishment.
+ *
+ * However, what we actually do depends on the fact the task is active,
+ * (it is on its rq) or has been removed from there by a call to
+ * dequeue_task_dl(). In the former case we must issue the runtime
+ * replenishment and add the task back to the dl_rq; in the latter, we just
+ * do nothing but clearing dl_throttled, so that runtime and deadline
+ * updating (and the queueing back to dl_rq) will be done by the
+ * next call to enqueue_task_dl().
+ */
+static enum hrtimer_restart dl_task_timer(struct hrtimer *timer)
+{
+       struct sched_dl_entity *dl_se = container_of(timer,
+                                                    struct sched_dl_entity,
+                                                    dl_timer);
+       struct task_struct *p = dl_task_of(dl_se);
+       struct rq *rq = task_rq(p);
+       raw_spin_lock(&rq->lock);
+
+       /*
+        * We need to take care of a possible races here. In fact, the
+        * task might have changed its scheduling policy to something
+        * different from SCHED_DEADLINE or changed its reservation
+        * parameters (through sched_setscheduler()).
+        */
+       if (!dl_task(p) || dl_se->dl_new)
+               goto unlock;
+
+       sched_clock_tick();
+       update_rq_clock(rq);
+       dl_se->dl_throttled = 0;
+       if (p->on_rq) {
+               enqueue_task_dl(rq, p, ENQUEUE_REPLENISH);
+               if (task_has_dl_policy(rq->curr))
+                       check_preempt_curr_dl(rq, p, 0);
+               else
+                       resched_task(rq->curr);
+       }
+unlock:
+       raw_spin_unlock(&rq->lock);
+
+       return HRTIMER_NORESTART;
+}
+
+void init_dl_task_timer(struct sched_dl_entity *dl_se)
+{
+       struct hrtimer *timer = &dl_se->dl_timer;
+
+       if (hrtimer_active(timer)) {
+               hrtimer_try_to_cancel(timer);
+               return;
+       }
+
+       hrtimer_init(timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+       timer->function = dl_task_timer;
+}
+
+static
+int dl_runtime_exceeded(struct rq *rq, struct sched_dl_entity *dl_se)
+{
+       int dmiss = dl_time_before(dl_se->deadline, rq_clock(rq));
+       int rorun = dl_se->runtime <= 0;
+
+       if (!rorun && !dmiss)
+               return 0;
+
+       /*
+        * If we are beyond our current deadline and we are still
+        * executing, then we have already used some of the runtime of
+        * the next instance. Thus, if we do not account that, we are
+        * stealing bandwidth from the system at each deadline miss!
+        */
+       if (dmiss) {
+               dl_se->runtime = rorun ? dl_se->runtime : 0;
+               dl_se->runtime -= rq_clock(rq) - dl_se->deadline;
+       }
+
+       return 1;
+}
+
+/*
+ * Update the current task's runtime statistics (provided it is still
+ * a -deadline task and has not been removed from the dl_rq).
+ */
+static void update_curr_dl(struct rq *rq)
+{
+       struct task_struct *curr = rq->curr;
+       struct sched_dl_entity *dl_se = &curr->dl;
+       u64 delta_exec;
+
+       if (!dl_task(curr) || !on_dl_rq(dl_se))
+               return;
+
+       /*
+        * Consumed budget is computed considering the time as
+        * observed by schedulable tasks (excluding time spent
+        * in hardirq context, etc.). Deadlines are instead
+        * computed using hard walltime. This seems to be the more
+        * natural solution, but the full ramifications of this
+        * approach need further study.
+        */
+       delta_exec = rq_clock_task(rq) - curr->se.exec_start;
+       if (unlikely((s64)delta_exec < 0))
+               delta_exec = 0;
+
+       schedstat_set(curr->se.statistics.exec_max,
+                     max(curr->se.statistics.exec_max, delta_exec));
+
+       curr->se.sum_exec_runtime += delta_exec;
+       account_group_exec_runtime(curr, delta_exec);
+
+       curr->se.exec_start = rq_clock_task(rq);
+       cpuacct_charge(curr, delta_exec);
+
+       dl_se->runtime -= delta_exec;
+       if (dl_runtime_exceeded(rq, dl_se)) {
+               __dequeue_task_dl(rq, curr, 0);
+               if (likely(start_dl_timer(dl_se)))
+                       dl_se->dl_throttled = 1;
+               else
+                       enqueue_task_dl(rq, curr, ENQUEUE_REPLENISH);
+
+               if (!is_leftmost(curr, &rq->dl))
+                       resched_task(curr);
+       }
+}
+
+static void __enqueue_dl_entity(struct sched_dl_entity *dl_se)
+{
+       struct dl_rq *dl_rq = dl_rq_of_se(dl_se);
+       struct rb_node **link = &dl_rq->rb_root.rb_node;
+       struct rb_node *parent = NULL;
+       struct sched_dl_entity *entry;
+       int leftmost = 1;
+
+       BUG_ON(!RB_EMPTY_NODE(&dl_se->rb_node));
+
+       while (*link) {
+               parent = *link;
+               entry = rb_entry(parent, struct sched_dl_entity, rb_node);
+               if (dl_time_before(dl_se->deadline, entry->deadline))
+                       link = &parent->rb_left;
+               else {
+                       link = &parent->rb_right;
+                       leftmost = 0;
+               }
+       }
+
+       if (leftmost)
+               dl_rq->rb_leftmost = &dl_se->rb_node;
+
+       rb_link_node(&dl_se->rb_node, parent, link);
+       rb_insert_color(&dl_se->rb_node, &dl_rq->rb_root);
+
+       dl_rq->dl_nr_running++;
+}
+
+static void __dequeue_dl_entity(struct sched_dl_entity *dl_se)
+{
+       struct dl_rq *dl_rq = dl_rq_of_se(dl_se);
+
+       if (RB_EMPTY_NODE(&dl_se->rb_node))
+               return;
+
+       if (dl_rq->rb_leftmost == &dl_se->rb_node) {
+               struct rb_node *next_node;
+
+               next_node = rb_next(&dl_se->rb_node);
+               dl_rq->rb_leftmost = next_node;
+       }
+
+       rb_erase(&dl_se->rb_node, &dl_rq->rb_root);
+       RB_CLEAR_NODE(&dl_se->rb_node);
+
+       dl_rq->dl_nr_running--;
+}
+
+static void
+enqueue_dl_entity(struct sched_dl_entity *dl_se, int flags)
+{
+       BUG_ON(on_dl_rq(dl_se));
+
+       /*
+        * If this is a wakeup or a new instance, the scheduling
+        * parameters of the task might need updating. Otherwise,
+        * we want a replenishment of its runtime.
+        */
+       if (!dl_se->dl_new && flags & ENQUEUE_REPLENISH)
+               replenish_dl_entity(dl_se);
+       else
+               update_dl_entity(dl_se);
+
+       __enqueue_dl_entity(dl_se);
+}
+
+static void dequeue_dl_entity(struct sched_dl_entity *dl_se)
+{
+       __dequeue_dl_entity(dl_se);
+}
+
+static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags)
+{
+       /*
+        * If p is throttled, we do nothing. In fact, if it exhausted
+        * its budget it needs a replenishment and, since it now is on
+        * its rq, the bandwidth timer callback (which clearly has not
+        * run yet) will take care of this.
+        */
+       if (p->dl.dl_throttled)
+               return;
+
+       enqueue_dl_entity(&p->dl, flags);
+       inc_nr_running(rq);
+}
+
+static void __dequeue_task_dl(struct rq *rq, struct task_struct *p, int flags)
+{
+       dequeue_dl_entity(&p->dl);
+}
+
+static void dequeue_task_dl(struct rq *rq, struct task_struct *p, int flags)
+{
+       update_curr_dl(rq);
+       __dequeue_task_dl(rq, p, flags);
+
+       dec_nr_running(rq);
+}
+
+/*
+ * Yield task semantic for -deadline tasks is:
+ *
+ *   get off from the CPU until our next instance, with
+ *   a new runtime. This is of little use now, since we
+ *   don't have a bandwidth reclaiming mechanism. Anyway,
+ *   bandwidth reclaiming is planned for the future, and
+ *   yield_task_dl will indicate that some spare budget
+ *   is available for other task instances to use it.
+ */
+static void yield_task_dl(struct rq *rq)
+{
+       struct task_struct *p = rq->curr;
+
+       /*
+        * We make the task go to sleep until its current deadline by
+        * forcing its runtime to zero. This way, update_curr_dl() stops
+        * it and the bandwidth timer will wake it up and will give it
+        * new scheduling parameters (thanks to dl_new=1).
+        */
+       if (p->dl.runtime > 0) {
+               rq->curr->dl.dl_new = 1;
+               p->dl.runtime = 0;
+       }
+       update_curr_dl(rq);
+}
+
+/*
+ * Only called when both the current and waking task are -deadline
+ * tasks.
+ */
+static void check_preempt_curr_dl(struct rq *rq, struct task_struct *p,
+                                 int flags)
+{
+       if (dl_time_before(p->dl.deadline, rq->curr->dl.deadline))
+               resched_task(rq->curr);
+}
+
+#ifdef CONFIG_SCHED_HRTICK
+static void start_hrtick_dl(struct rq *rq, struct task_struct *p)
+{
+       s64 delta = p->dl.dl_runtime - p->dl.runtime;
+
+       if (delta > 10000)
+               hrtick_start(rq, p->dl.runtime);
+}
+#endif
+
+static struct sched_dl_entity *pick_next_dl_entity(struct rq *rq,
+                                                  struct dl_rq *dl_rq)
+{
+       struct rb_node *left = dl_rq->rb_leftmost;
+
+       if (!left)
+               return NULL;
+
+       return rb_entry(left, struct sched_dl_entity, rb_node);
+}
+
+struct task_struct *pick_next_task_dl(struct rq *rq)
+{
+       struct sched_dl_entity *dl_se;
+       struct task_struct *p;
+       struct dl_rq *dl_rq;
+
+       dl_rq = &rq->dl;
+
+       if (unlikely(!dl_rq->dl_nr_running))
+               return NULL;
+
+       dl_se = pick_next_dl_entity(rq, dl_rq);
+       BUG_ON(!dl_se);
+
+       p = dl_task_of(dl_se);
+       p->se.exec_start = rq_clock_task(rq);
+#ifdef CONFIG_SCHED_HRTICK
+       if (hrtick_enabled(rq))
+               start_hrtick_dl(rq, p);
+#endif
+       return p;
+}
+
+static void put_prev_task_dl(struct rq *rq, struct task_struct *p)
+{
+       update_curr_dl(rq);
+}
+
+static void task_tick_dl(struct rq *rq, struct task_struct *p, int queued)
+{
+       update_curr_dl(rq);
+
+#ifdef CONFIG_SCHED_HRTICK
+       if (hrtick_enabled(rq) && queued && p->dl.runtime > 0)
+               start_hrtick_dl(rq, p);
+#endif
+}
+
+static void task_fork_dl(struct task_struct *p)
+{
+       /*
+        * SCHED_DEADLINE tasks cannot fork and this is achieved through
+        * sched_fork()
+        */
+}
+
+static void task_dead_dl(struct task_struct *p)
+{
+       struct hrtimer *timer = &p->dl.dl_timer;
+
+       if (hrtimer_active(timer))
+               hrtimer_try_to_cancel(timer);
+}
+
+static void set_curr_task_dl(struct rq *rq)
+{
+       struct task_struct *p = rq->curr;
+
+       p->se.exec_start = rq_clock_task(rq);
+}
+
+static void switched_from_dl(struct rq *rq, struct task_struct *p)
+{
+       if (hrtimer_active(&p->dl.dl_timer))
+               hrtimer_try_to_cancel(&p->dl.dl_timer);
+}
+
+static void switched_to_dl(struct rq *rq, struct task_struct *p)
+{
+       /*
+        * If p is throttled, don't consider the possibility
+        * of preempting rq->curr, the check will be done right
+        * after its runtime will get replenished.
+        */
+       if (unlikely(p->dl.dl_throttled))
+               return;
+
+       if (p->on_rq || rq->curr != p) {
+               if (task_has_dl_policy(rq->curr))
+                       check_preempt_curr_dl(rq, p, 0);
+               else
+                       resched_task(rq->curr);
+       }
+}
+
+static void prio_changed_dl(struct rq *rq, struct task_struct *p,
+                           int oldprio)
+{
+       switched_to_dl(rq, p);
+}
+
+#ifdef CONFIG_SMP
+static int
+select_task_rq_dl(struct task_struct *p, int prev_cpu, int sd_flag, int flags)
+{
+       return task_cpu(p);
+}
+#endif
+
+const struct sched_class dl_sched_class = {
+       .next                   = &rt_sched_class,
+       .enqueue_task           = enqueue_task_dl,
+       .dequeue_task           = dequeue_task_dl,
+       .yield_task             = yield_task_dl,
+
+       .check_preempt_curr     = check_preempt_curr_dl,
+
+       .pick_next_task         = pick_next_task_dl,
+       .put_prev_task          = put_prev_task_dl,
+
+#ifdef CONFIG_SMP
+       .select_task_rq         = select_task_rq_dl,
+#endif
+
+       .set_curr_task          = set_curr_task_dl,
+       .task_tick              = task_tick_dl,
+       .task_fork              = task_fork_dl,
+       .task_dead              = task_dead_dl,
+
+       .prio_changed           = prio_changed_dl,
+       .switched_from          = switched_from_dl,
+       .switched_to            = switched_to_dl,
+};