void vx_tokens_set(struct vx_info *vxi, int tokens) {
int class = CLASS(vxi);
+ uint64_t tmp;
+
+ tmp = GLOBAL_TICKS(vxi);
+ tmp -= tokens * TICKS_PER_TOKEN(vxi);
- vxi->sched.ticks[class] = GLOBAL_TICKS(vxi);
- vxi->sched.ticks[class] -= tokens * TICKS_PER_TOKEN(vxi);
+ vxi->sched.ticks[class] = tmp;
}
void vx_scheduler_tick(void) {
int vx_tokens_avail(struct vx_info *vxi)
{
- uint64_t diff;
+ uint64_t diff, max_ticks;
int tokens;
- long rem;
+ long tpt, rem;
int class = CLASS(vxi);
if (vxi->sched.state[class] == SCH_UNINITIALIZED) {
/* Use of fixed-point arithmetic in these calculations leads to
* some limitations. These should be made explicit.
*/
+ max_ticks = (tpt = TICKS_PER_TOKEN(vxi));
+ max_ticks *= vxi->sched.tokens_max;
diff = GLOBAL_TICKS(vxi) - vxi->sched.ticks[class];
- tokens = div_long_long_rem(diff, TICKS_PER_TOKEN(vxi), &rem);
- if (tokens > vxi->sched.tokens_max) {
+ /* Avoid an overflow from div_long_long_rem */
+ if (diff >= max_ticks) {
vx_tokens_set(vxi, vxi->sched.tokens_max);
tokens = vxi->sched.tokens_max;
+ } else {
+ /* Divide ticks by ticks per token to get tokens */
+ tokens = div_long_long_rem(diff, tpt, &rem);
}
atomic_set(&vxi->sched.tokens, tokens);
int class = CLASS(vxi);
vxi->sched.ticks[class] += TICKS_PER_TOKEN(vxi);
+ atomic_dec(&vxi->sched.tokens);
}
/*