1 /* kernel/ckrm_sched.c - Supporting functions for ckrm scheduling
3 * Copyright (C) Haoqiang Zheng, IBM Corp. 2004
4 * (C) Hubertus Franke, IBM Corp. 2004
6 * Latest version, more details at http://ckrm.sf.net
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
15 #include <linux/init.h>
16 #include <linux/ckrm_sched.h>
18 rwlock_t class_list_lock = RW_LOCK_UNLOCKED;
19 LIST_HEAD(active_cpu_classes); // list of active cpu classes; anchor
21 struct ckrm_cpu_class default_cpu_class_obj;
23 struct ckrm_cpu_class * get_default_cpu_class(void) {
24 return (&default_cpu_class_obj);
27 /*******************************************************/
29 /*******************************************************/
31 static inline void check_inactive_class(ckrm_lrq_t * lrq,CVT_t cur_cvt)
36 //just a safty measure
37 if (unlikely(! cur_cvt))
40 #ifndef INTERACTIVE_BONUS_SUPPORT
41 #warning "ACB taking out interactive bonus calculation"
45 * Always leaving a small bonus for inactive classes
46 * allows them to compete for cycles immediately when the become
47 * active. This should improve interactive behavior
49 bonus = INTERACTIVE_BONUS(lrq);
52 //cvt can't be negative
54 min_cvt = cur_cvt - bonus;
58 if (lrq->local_cvt < min_cvt) {
61 lost_cvt = scale_cvt(min_cvt - lrq->local_cvt,lrq);
62 lrq->local_cvt = min_cvt;
64 /* add what the class lost to its savings*/
65 lrq->savings += lost_cvt;
66 if (lrq->savings > MAX_SAVINGS)
67 lrq->savings = MAX_SAVINGS;
68 } else if (lrq->savings) {
70 *if a class saving and falling behind
71 * then start to use it saving in a leaking bucket way
75 savings_used = scale_cvt((lrq->local_cvt - min_cvt),lrq);
76 if (savings_used > lrq->savings)
77 savings_used = lrq->savings;
79 if (savings_used > SAVINGS_LEAK_SPEED)
80 savings_used = SAVINGS_LEAK_SPEED;
82 BUG_ON(lrq->savings < savings_used);
83 lrq->savings -= savings_used;
84 unscale_cvt(savings_used,lrq);
85 BUG_ON(lrq->local_cvt < savings_used);
86 #ifndef CVT_SAVINGS_SUPPORT
87 #warning "ACB taking out cvt saving"
89 lrq->local_cvt -= savings_used;
95 * return the max_cvt of all the classes
97 static inline CVT_t get_max_cvt(int this_cpu)
99 struct ckrm_cpu_class *clsptr;
105 /*update class time, at the same time get max_cvt */
106 list_for_each_entry(clsptr, &active_cpu_classes, links) {
107 lrq = get_ckrm_lrq(clsptr, this_cpu);
108 if (lrq->local_cvt > max_cvt)
109 max_cvt = lrq->local_cvt;
116 * update_class_cputime - updates cvt of inactive classes
117 * -- an inactive class shouldn't starve others when it comes back
118 * -- the cpu time it lost when it's inactive should be accumulated
119 * -- its accumulated saving should be compensated (in a leaky bucket fashion)
121 * class_list_lock must have been acquired
123 void update_class_cputime(int this_cpu)
125 struct ckrm_cpu_class *clsptr;
130 * a class's local_cvt must not be significantly smaller than min_cvt
131 * of active classes otherwise, it will starve other classes when it
134 * Hence we keep all local_cvt's within a range of the min_cvt off
135 * all active classes (approximated by the local_cvt of the currently
136 * running class) and account for how many cycles where thus taken
137 * from an inactive class building a savings (not to exceed a few seconds)
138 * for a class to gradually make up upon reactivation, without
139 * starvation of other classes.
142 cur_cvt = get_local_cur_cvt(this_cpu);
145 * cur_cvt == 0 means the system is now idle
146 * in this case, we use max_cvt as cur_cvt
147 * max_cvt roughly represents the cvt of the class
148 * that has just finished running
150 * fairness wouldn't be a problem since we account for whatever lost in savings
151 * if the system is not busy, the system responsiveness is not a problem.
152 * still fine if the sytem is busy, but happened to be idle at this certain point
153 * since bias toward interactive classes (class priority) is a more important way to improve system responsiveness
155 if (unlikely(! cur_cvt)) {
156 cur_cvt = get_max_cvt(this_cpu);
161 * - check the local cvt of all the classes
162 * - update total_ns received by the class
163 * - do a usage sampling for the whole class
165 list_for_each_entry(clsptr, &active_cpu_classes, links) {
166 lrq = get_ckrm_lrq(clsptr, this_cpu);
168 spin_lock(&clsptr->stat.stat_lock);
169 clsptr->stat.total_ns += lrq->uncounted_ns;
170 ckrm_sample_usage(clsptr);
171 spin_unlock(&clsptr->stat.stat_lock);
172 lrq->uncounted_ns = 0;
174 check_inactive_class(lrq,cur_cvt);
178 /*******************************************************/
179 /* PID load balancing stuff */
180 /*******************************************************/
181 #define PID_SAMPLE_T 32
187 * sample pid load periodically
189 void ckrm_load_sample(ckrm_load_t* pid,int cpu)
194 if (jiffies % PID_SAMPLE_T)
197 adjust_local_weight();
199 load = ckrm_cpu_load(cpu);
200 err = load - pid->load_p;
208 long pid_get_pressure(ckrm_load_t* ckrm_load, int local_group)
211 pressure = ckrm_load->load_p * PID_KP;
212 pressure += ckrm_load->load_i * PID_KI;
213 pressure += ckrm_load->load_d * PID_KD;