--- linux-2.6.1-batch6/kernel/sched.c 2004-01-21 02:00:21.000000000 +1100 +++ linux-2.6.1-ht8/kernel/sched.c 2004-01-22 12:49:22.000000000 +1100 @@ -216,6 +216,7 @@ struct runqueue { struct mm_struct *prev_mm; prio_array_t *active, *expired, *batch, arrays[3]; int best_expired_prio, prev_cpu_load[NR_CPUS]; + unsigned long cpu; #ifdef CONFIG_NUMA atomic_t *node_nr_running; int prev_node_load[MAX_NUMNODES]; @@ -233,6 +234,10 @@ static DEFINE_PER_CPU(struct runqueue, r #define task_rq(p) cpu_rq(task_cpu(p)) #define cpu_curr(cpu) (cpu_rq(cpu)->curr) +#define ht_active (cpu_has_ht && smp_num_siblings > 1) +#define ht_siblings(cpu1, cpu2) (ht_active && \ + cpu_sibling_map[(cpu1)] == (cpu2)) + /* * Default context-switch locking: */ @@ -1194,8 +1199,9 @@ can_migrate_task(task_t *tsk, runqueue_t { unsigned long delta = sched_clock() - tsk->timestamp; - if (!idle && (delta <= JIFFIES_TO_NS(cache_decay_ticks))) - return 0; + if (!idle && (delta <= JIFFIES_TO_NS(cache_decay_ticks)) && + !ht_siblings(this_cpu, task_cpu(tsk))) + return 0; if (task_running(rq, tsk)) return 0; if (!cpu_isset(this_cpu, tsk->cpus_allowed)) @@ -1230,15 +1236,23 @@ static void load_balance(runqueue_t *thi imbalance /= 2; /* + * For hyperthread siblings take tasks from the active array + * to get cache-warm tasks since they share caches. + */ + if (ht_siblings(this_cpu, busiest->cpu)) + array = busiest->active; + /* * We first consider expired tasks. Those will likely not be * executed in the near future, and they are most likely to * be cache-cold, thus switching CPUs has the least effect * on them. */ - if (busiest->expired->nr_active) - array = busiest->expired; - else - array = busiest->active; + else { + if (busiest->expired->nr_active) + array = busiest->expired; + else + array = busiest->active; + } new_array: /* Start searching at priority 0: */ @@ -1249,9 +1263,16 @@ skip_bitmap: else idx = find_next_bit(array->bitmap, MAX_PRIO, idx); if (idx >= MAX_PRIO) { - if (array == busiest->expired) { - array = busiest->active; - goto new_array; + if (ht_siblings(this_cpu, busiest->cpu)){ + if (array == busiest->active) { + array = busiest->expired; + goto new_array; + } + } else { + if (array == busiest->expired) { + array = busiest->active; + goto new_array; + } } goto out_unlock; } @@ -1587,6 +1608,20 @@ need_resched: if (!rq->nr_running) { next = rq->idle; rq->expired_timestamp = 0; +#ifdef CONFIG_SMP + if (ht_active) { + /* + * If a HT sibling task is sleeping due to + * priority or batch reasons wake it up now + */ + runqueue_t *htrq; + htrq = cpu_rq(cpu_sibling_map[(rq->cpu)]); + + if (htrq->curr == htrq->idle && + htrq->nr_running) + resched_task(htrq->idle); + } +#endif goto switch_tasks; } } @@ -1617,6 +1652,62 @@ need_resched: queue = array->queue + idx; next = list_entry(queue->next, task_t, run_list); +#ifdef CONFIG_SMP + if (ht_active && next->mm && !rt_task(next)) { + runqueue_t *htrq; + htrq = cpu_rq(cpu_sibling_map[(rq->cpu)]); + task_t *htcurr; + htcurr = htrq->curr; + + if (likely(htcurr->mm && !rt_task(htcurr))){ + /* + * If a user task with dynamic priority of >10 or + * static priority of >5 difference from another + * running user task on the hyperthread sibling + * is trying to schedule delay it to prevent a + * lower priority task from using an unfair + * proportion of the physical cpu resources. + */ + if (next->prio > htcurr->prio + 10 || + next->static_prio > htcurr->static_prio + 5) { + next = rq->idle; + goto switch_tasks; + } + + if (unlikely(batch_task(next))) { + /* + * Prevent a batch task from running if a user + * non batch task is running on a HT sibling. + */ + if (htrq->nr_running > htrq->nr_batch) { + dequeue_task(next, array); + enqueue_task(next, rq->batch); + next = rq->idle; + goto switch_tasks; + } + } else { + /* + * Reschedule a lower priority or batch task + * on the HT sibling if present. + */ + if (htcurr->prio > next->prio + 10 || + htcurr->static_prio > next->static_prio + 5 || + batch_task(htcurr)) + resched_task(htcurr); + else + /* + * If a HT sibling task has been put to sleep + * previously for priority reasons wake it up + * now. + */ + if (htcurr == htrq->idle && + htrq->nr_running > htrq->nr_batch) + resched_task(htcurr); + } + } + } +#endif + if (next->activated > 0) { unsigned long long delta = now - next->timestamp; @@ -2878,6 +2969,7 @@ void __init sched_init(void) prio_array_t *array; rq = cpu_rq(i); + rq->cpu = (unsigned long)(i); rq->active = rq->arrays; rq->expired = rq->arrays + 1; rq->batch = rq->arrays + 2;