* [Question]How to restrict some kind of task?
@ 2005-11-15 10:18 liyu
2005-11-15 10:21 ` Con Kolivas
0 siblings, 1 reply; 8+ messages in thread
From: liyu @ 2005-11-15 10:18 UTC (permalink / raw)
To: LKML
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;
}
These code are so simple, but is make system crash, if I create some
XYZ policy task.
I tried the more radical idea (remove these tasks from runqueue to
our one
list_head that spin_lock protected), but crash again and again.
if need, I can paste my global patch.
Thanks in advanced.
-liyu
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [Question]How to restrict some kind of task? 2005-11-15 10:18 [Question]How to restrict some kind of task? liyu @ 2005-11-15 10:21 ` Con Kolivas 2005-11-16 1:16 ` liyu 0 siblings, 1 reply; 8+ messages in thread From: Con Kolivas @ 2005-11-15 10:21 UTC (permalink / raw) To: liyu; +Cc: LKML 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 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Question]How to restrict some kind of task? 2005-11-15 10:21 ` Con Kolivas @ 2005-11-16 1:16 ` liyu 2005-11-17 6:20 ` liyu 0 siblings, 1 reply; 8+ messages in thread From: liyu @ 2005-11-16 1:16 UTC (permalink / raw) To: Con Kolivas; +Cc: LKML 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> +/* liyu@ccoss.com.cn */ +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 + /* liyu@ccoss.com.cn */ + 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) { +/* liyu@ccoss.com.cn */ + 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) { + /* liyu@ccoss.com.cn */ + 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) { + /* liyu@ccoss.com.cn */ + 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); } +/* liyu@ccoss.com.cn */ +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; + /* liyu@ccoss.com.cn */ + 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; } + + /* liyu@ccoss.com.cn */ + 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; + /* liyu@ccoss.com.cn */ +/* 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; + /* liyu@ccoss.com.cn */ + 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)) + /* liyu@ccoss.com.cn */ + // 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) + /* liyu@ccoss.com.cn */ + //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); - + /* liyu@ccoss.com.cn */ + 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++) { ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Question]How to restrict some kind of task? 2005-11-16 1:16 ` liyu @ 2005-11-17 6:20 ` liyu 2005-11-17 9:57 ` Con Kolivas 0 siblings, 1 reply; 8+ messages in thread From: liyu @ 2005-11-17 6:20 UTC (permalink / raw) Cc: Con Kolivas, LKML liyu wrote: > 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> > > +/* liyu@ccoss.com.cn */ > +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 > + /* liyu@ccoss.com.cn */ > + 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) > { > +/* liyu@ccoss.com.cn */ > + 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) > { > + /* liyu@ccoss.com.cn */ > + 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) > { > + /* liyu@ccoss.com.cn */ > + 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); > } > > +/* liyu@ccoss.com.cn */ > +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; > > + /* liyu@ccoss.com.cn */ > + 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; > } > + > + /* liyu@ccoss.com.cn */ > + 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; > + /* liyu@ccoss.com.cn */ > +/* 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; > + /* liyu@ccoss.com.cn */ > + 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)) > + /* liyu@ccoss.com.cn */ > + // 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) > + /* liyu@ccoss.com.cn */ > + //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); > - > + /* liyu@ccoss.com.cn */ > + 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 majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > Please read the FAQ at http://www.tux.org/lkml/ > > I fixed it. we should insert code start of enqueue_task(): static void enqueue_task(struct task_struct *p, prio_array_t *array) { unsigned long flags; spin_lock_irqsave(&(task_rq(p)->keep_lock), flags); if (p->flags & PF_KEEPOVER) { list_del(&p->run_list); p->state = TASK_RUNNING; p->flags &= ~PF_KEEPOVER; } spin_unlock_irqrestore(&(task_rq(p)->keep_lock), flags); .... } However, this patch still have problem, it may lock entire system. I am trying to catch this bug~. -Liyu ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Question]How to restrict some kind of task? 2005-11-17 6:20 ` liyu @ 2005-11-17 9:57 ` Con Kolivas 2005-11-18 8:37 ` [Question] spin_lock in interrupt handler liyu 0 siblings, 1 reply; 8+ messages in thread From: Con Kolivas @ 2005-11-17 9:57 UTC (permalink / raw) To: liyu; +Cc: LKML On Thu, 17 Nov 2005 17:20, liyu wrote: > I fixed it. we should insert code start of enqueue_task(): > > static void enqueue_task(struct task_struct *p, prio_array_t *array) > { > unsigned long flags; > > spin_lock_irqsave(&(task_rq(p)->keep_lock), flags); > if (p->flags & PF_KEEPOVER) { > list_del(&p->run_list); > p->state = TASK_RUNNING; > p->flags &= ~PF_KEEPOVER; > } > spin_unlock_irqrestore(&(task_rq(p)->keep_lock), flags); > > .... > } > However, this patch still have problem, it may lock entire system. > > I am trying to catch this bug~. The obvious bug is that there are places that expect a task to be added to the run list after it has called enqueue_task and you've broken that expectation. The locking in the rest of your patch did not look too robust, but I don't have time to review it sorry. Cheers, Con ^ permalink raw reply [flat|nested] 8+ messages in thread
* [Question] spin_lock in interrupt handler. 2005-11-17 9:57 ` Con Kolivas @ 2005-11-18 8:37 ` liyu 2005-11-18 22:44 ` Steven Rostedt 0 siblings, 1 reply; 8+ messages in thread From: liyu @ 2005-11-18 8:37 UTC (permalink / raw) Cc: LKML Hi, every one in LKML. I have one question about how to use spin_lock. I read Documentation/spinlocks.txt wrote by Linus. The Lesson 1 and 2 are simple for me. But I confused in Lesson 3. The most doublt is why we can not use spin_lock_irq*() version in interrupt handler? At i386, I known the interrupt is disabled in interrupt handler. I think this feature is supplied in handware-level. The spin_lock_irqrestore() will use 'sti' instruction internal, it will change interrupt mask bit in FLAGS register, do this have re-enable interrupt, even in interrput handler? I can not sure this. Thanks in advanced. -liyu ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Question] spin_lock in interrupt handler. 2005-11-18 8:37 ` [Question] spin_lock in interrupt handler liyu @ 2005-11-18 22:44 ` Steven Rostedt 2005-11-21 1:13 ` liyu 0 siblings, 1 reply; 8+ messages in thread From: Steven Rostedt @ 2005-11-18 22:44 UTC (permalink / raw) To: liyu; +Cc: LKML On Fri, 2005-11-18 at 16:37 +0800, liyu wrote: > Hi, every one in LKML. > > I have one question about how to use spin_lock. > > I read Documentation/spinlocks.txt wrote by Linus. The Lesson 1 and > 2 are simple for me. > But I confused in Lesson 3. The most doublt is why we can not use > spin_lock_irq*() version in > interrupt handler? > > At i386, I known the interrupt is disabled in interrupt handler. I > think this feature is > supplied in handware-level. The spin_lock_irqrestore() will use 'sti' > instruction internal, it will change interrupt mask bit in FLAGS > register, do this have re-enable interrupt, even in interrput handler? I > can not sure this. Hello once again Liyu ;-) I don't see where he says you can't use spin_lock_irq* in interrupt handlers. He only says that you are safe to use the non-irq* versions IFF (if and only if) the locks are not used in interrupts. So, (copied from the text itself): --- The reasons you mustn't use these versions if you have interrupts that play with the spinlock is that you can get deadlocks: spin_lock(&lock); ... <- interrupt comes in: spin_lock(&lock); --- If you hold a spin lock without interrupts disabled, and an interrupt happens on the same CPU that holds the lock, and that interrupt handler tries to grab the lock it will just spin until that lock is released, which will _never_ happen, since the lock is held by the process that was interrupted, and will not run until the interrupt (that's spinning) is done. So you have a deadlock. Clear? -- Steve ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Question] spin_lock in interrupt handler. 2005-11-18 22:44 ` Steven Rostedt @ 2005-11-21 1:13 ` liyu 0 siblings, 0 replies; 8+ messages in thread From: liyu @ 2005-11-21 1:13 UTC (permalink / raw) To: Steven Rostedt; +Cc: LKML Steven Rostedt wrote: >On Fri, 2005-11-18 at 16:37 +0800, liyu wrote: > > >>Hi, every one in LKML. >> >> I have one question about how to use spin_lock. >> >> I read Documentation/spinlocks.txt wrote by Linus. The Lesson 1 and >>2 are simple for me. >>But I confused in Lesson 3. The most doublt is why we can not use >>spin_lock_irq*() version in >>interrupt handler? >> >> At i386, I known the interrupt is disabled in interrupt handler. I >>think this feature is >>supplied in handware-level. The spin_lock_irqrestore() will use 'sti' >>instruction internal, it will change interrupt mask bit in FLAGS >>register, do this have re-enable interrupt, even in interrput handler? I >>can not sure this. >> >> > >Hello once again Liyu ;-) > >I don't see where he says you can't use spin_lock_irq* in interrupt >handlers. He only says that you are safe to use the non-irq* versions >IFF (if and only if) the locks are not used in interrupts. > >So, (copied from the text itself): > >--- >The reasons you mustn't use these versions if you have interrupts that >play with the spinlock is that you can get deadlocks: > > spin_lock(&lock); > ... > <- interrupt comes in: > spin_lock(&lock); >--- > >If you hold a spin lock without interrupts disabled, and an interrupt >happens on the same CPU that holds the lock, and that interrupt handler >tries to grab the lock it will just spin until that lock is released, >which will _never_ happen, since the lock is held by the process that >was interrupted, and will not run until the interrupt (that's spinning) >is done. So you have a deadlock. > >Clear? > >-- Steve > > > > >- >To unsubscribe from this list: send the line "unsubscribe linux-kernel" in >the body of a message to majordomo@vger.kernel.org >More majordomo info at http://vger.kernel.org/majordomo-info.html >Please read the FAQ at http://www.tux.org/lkml/ > > > > Hi, Steven, Nice to meet you too ;) (These are the words that I first studied in English class.) Yes, I am clear, I think I understand it in wrong direction before. Good Luck. -liyu ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2005-11-21 1:12 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2005-11-15 10:18 [Question]How to restrict some kind of task? liyu 2005-11-15 10:21 ` Con Kolivas 2005-11-16 1:16 ` liyu 2005-11-17 6:20 ` liyu 2005-11-17 9:57 ` Con Kolivas 2005-11-18 8:37 ` [Question] spin_lock in interrupt handler liyu 2005-11-18 22:44 ` Steven Rostedt 2005-11-21 1:13 ` liyu
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox