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