mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 18:17:34 +00:00
Kernel: Scheduler donations need to verify that the beneficiary is valid.
Add a Thread::is_thread(void*) helper that we can use to check that the incoming donation beneficiary is a valid thread. The O(n) here is a bit sad and we should eventually rethink the process/thread table data structures.
This commit is contained in:
parent
6bb0dbe8bf
commit
c59f8cd663
3 changed files with 19 additions and 5 deletions
|
@ -243,11 +243,14 @@ bool Scheduler::pick_next()
|
||||||
|
|
||||||
bool Scheduler::donate_to(Thread* beneficiary, const char* reason)
|
bool Scheduler::donate_to(Thread* beneficiary, const char* reason)
|
||||||
{
|
{
|
||||||
|
InterruptDisabler disabler;
|
||||||
|
if (!Thread::is_thread(beneficiary))
|
||||||
|
return false;
|
||||||
|
|
||||||
(void)reason;
|
(void)reason;
|
||||||
unsigned ticks_left = current->ticks_left();
|
unsigned ticks_left = current->ticks_left();
|
||||||
if (!beneficiary || beneficiary->state() != Thread::Runnable || ticks_left <= 1) {
|
if (!beneficiary || beneficiary->state() != Thread::Runnable || ticks_left <= 1)
|
||||||
return yield();
|
return yield();
|
||||||
}
|
|
||||||
|
|
||||||
unsigned ticks_to_donate = min(ticks_left - 1, time_slice_for(beneficiary->process().priority()));
|
unsigned ticks_to_donate = min(ticks_left - 1, time_slice_for(beneficiary->process().priority()));
|
||||||
#ifdef SCHEDULER_DEBUG
|
#ifdef SCHEDULER_DEBUG
|
||||||
|
@ -256,7 +259,7 @@ bool Scheduler::donate_to(Thread* beneficiary, const char* reason)
|
||||||
context_switch(*beneficiary);
|
context_switch(*beneficiary);
|
||||||
beneficiary->set_ticks_left(ticks_to_donate);
|
beneficiary->set_ticks_left(ticks_to_donate);
|
||||||
switch_now();
|
switch_now();
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Scheduler::yield()
|
bool Scheduler::yield()
|
||||||
|
@ -266,11 +269,11 @@ bool Scheduler::yield()
|
||||||
// dbgprintf("%s(%u:%u) yield()\n", current->process().name().characters(), current->pid(), current->tid());
|
// dbgprintf("%s(%u:%u) yield()\n", current->process().name().characters(), current->pid(), current->tid());
|
||||||
|
|
||||||
if (!pick_next())
|
if (!pick_next())
|
||||||
return 1;
|
return false;
|
||||||
|
|
||||||
// dbgprintf("yield() jumping to new process: sel=%x, %s(%u:%u)\n", current->far_ptr().selector, current->process().name().characters(), current->pid(), current->tid());
|
// dbgprintf("yield() jumping to new process: sel=%x, %s(%u:%u)\n", current->far_ptr().selector, current->process().name().characters(), current->pid(), current->tid());
|
||||||
switch_now();
|
switch_now();
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scheduler::pick_next_and_switch_now()
|
void Scheduler::pick_next_and_switch_now()
|
||||||
|
|
|
@ -526,3 +526,13 @@ Vector<Thread*> Thread::all_threads()
|
||||||
threads.append(thread);
|
threads.append(thread);
|
||||||
return threads;
|
return threads;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Thread::is_thread(void* ptr)
|
||||||
|
{
|
||||||
|
ASSERT_INTERRUPTS_DISABLED();
|
||||||
|
for (auto* thread = g_threads->head(); thread; thread = thread->next()) {
|
||||||
|
if (thread == ptr)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ public:
|
||||||
static void finalize_dying_threads();
|
static void finalize_dying_threads();
|
||||||
|
|
||||||
static Vector<Thread*> all_threads();
|
static Vector<Thread*> all_threads();
|
||||||
|
static bool is_thread(void*);
|
||||||
|
|
||||||
int tid() const { return m_tid; }
|
int tid() const { return m_tid; }
|
||||||
int pid() const;
|
int pid() const;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue