diff options
| author | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2007-10-07 01:41:46 -0400 |
|---|---|---|
| committer | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2007-10-07 01:41:46 -0400 |
| commit | 3909278d5cb6c06907df1c542a60e09e2ded4e37 (patch) | |
| tree | b3eb071164548f81c021b2b0f076b2f19371933a /include/linux | |
| parent | a75df6573126387eca0e10bd30ce99c11f6a61b1 (diff) | |
adaptive: introduce fixed point math
Introduces fixed point math header stuff and start of predictor support in
sched_adaptive.c
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/fpmath.h | 79 | ||||
| -rw-r--r-- | include/linux/rt_param.h | 41 | ||||
| -rw-r--r-- | include/linux/sched_adaptive.h | 34 |
3 files changed, 143 insertions, 11 deletions
diff --git a/include/linux/fpmath.h b/include/linux/fpmath.h new file mode 100644 index 0000000000..73d89ba210 --- /dev/null +++ b/include/linux/fpmath.h | |||
| @@ -0,0 +1,79 @@ | |||
| 1 | #ifndef __FP_MATH_H__ | ||
| 2 | #define __FP_MATH_H__ | ||
| 3 | |||
| 4 | #define FP_SHIFT 16 | ||
| 5 | #define ROUND_BIT (FP_SHIFT - 1) | ||
| 6 | #define ONE FP(1) | ||
| 7 | |||
| 8 | #define _fp(x) ((fp_t) {x}) | ||
| 9 | |||
| 10 | static inline fp_t FP(long x) | ||
| 11 | { | ||
| 12 | return _fp(((long long) x) << FP_SHIFT); | ||
| 13 | } | ||
| 14 | |||
| 15 | static inline long _floor(fp_t x) | ||
| 16 | { | ||
| 17 | return x.val >> FP_SHIFT; | ||
| 18 | } | ||
| 19 | |||
| 20 | /* FIXME: negative rounding */ | ||
| 21 | static inline long _round(fp_t x) | ||
| 22 | { | ||
| 23 | return _floor(x) + ((x.val >> ROUND_BIT) & 1); | ||
| 24 | } | ||
| 25 | |||
| 26 | /* divide two integers to obtain a fixed point value */ | ||
| 27 | static inline fp_t _frac(long a, long b) | ||
| 28 | { | ||
| 29 | return _fp(FP(a).val / (b)); | ||
| 30 | } | ||
| 31 | |||
| 32 | /* multiply two fixed point values */ | ||
| 33 | static inline fp_t _mul(fp_t a, fp_t b) | ||
| 34 | { | ||
| 35 | return _fp((a.val * b.val) >> FP_SHIFT); | ||
| 36 | } | ||
| 37 | |||
| 38 | static inline fp_t _div(fp_t a, fp_t b) | ||
| 39 | { | ||
| 40 | return _fp(FP(a.val).val / b.val); | ||
| 41 | } | ||
| 42 | |||
| 43 | static inline fp_t _add(fp_t a, fp_t b) | ||
| 44 | { | ||
| 45 | return _fp(a.val + b.val); | ||
| 46 | } | ||
| 47 | |||
| 48 | static inline fp_t _sub(fp_t a, fp_t b) | ||
| 49 | { | ||
| 50 | return _fp(a.val - b.val); | ||
| 51 | } | ||
| 52 | |||
| 53 | static inline fp_t _neg(fp_t x) | ||
| 54 | { | ||
| 55 | return _fp(-x.val); | ||
| 56 | } | ||
| 57 | |||
| 58 | static inline int _leq(fp_t a, fp_t b) | ||
| 59 | { | ||
| 60 | return a.val <= b.val; | ||
| 61 | } | ||
| 62 | |||
| 63 | static inline int _geq(fp_t a, fp_t b) | ||
| 64 | { | ||
| 65 | return a.val >= b.val; | ||
| 66 | } | ||
| 67 | |||
| 68 | static inline int _lt(fp_t a, fp_t b) | ||
| 69 | { | ||
| 70 | return a.val < b.val; | ||
| 71 | } | ||
| 72 | |||
| 73 | static inline int _gt(fp_t a, fp_t b) | ||
| 74 | { | ||
| 75 | return a.val > b.val; | ||
| 76 | } | ||
| 77 | |||
| 78 | |||
| 79 | #endif | ||
diff --git a/include/linux/rt_param.h b/include/linux/rt_param.h index 69aa781a40..c275565835 100644 --- a/include/linux/rt_param.h +++ b/include/linux/rt_param.h | |||
| @@ -23,14 +23,27 @@ typedef struct rt_param { | |||
| 23 | task_class_t class; | 23 | task_class_t class; |
| 24 | } rt_param_t; | 24 | } rt_param_t; |
| 25 | 25 | ||
| 26 | /* fixed point wrapper to force compiler | ||
| 27 | * errors in case of misuse of a fixed point value | ||
| 28 | */ | ||
| 29 | typedef struct | ||
| 30 | { | ||
| 31 | long long val; | ||
| 32 | } fp_t; | ||
| 33 | |||
| 26 | typedef struct { | 34 | typedef struct { |
| 27 | unsigned long exec_cost; | 35 | fp_t weight; |
| 28 | unsigned long period; | 36 | unsigned long period; |
| 29 | /* fixed point */ | 37 | fp_t value; |
| 30 | unsigned long utility; | ||
| 31 | } service_level_t; | 38 | } service_level_t; |
| 32 | 39 | ||
| 33 | typedef struct { | 40 | typedef struct { |
| 41 | fp_t error; | ||
| 42 | fp_t estimate; | ||
| 43 | fp_t accumulated; | ||
| 44 | } predictor_state_t; | ||
| 45 | |||
| 46 | typedef struct { | ||
| 34 | /* when will this task be release the next time? */ | 47 | /* when will this task be release the next time? */ |
| 35 | jiffie_t release; | 48 | jiffie_t release; |
| 36 | /* time instant the last job was released */ | 49 | /* time instant the last job was released */ |
| @@ -111,14 +124,14 @@ typedef struct task_rt_param { | |||
| 111 | * section support. | 124 | * section support. |
| 112 | * TODO: What happens on fork? | 125 | * TODO: What happens on fork? |
| 113 | */ | 126 | */ |
| 114 | __user short* np_flag; | 127 | __user short* np_flag; |
| 115 | 128 | ||
| 116 | /* For the FMLP under PSN-EDF, it is required to make the task | 129 | /* For the FMLP under PSN-EDF, it is required to make the task |
| 117 | * non-preemptive from kernel space. In order not to interfere with | 130 | * non-preemptive from kernel space. In order not to interfere with |
| 118 | * user space, this counter indicates the kernel space np setting. | 131 | * user space, this counter indicates the kernel space np setting. |
| 119 | * kernel_np > 0 => task is non-preemptive | 132 | * kernel_np > 0 => task is non-preemptive |
| 120 | */ | 133 | */ |
| 121 | unsigned int kernel_np; | 134 | unsigned int kernel_np; |
| 122 | 135 | ||
| 123 | /* put information for feedback control stuff and | 136 | /* put information for feedback control stuff and |
| 124 | * information about the performance of the task here | 137 | * information about the performance of the task here |
| @@ -126,15 +139,15 @@ typedef struct task_rt_param { | |||
| 126 | struct { | 139 | struct { |
| 127 | /* How many non-tardy jobs since the last tardy job? */ | 140 | /* How many non-tardy jobs since the last tardy job? */ |
| 128 | unsigned int nontardy_jobs_ctr; | 141 | unsigned int nontardy_jobs_ctr; |
| 129 | long accumulated_error; | 142 | long accumulated_error; |
| 130 | } stats; | 143 | } stats; |
| 131 | 144 | ||
| 132 | rt_times_t times; | 145 | rt_times_t times; |
| 133 | 146 | ||
| 134 | /* This is currently only used by the PFAIR code | 147 | /* This is currently only used by the PFAIR code |
| 135 | * and a prime candidate for cleanup. | 148 | * and a prime candidate for cleanup. |
| 136 | */ | 149 | */ |
| 137 | rt_times_t backup; | 150 | rt_times_t backup; |
| 138 | 151 | ||
| 139 | /* This field can be used by plugins to store where the task | 152 | /* This field can be used by plugins to store where the task |
| 140 | * is currently scheduled. It is the responsibility of the | 153 | * is currently scheduled. It is the responsibility of the |
| @@ -155,9 +168,13 @@ typedef struct task_rt_param { | |||
| 155 | /* Adaptive support. Adaptive tasks will store service levels | 168 | /* Adaptive support. Adaptive tasks will store service levels |
| 156 | * in this (dynamically allocated) structure. | 169 | * in this (dynamically allocated) structure. |
| 157 | */ | 170 | */ |
| 158 | service_level_t* service_level; | 171 | service_level_t* service_level; |
| 159 | unsigned int no_service_levels; | 172 | unsigned int no_service_levels; |
| 160 | unsigned int cur_service_level; | 173 | unsigned int cur_service_level; |
| 174 | |||
| 175 | /* Adaptive support. Store state for weight estimation. | ||
| 176 | */ | ||
| 177 | predictor_state_t predictor_state; | ||
| 161 | } task_rt_param_t; | 178 | } task_rt_param_t; |
| 162 | 179 | ||
| 163 | /* Possible RT flags */ | 180 | /* Possible RT flags */ |
| @@ -180,6 +197,8 @@ typedef struct task_rt_param { | |||
| 180 | #define get_deadline(t) ((t)->rt_param.times.deadline) | 197 | #define get_deadline(t) ((t)->rt_param.times.deadline) |
| 181 | #define get_class(t) ((t)->rt_param.basic_params.class) | 198 | #define get_class(t) ((t)->rt_param.basic_params.class) |
| 182 | 199 | ||
| 200 | #define get_est_weight(t) ((t)->rt_param.predictor_state.estimate) | ||
| 201 | |||
| 183 | #define is_realtime(t) ((t)->rt_param.is_realtime) | 202 | #define is_realtime(t) ((t)->rt_param.is_realtime) |
| 184 | #define is_subject_to_srp(t) ((t)->rt_param.subject_to_srp) | 203 | #define is_subject_to_srp(t) ((t)->rt_param.subject_to_srp) |
| 185 | #define is_hrt(t) \ | 204 | #define is_hrt(t) \ |
diff --git a/include/linux/sched_adaptive.h b/include/linux/sched_adaptive.h new file mode 100644 index 0000000000..eac2f90652 --- /dev/null +++ b/include/linux/sched_adaptive.h | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | #ifndef __ADAPTIVE_H__ | ||
| 2 | #define __ADAPTIVE_H__ | ||
| 3 | |||
| 4 | static inline unsigned long ideal_allocation(fp_t weight, unsigned long delta_t) | ||
| 5 | { | ||
| 6 | return _floor(_mul(weight, FP(delta_t))); | ||
| 7 | } | ||
| 8 | |||
| 9 | /* this makes a whole bunch of linearity assumptions */ | ||
| 10 | static inline fp_t weight_transfer(fp_t from_val, fp_t to_val, | ||
| 11 | fp_t slope, fp_t intercept, fp_t act_weight) | ||
| 12 | { | ||
| 13 | fp_t rel_from, rel_to; | ||
| 14 | rel_from = _add(intercept, _mul(from_val, slope)); | ||
| 15 | rel_to = _add(intercept, _mul(to_val, slope)); | ||
| 16 | return _div(_mul(act_weight, rel_to), rel_from); | ||
| 17 | } | ||
| 18 | |||
| 19 | static inline void update_estimate(predictor_state_t *state, fp_t actual_weight, | ||
| 20 | fp_t a, fp_t b, fp_t c) | ||
| 21 | { | ||
| 22 | fp_t err, new, delta_err; | ||
| 23 | |||
| 24 | err = _sub(actual_weight, state->estimate); | ||
| 25 | state->accumulated = _add(state->accumulated, err); | ||
| 26 | delta_err = _sub(err, state->error); | ||
| 27 | new = _add(_add(_mul(a, err), | ||
| 28 | _mul(b, state->accumulated)), | ||
| 29 | _mul(c, delta_err)); | ||
| 30 | state->estimate = new; | ||
| 31 | state->error = err; | ||
| 32 | } | ||
| 33 | |||
| 34 | #endif | ||
