Squashed a TODO: When delivering signals, check if a) any threads were in fact enqueued, and b) if the scheduler's preemption hint indicates that a reschedule is desired. This prevents unnecessarily invoking the scheduler every single time a signal is delivered, regardless of result.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32592 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Rene Gollent 2009-08-21 23:48:42 +00:00
parent 93134c5eb2
commit c3350a57ff

View File

@ -59,7 +59,7 @@ const char * const sigstr[NSIG] = {
static status_t deliver_signal(struct thread *thread, uint signal,
uint32 flags);
uint32 flags, bool& reschedule);
@ -377,8 +377,12 @@ handle_signals(struct thread *thread)
= thread->team->parent->main_thread;
struct sigaction& parentHandler
= parentThread->sig_action[SIGCHLD - 1];
if ((parentHandler.sa_flags & SA_NOCLDSTOP) == 0)
deliver_signal(parentThread, SIGCHLD, 0);
// TODO: do we need to worry about rescheduling here?
bool unused = false;
if ((parentHandler.sa_flags & SA_NOCLDSTOP) == 0) {
deliver_signal(parentThread, SIGCHLD, 0,
unused);
}
}
return true;
@ -484,7 +488,8 @@ is_signal_blocked(int signal)
thread lock held.
*/
static status_t
deliver_signal(struct thread *thread, uint signal, uint32 flags)
deliver_signal(struct thread *thread, uint signal, uint32 flags,
bool& reschedule)
{
if (flags & B_CHECK_PERMISSION) {
// ToDo: introduce euid & uid fields to the team and check permission
@ -496,7 +501,7 @@ deliver_signal(struct thread *thread, uint signal, uint32 flags)
if (thread->team == team_get_kernel_team()) {
// Signals to kernel threads will only wake them up
if (thread->state == B_THREAD_SUSPENDED)
scheduler_enqueue_in_run_queue(thread);
reschedule |= scheduler_enqueue_in_run_queue(thread);
return B_OK;
}
@ -511,7 +516,7 @@ deliver_signal(struct thread *thread, uint signal, uint32 flags)
// Wake up main thread
if (mainThread->state == B_THREAD_SUSPENDED)
scheduler_enqueue_in_run_queue(mainThread);
reschedule |= scheduler_enqueue_in_run_queue(mainThread);
else
thread_interrupt(mainThread, true);
@ -522,7 +527,7 @@ deliver_signal(struct thread *thread, uint signal, uint32 flags)
case SIGKILLTHR:
// Wake up suspended threads and interrupt waiting ones
if (thread->state == B_THREAD_SUSPENDED)
scheduler_enqueue_in_run_queue(thread);
reschedule |= scheduler_enqueue_in_run_queue(thread);
else
thread_interrupt(thread, true);
break;
@ -530,7 +535,7 @@ deliver_signal(struct thread *thread, uint signal, uint32 flags)
case SIGCONT:
// Wake up thread if it was suspended
if (thread->state == B_THREAD_SUSPENDED)
scheduler_enqueue_in_run_queue(thread);
reschedule |= scheduler_enqueue_in_run_queue(thread);
if ((flags & SIGNAL_FLAG_DONT_RESTART_SYSCALL) != 0)
atomic_or(&thread->flags, THREAD_FLAGS_DONT_RESTART_SYSCALL);
@ -560,6 +565,7 @@ send_signal_etc(pid_t id, uint signal, uint32 flags)
status_t status = B_BAD_THREAD_ID;
struct thread *thread;
cpu_status state = 0;
bool reschedule = false;
if (signal < 0 || signal > MAX_SIGNO)
return B_BAD_VALUE;
@ -575,8 +581,10 @@ send_signal_etc(pid_t id, uint signal, uint32 flags)
GRAB_THREAD_LOCK();
thread = thread_get_thread_struct_locked(id);
if (thread != NULL)
status = deliver_signal(thread, signal, flags);
if (thread != NULL) {
status = deliver_signal(thread, signal, flags,
reschedule);
}
} else {
// send a signal to the specified process group
// (the absolute value of the id)
@ -609,7 +617,8 @@ send_signal_etc(pid_t id, uint signal, uint32 flags)
if (thread != NULL) {
// we don't stop because of an error sending the signal; we
// rather want to send as much signals as possible
status = deliver_signal(thread, signal, flags);
status = deliver_signal(thread, signal, flags,
reschedule);
}
RELEASE_THREAD_LOCK();
@ -622,9 +631,8 @@ send_signal_etc(pid_t id, uint signal, uint32 flags)
GRAB_THREAD_LOCK();
}
// TODO: The scheduler should only be invoked if there is reason to do it
// (ie. deliver_signal() moved some threads in the running queue)!
if ((flags & (B_DO_NOT_RESCHEDULE | SIGNAL_FLAG_TEAMS_LOCKED)) == 0)
if ((flags & (B_DO_NOT_RESCHEDULE | SIGNAL_FLAG_TEAMS_LOCKED)) == 0
&& reschedule)
scheduler_reschedule();
RELEASE_THREAD_LOCK();