diff -NurpP linux-2.6.28.3-vs2.3.0.36.5.1/include/linux/sched.h linux-2.6.28.3-vs2.3.0.36.5.2/include/linux/sched.h --- linux-2.6.28.3-vs2.3.0.36.5.1/include/linux/sched.h 2009-02-05 12:35:44.000000000 +0100 +++ linux-2.6.28.3-vs2.3.0.36.5.2/include/linux/sched.h 2009-02-06 00:35:07.000000000 +0100 @@ -175,12 +175,13 @@ extern unsigned long long time_sync_thre #define TASK_UNINTERRUPTIBLE 2 #define __TASK_STOPPED 4 #define __TASK_TRACED 8 +#define TASK_ONHOLD 16 /* in tsk->exit_state */ -#define EXIT_ZOMBIE 16 -#define EXIT_DEAD 32 +#define EXIT_ZOMBIE 32 +#define EXIT_DEAD 64 /* in tsk->state again */ -#define TASK_DEAD 64 -#define TASK_WAKEKILL 128 +#define TASK_DEAD 128 +#define TASK_WAKEKILL 256 /* Convenience macros for the sake of set_task_state */ #define TASK_KILLABLE (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE) @@ -1094,7 +1095,9 @@ struct task_struct { const struct sched_class *sched_class; struct sched_entity se; struct sched_rt_entity rt; - +#ifdef CONFIG_VSERVER_HARDCPU + struct list_head hq; +#endif #ifdef CONFIG_PREEMPT_NOTIFIERS /* list of struct preempt_notifier: */ struct hlist_head preempt_notifiers; diff -NurpP linux-2.6.28.3-vs2.3.0.36.5.1/kernel/sched.c linux-2.6.28.3-vs2.3.0.36.5.2/kernel/sched.c --- linux-2.6.28.3-vs2.3.0.36.5.1/kernel/sched.c 2009-01-19 00:14:21.000000000 +0100 +++ linux-2.6.28.3-vs2.3.0.36.5.2/kernel/sched.c 2009-02-07 04:44:24.000000000 +0100 @@ -594,6 +584,16 @@ struct rq { #endif struct hrtimer hrtick_timer; #endif + unsigned long norm_time; + unsigned long idle_time; +#ifdef CONFIG_VSERVER_IDLETIME + int idle_skip; +#endif +#ifdef CONFIG_VSERVER_HARDCPU + struct list_head hold_queue; + unsigned long nr_onhold; + int idle_tokens; +#endif #ifdef CONFIG_SCHEDSTATS /* latency stats */ @@ -4462,6 +4462,8 @@ pick_next_task(struct rq *rq, struct tas } } +#include "sched_hard.h" + /* * schedule() is the main scheduler function. */ @@ -4509,6 +4511,11 @@ need_resched_nonpreemptible: idle_balance(cpu, rq); prev->sched_class->put_prev_task(rq, prev); + + vx_set_rq_time(rq, jiffies); /* update time */ + vx_schedule(prev, rq, cpu); /* hold if over limit */ + vx_try_unhold(rq, cpu); /* unhold if refilled */ + next = pick_next_task(rq, prev); if (likely(prev != next)) { @@ -8297,7 +8304,10 @@ void __init sched_init(void) #endif #endif /* CONFIG_FAIR_GROUP_SCHED */ - +#ifdef CONFIG_VSERVER_HARDCPU + INIT_LIST_HEAD(&rq->hold_queue); + rq->nr_onhold = 0; +#endif rq->rt.rt_runtime = def_rt_bandwidth.rt_runtime; #ifdef CONFIG_RT_GROUP_SCHED INIT_LIST_HEAD(&rq->leaf_rt_rq_list); diff -NurpP linux-2.6.28.3-vs2.3.0.36.5.1/kernel/sched_hard.h linux-2.6.28.3-vs2.3.0.36.5.2/kernel/sched_hard.h --- linux-2.6.28.3-vs2.3.0.36.5.1/kernel/sched_hard.h 2008-12-30 21:36:10.000000000 +0100 +++ linux-2.6.28.3-vs2.3.0.36.5.2/kernel/sched_hard.h 2009-02-07 04:12:06.000000000 +0100 @@ -90,12 +90,17 @@ void __vx_save_max_idle(int ret, int *mi static inline void vx_hold_task(struct task_struct *p, struct rq *rq) { - __deactivate_task(p, rq); + // printk("@ hold_task(%p)\n", p); + if (likely(p->se.on_rq)) + dequeue_task(rq, p, 0); + else + printk("@ wrong assumption on rq (%p)\n", p); p->state |= TASK_ONHOLD; /* a new one on hold */ rq->nr_onhold++; vxm_hold_task(p, rq); - list_add_tail(&p->run_list, &rq->hold_queue); + list_add_tail(&p->hq, &rq->hold_queue); + // list_add_tail(&p->run_list, &rq->hold_queue); } /* @@ -104,16 +109,15 @@ void vx_hold_task(struct task_struct *p, static inline void vx_unhold_task(struct task_struct *p, struct rq *rq) { - list_del(&p->run_list); + // printk("@ unhold_task(%p)\n", p); + list_del_init(&p->hq); + // list_del(&p->run_list); /* one less waiting */ rq->nr_onhold--; p->state &= ~TASK_ONHOLD; - enqueue_task(p, rq->expired); - inc_nr_running(p, rq); + enqueue_task(rq, p, 0); + // ? inc_nr_running(p, rq); vxm_unhold_task(p, rq); - - if (p->static_prio < rq->best_expired_prio) - rq->best_expired_prio = p->static_prio; } unsigned long nr_onhold(void) @@ -187,7 +191,7 @@ void vx_try_unhold(struct rq *rq, int cp struct _vx_sched_pc *sched_pc; struct task_struct *p; - p = list_entry(l, struct task_struct, run_list); + p = list_entry(l, struct task_struct, hq); /* don't bother with same context */ if (vxi == p->vx_info) continue; diff -NurpP linux-2.6.28.3-vs2.3.0.36.5.1/kernel/timer.c linux-2.6.28.3-vs2.3.0.36.5.2/kernel/timer.c --- linux-2.6.28.3-vs2.3.0.36.5.1/kernel/timer.c 2009-01-19 00:14:21.000000000 +0100 +++ linux-2.6.28.3-vs2.3.0.36.5.2/kernel/timer.c 2009-02-06 02:36:54.000000000 +0100 @@ -1037,6 +1037,25 @@ void account_process_tick(struct task_st } #endif +static inline +void __vx_consume_token(struct _vx_sched_pc *sched_pc) +{ + sched_pc->tokens--; +} + +static inline +void vx_hard_tick(struct task_struct *p, int cpu) +{ + struct vx_info *vxi = p->vx_info; + + if (vx_info_flags(vxi, VXF_SCHED_HARD|VXF_SCHED_PRIO, 0)) { + struct _vx_sched_pc *sched_pc = + &vx_per_cpu(vxi, sched_pc, cpu); + + __vx_consume_token(sched_pc); + } +} + /* * Called from the timer interrupt handler to charge one tick to the current * process. user_tick is 1 if the tick is user time, 0 for system. @@ -1053,6 +1072,7 @@ void update_process_times(int user_tick) rcu_check_callbacks(cpu, user_tick); printk_tick(); scheduler_tick(); + vx_hard_tick(p, cpu); run_posix_cpu_timers(p); } diff -NurpP linux-2.6.28.3-vs2.3.0.36.5.1/kernel/vserver/sched.c linux-2.6.28.3-vs2.3.0.36.5.2/kernel/vserver/sched.c --- linux-2.6.28.3-vs2.3.0.36.5.1/kernel/vserver/sched.c 2008-12-30 21:36:10.000000000 +0100 +++ linux-2.6.28.3-vs2.3.0.36.5.2/kernel/vserver/sched.c 2009-02-07 03:35:02.000000000 +0100 @@ -77,6 +77,7 @@ int vx_tokens_recalc(struct _vx_sched_pc /* how much time did pass? */ delta = *norm_time - sched_pc->norm_time; + // printk("@ %ld, %ld, %ld\n", *norm_time, sched_pc->norm_time, jiffies); vxd_check_range(delta, 0, INT_MAX); if (delta >= sched_pc->interval[0]) { @@ -155,7 +156,7 @@ skip_idle: on_hold: tokens = sched_pc->tokens_min - tokens; sched_pc->flags = flags; - BUG_ON(tokens < 0); + // BUG_ON(tokens < 0); probably doesn't hold anymore #ifdef CONFIG_VSERVER_HARDCPU /* next interval? */