Re: [Question]How to restrict some kind of task?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Con Kolivas Wrote:

On Tue, 15 Nov 2005 21:18, liyu wrote:
Hi, All.

   I want to restrict some kind of task.

   For example, for some task have one schedule policy SCHED_XYZ, when
it reach beyond
40% CPU time, we force it yield CPU.

   I inserted some code in scheduler_tick(), like this:
       if (check_task_overload(rq)) {
               if (xyz_task(p) && yield_cpu(p, rq)) {
                       set_tsk_need_resched(p);
                       p->prio = effective_prio(p);
                       p->time_slice = task_timeslice(p);
                       p->first_time_slice = 0;
                       goto out_unlock;
               }
       }
   Of course, before these code, we hold our rq->lock first, so we should
go to 'out_unlock'.
   The function xyz_task(p) just is macro (p->policy == SCHED_XYZ), and
yield_cpu() also is simple, it just move the task to expired array,

int yield_cpu(task_t *p, runqueue_t *rq)
{
   dequeue_task(p, p->array);
   requeue_task(p, rq->expired);
   return 1;
}

Don't requeue after dequeue. You enqueue after dequeue.

Con


Thanks Con first.

I am sorry that is a my typo. if we wrote requeue_task() after dequeue_task(), we will crash
beacause remove task from prio_array twice.

The last of this mail is my patch. You will find it is similar to SCHED_ISO of the your CK patch,
However, this is more radicaler than SCHED_ISO.

I am gonna crazy for it.

Thanks.


PATCH:

--- linux-2.6.13.3/kernel/sched.c    2005-11-16 08:57:56.000000000 +0800
+++ linux-2.6.13.3.keep/kernel/sched.c 2005-11-15 15:21:47.000000000 +0800
@@ -51,6 +51,21 @@

#include <asm/unistd.h>

+/* [email protected] */
+int keep_tick;
+int keep_over;
+int keep_dbg;
+int keep_switch = 3*HZ; /* sysctl var */
+#define PF_KEEPOVER    0x01000000
+#define PF_NONREGU      (PF_EXITING|PF_DEAD|PF_DUMPCORE)
+#define KEEP_TEST_PERIOD (keep_switch)
+#define KEEP_LOAD_CFG (40)
+#define KEEP_LOAD_STD (KEEP_TEST_PERIOD*KEEP_LOAD_CFG/100)
+#define KEEP_LOAD_DELTA  (KEEP_TEST_PERIOD*5/100)
+#define KEEP_LOAD_TOP  (KEEP_LOAD_STD)
+#define KEEP_LOAD_BTM  (KEEP_LOAD_STD-KEEP_LOAD_DELTA)
+/* enda */
+
/*
 * Convert user-nice values [ -20 ... 0 ... 19 ]
 * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],
@@ -256,6 +271,12 @@
    unsigned long ttwu_cnt;
    unsigned long ttwu_local;
#endif
+  /* [email protected] */
+  int keep_tick;
+  int keep_over;
+  spinlock_t keep_lock;
+  struct list_head keep;
+  /* enda */
};

static DEFINE_PER_CPU(struct runqueue, runqueues);
@@ -592,6 +613,10 @@
 */
static void dequeue_task(struct task_struct *p, prio_array_t *array)
{
+/* [email protected] */
+    if (p->flags & PF_KEEPOVER)
+        return;
+/* enda */
    array->nr_active--;
    list_del(&p->run_list);
    if (list_empty(array->queue + p->prio))
@@ -600,6 +625,10 @@

static void enqueue_task(struct task_struct *p, prio_array_t *array)
{
+    /* [email protected] */
+    if (p->flags & PF_KEEPOVER)
+        return;
+    /* enda */
    sched_info_queued(p);
    list_add_tail(&p->run_list, array->queue + p->prio);
    __set_bit(p->prio, array->bitmap);
@@ -613,6 +642,10 @@
 */
static void requeue_task(struct task_struct *p, prio_array_t *array)
{
+    /* [email protected] */
+    if (p->flags & PF_KEEPOVER)
+        return;
+    /* enda */
    list_move_tail(&p->run_list, array->queue + p->prio);
}

@@ -2474,6 +2507,61 @@
        cpustat->steal = cputime64_add(cpustat->steal, tmp);
}

+/* [email protected] */
+static int
+keep_check_overload(runqueue_t *rq)
+{
+    if (rq->keep_tick > KEEP_LOAD_TOP)
+        rq->keep_over = 1;
+    else if (rq->keep_over && rq->keep_tick<KEEP_LOAD_BTM)
+        rq->keep_over = 0;
+ keep_tick = rq->keep_tick; /* sysctl var for debug, but only work on UP */
+    keep_over = rq->keep_over; /* like above */
+    return rq->keep_over;
+}
+
+static int
+enqueue_keep(struct task_struct *p, runqueue_t *rq)
+{
+    unsigned long flags;
+
+    spin_lock_irqsave(&rq->keep_lock, flags);
+    if (p->flags & (PF_KEEPOVER|PF_NONREGU)) {
+        spin_unlock_irqrestore(&rq->keep_lock, flags);
+        return 0;
+    }
+    if (p->array)
+        deactivate_task(p, rq);
+    list_add(&p->run_list, &rq->keep);
+    p->flags |= PF_KEEPOVER;
+    spin_unlock_irqrestore(&rq->keep_lock, flags);
+    return 1;
+}
+
+static void
+clear_keep(runqueue_t *rq)
+{
+    struct task_struct *p;
+    unsigned long flags;
+
+    spin_lock_irqsave(&rq->keep_lock, flags);
+    while (!list_empty(&rq->keep)) {
+        p = list_entry(rq->keep.next, struct task_struct, run_list);
+        if (p->flags & PF_KEEPOVER) {
+            list_del(&p->run_list);
+            p->state = TASK_RUNNING;
+            p->flags &= (~PF_KEEPOVER);
+             __activate_task(p, rq);
+        } else {
+                show_stack(p, NULL);
+              panic(KERN_ALERT"dq normal-task%d. ", p->pid);
+        }
+ } + spin_unlock_irqrestore(&rq->keep_lock, flags);
+}
+
+/* enda */
+
/*
 * This function gets called by the timer code, with HZ frequency.
 * We call it with interrupts disabled.
@@ -2492,6 +2580,22 @@

    rq->timestamp_last_tick = now;

+    /* [email protected] */
+    if (in_interrupt()) {
+        if (keep_task(p)) {
+            if ( ++rq->keep_tick>KEEP_TEST_PERIOD )
+                rq->keep_tick = KEEP_TEST_PERIOD;
+        }
+        else if (!--rq->keep_tick) {
+            rq->keep_tick = 1;
+        }
+        spin_lock(&rq->lock);
+        if ( !keep_check_overload(rq) )
+            clear_keep(rq);
+        spin_unlock(&rq->lock);
+    }
+    /* enda */
+
    if (p == rq->idle) {
        if (wake_priority_sleeper(rq))
            goto out;
@@ -2527,6 +2631,19 @@
        }
        goto out_unlock;
    }
+
+    /* [email protected] */
+    if (keep_check_overload(rq)) {
+        if (keep_task(p) && enqueue_keep(p, rq)) {
+            set_tsk_need_resched(p);
+            p->prio = effective_prio(p);
+            p->time_slice = task_timeslice(p);
+            p->first_time_slice = 0;
+            goto out_unlock;
+ } + }
+    /* enda */
+
    if (!--p->time_slice) {
        dequeue_task(p, rq->active);
        set_tsk_need_resched(p);
@@ -2859,6 +2976,7 @@
        rq->expired_timestamp = 0;
        rq->best_expired_prio = MAX_PRIO;
    }
+
    idx = sched_find_first_bit(array->bitmap);
    queue = array->queue + idx;
@@ -3485,10 +3603,20 @@
    BUG_ON(p->array);
    p->policy = policy;
    p->rt_priority = prio;
-    if (policy != SCHED_NORMAL)
-        p->prio = MAX_RT_PRIO-1 - p->rt_priority;
-    else
-        p->prio = p->static_prio;
+    /* [email protected] */
+/*     if (policy != SCHED_NORMAL) */
+/*         p->prio = MAX_RT_PRIO-1 - p->rt_priority; */
+/*     else */
+/*         p->prio = p->static_prio; */
+    switch (policy) {
+    case SCHED_RR:
+    case SCHED_FIFO:
+      p->prio = MAX_RT_PRIO-1 - p->rt_priority;
+      break;
+    default:
+      p->prio = p->static_prio;
+    };
+    /* endm */
}

/**
@@ -3510,9 +3638,12 @@
    /* double check policy once rq lock held */
    if (policy < 0)
        policy = oldpolicy = p->policy;
-    else if (policy != SCHED_FIFO && policy != SCHED_RR &&
-                policy != SCHED_NORMAL)
-            return -EINVAL;
+    /* [email protected] */
+     else if (policy != SCHED_FIFO && policy != SCHED_RR &&
+         policy != SCHED_NORMAL && policy != SCHED_KEEP)
+             return -EINVAL;
+    /* endm */
+
    /*
     * Valid priorities for SCHED_FIFO and SCHED_RR are
     * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL is 0.
@@ -3521,17 +3652,30 @@
        (p->mm &&  param->sched_priority > MAX_USER_RT_PRIO-1) ||
        (!p->mm && param->sched_priority > MAX_RT_PRIO-1))
        return -EINVAL;
-    if ((policy == SCHED_NORMAL) != (param->sched_priority == 0))
+    /* [email protected] */
+    //    if ((policy == SCHED_NORMAL) != (param->sched_priority == 0))
+    //        return -EINVAL;
+    if ((policy == SCHED_NORMAL) != (param->sched_priority == 0)) {
+      if ((policy == SCHED_KEEP) != (param->sched_priority == 0))
+        return -EINVAL;
+    }
+    if (policy==SCHED_KEEP && !p->mm)
        return -EINVAL;
-
+    /* endm */
    /*
     * Allow unprivileged RT tasks to decrease priority:
     */
    if (!capable(CAP_SYS_NICE)) {
        /* can't change policy */
        if (policy != p->policy &&
-            !p->signal->rlim[RLIMIT_RTPRIO].rlim_cur)
-            return -EPERM;
+            !p->signal->rlim[RLIMIT_RTPRIO].rlim_cur)
+          /* [email protected] */
+          //return -EPERM;
+          {
+            if (policy != SCHED_KEEP)
+              return -EPERM;
+          }
+        /* endm */
        /* can't increase priority */
        if (policy != SCHED_NORMAL &&
            param->sched_priority > p->rt_priority &&
@@ -5184,7 +5328,12 @@
        INIT_LIST_HEAD(&rq->migration_queue);
#endif
        atomic_set(&rq->nr_iowait, 0);
-
+        /* [email protected] */
+        rq->keep_lock = SPIN_LOCK_UNLOCKED;
+        INIT_LIST_HEAD(&rq->keep);
+        rq->keep_tick = 1;
+        rq->keep_over = 0;
+ /* enda */ for (j = 0; j < 2; j++) {
            array = rq->arrays + j;
            for (k = 0; k < MAX_PRIO; k++) {


-
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/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux