-
Notifications
You must be signed in to change notification settings - Fork 137
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Scheduler: implement fair scheduling between user threads #1759
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@@ -240,7 +247,8 @@ static void thread_resume(context ctx) | |||
static void thread_schedule_return(context ctx) | |||
{ | |||
thread t = (thread)ctx; | |||
assert(enqueue_irqsafe(t->scheduling_queue, &t->thread_return)); | |||
thread_cputime_update(t); /* so that it is scheduled based on how much CPU time it used */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't the thread be paused at this point, with t->start_time == 0, thus making the call to thread_cputime_update() a no-op here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a user thread is interrupted by a hardware interrupt, the interrupt handler calls context_schedule_return() without the thread being paused. Also, when the Unix fault handler raises a signal or resolves a page fault without blocking, it calls schedule_thread(), again without the thread being paused.
When an unhandled page fault occurs in a syscall context, the syscall is abandoned and a SIGSEGV is raised. The syscall context should not be reused by other threads until the offending thread runs the signal handler, otherwise if another thread executes a syscall, the assert(sc->context.refcount.c == 1) in the syscall handler fails. This commit fxes the above issue by adding a call to orphan_syscall_context() in the Unix fault handler, so that the syscall context is not reused by any threads that might run on the same CPU before the signal handler of the offending thread. Since orphaning a context releases its refcount, a call to context_release_refcount() is being removed from the arch-specific exception handlers.
This change introduces a new scheduling algorithm that assigns CPU resources to a task based on how much CPU time the task used in the past. It uses a priority queue where tasks are ordered based on their CPU time: when a task is enqueued, it is positioned according to the time it has been running since it was last scheduled; when a task is dequeued, its CPU time is subtracted from the CPU time of any other tasks in the queue, so that their priority in the queue is increased; this is implemented by storing a reference CPU time in the queue (min_runtime struct member), which prevents long-running tasks from being starved by newly created tasks. This algorithm is applied for scheduling user threads, so that CPU time is distributed fairly between all runnable threads.
684d9b9
to
20ef40d
Compare
This change introduces a new scheduling algorithm that assigns CPU resources to a task based on how much CPU time the task used in the past. It uses a priority queue where tasks are ordered based on their CPU time: when a task is enqueued, it is positioned according to the time it has been running since it was last scheduled; when a task is dequeued, its CPU time is subtracted from the CPU time of any other tasks in the queue, so that their priority in the queue is increased; this is implemented by storing a reference CPU time in the queue (min_runtime struct member), which prevents long-running tasks from being starved by newly created tasks.
This algorithm is applied for scheduling user threads, so that CPU time is distributed fairly between all runnable threads.
The first commit is a fix to a pre-existing bug that has been exposed by modifying the execution order of runnable user threads.