summaryrefslogtreecommitdiff
path: root/kern/thread.c
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2013-03-11 20:14:54 +0100
committerRichard Braun <rbraun@sceen.net>2013-03-11 20:14:54 +0100
commitc41eee45972dcbeac7a327b9531b7e5ea3757538 (patch)
treed3e0ee851c513079b87784f696f65fad42dfbabe /kern/thread.c
parent98371badcb26e68fde275fa250162692204d6694 (diff)
kern/thread: handle round overflows
Diffstat (limited to 'kern/thread.c')
-rw-r--r--kern/thread.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/kern/thread.c b/kern/thread.c
index 7eb49097..ce52e850 100644
--- a/kern/thread.c
+++ b/kern/thread.c
@@ -61,6 +61,13 @@ struct thread_rt_runq {
};
/*
+ * Initial value of the highest round.
+ *
+ * Set to a high value to make sure overflows are correctly handled.
+ */
+#define THREAD_TS_INITIAL_ROUND ((unsigned long)-10)
+
+/*
* When pulling threads from a run queue, this value is used to determine
* the total number of threads to pull by dividing the number of eligible
* threads with it.
@@ -190,11 +197,11 @@ thread_ts_group_init(struct thread_ts_group *group)
}
static void __init
-thread_ts_runq_init(struct thread_ts_runq *ts_runq, unsigned long round)
+thread_ts_runq_init(struct thread_ts_runq *ts_runq)
{
size_t i;
- ts_runq->round = round;
+ /* The current round is set when the run queue becomes non-empty */
for (i = 0; i < ARRAY_SIZE(ts_runq->group_array); i++)
thread_ts_group_init(&ts_runq->group_array[i]);
@@ -212,8 +219,8 @@ thread_runq_init_ts(struct thread_runq *runq)
runq->ts_weight = 0;
runq->ts_runq_active = &runq->ts_runqs[0];
runq->ts_runq_expired = &runq->ts_runqs[1];
- thread_ts_runq_init(runq->ts_runq_active, 0);
- thread_ts_runq_init(runq->ts_runq_expired, 1);
+ thread_ts_runq_init(runq->ts_runq_active);
+ thread_ts_runq_init(runq->ts_runq_expired);
}
static void __init
@@ -825,6 +832,7 @@ static void
thread_sched_ts_start_next_round(struct thread_runq *runq)
{
struct thread_ts_runq *tmp;
+ unsigned long highest_round;
tmp = runq->ts_runq_expired;
runq->ts_runq_expired = runq->ts_runq_active;
@@ -832,8 +840,11 @@ thread_sched_ts_start_next_round(struct thread_runq *runq)
runq->ts_runq_expired->round = runq->ts_runq_active->round + 1;
if (runq->ts_runq_active->nr_threads != 0) {
- /* TODO Handle round overflows */
- if (runq->ts_runq_active->round > thread_ts_highest_round)
+ highest_round = thread_ts_highest_round;
+
+ /* Compare to 0 to handle overflow */
+ if ((runq->ts_runq_active->round > highest_round)
+ || ((runq->ts_runq_active->round == 0) && (highest_round != 0)))
thread_ts_highest_round = runq->ts_runq_active->round;
thread_sched_ts_restart(runq);
@@ -1151,6 +1162,8 @@ thread_setup(void)
bitmap_zero(thread_active_runqs, MAX_CPUS);
+ thread_ts_highest_round = THREAD_TS_INITIAL_ROUND;
+
kmem_cache_init(&thread_cache, "thread", sizeof(struct thread),
CPU_L1_SIZE, NULL, NULL, NULL, 0);
kmem_cache_init(&thread_stack_cache, "thread_stack", STACK_SIZE,