We use only a single condition variable (instead of thread different
ones) for wait_for_child(), which is notified when any job control condition (child dead, stopped, continued) occurs. These events are relatively rare anyway, and it simplifies the code. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25079 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -138,11 +138,11 @@ struct job_control_entry : DoublyLinkedListLinkImpl<job_control_entry> {
|
|||||||
typedef DoublyLinkedList<job_control_entry> JobControlEntryList;
|
typedef DoublyLinkedList<job_control_entry> JobControlEntryList;
|
||||||
|
|
||||||
struct team_job_control_children {
|
struct team_job_control_children {
|
||||||
ConditionVariable<team_job_control_children> condition_variable;
|
JobControlEntryList entries;
|
||||||
JobControlEntryList entries;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct team_dead_children : team_job_control_children {
|
struct team_dead_children : team_job_control_children {
|
||||||
|
ConditionVariable<team_dead_children> condition_variable;
|
||||||
uint32 count;
|
uint32 count;
|
||||||
bigtime_t kernel_time;
|
bigtime_t kernel_time;
|
||||||
bigtime_t user_time;
|
bigtime_t user_time;
|
||||||
|
|||||||
@@ -883,11 +883,7 @@ create_team_struct(const char *name, bool kernel)
|
|||||||
|
|
||||||
// publish dead/stopped/continued children condition vars
|
// publish dead/stopped/continued children condition vars
|
||||||
team->dead_children->condition_variable.Publish(team->dead_children,
|
team->dead_children->condition_variable.Publish(team->dead_children,
|
||||||
"dead children");
|
"team children");
|
||||||
team->stopped_children->condition_variable.Publish(team->stopped_children,
|
|
||||||
"stopped children");
|
|
||||||
team->continued_children->condition_variable.Publish(
|
|
||||||
team->continued_children, "continued children");
|
|
||||||
|
|
||||||
// keep all allocated structures
|
// keep all allocated structures
|
||||||
jobControlEntryDeleter.Detach();
|
jobControlEntryDeleter.Detach();
|
||||||
@@ -903,9 +899,6 @@ create_team_struct(const char *name, bool kernel)
|
|||||||
static void
|
static void
|
||||||
delete_team_struct(struct team *team)
|
delete_team_struct(struct team *team)
|
||||||
{
|
{
|
||||||
team->stopped_children->condition_variable.Unpublish();
|
|
||||||
team->continued_children->condition_variable.Unpublish();
|
|
||||||
|
|
||||||
team->dead_children->condition_variable.Unpublish();
|
team->dead_children->condition_variable.Unpublish();
|
||||||
|
|
||||||
while (death_entry* threadDeathEntry = (death_entry*)list_remove_head_item(
|
while (death_entry* threadDeathEntry = (death_entry*)list_remove_head_item(
|
||||||
@@ -1748,23 +1741,12 @@ wait_for_child(pid_t child, uint32 flags, int32 *_reason,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If we haven't got anything yet, add prepare for waiting for the
|
// If we haven't got anything yet, add prepare for waiting for the
|
||||||
// condition variables.
|
// condition variable.
|
||||||
ConditionVariableEntry<team_dead_children> deadWaitEntry;
|
ConditionVariableEntry<team_dead_children> deadWaitEntry;
|
||||||
ConditionVariableEntry<team_job_control_children> continuedWaitEntry;
|
|
||||||
ConditionVariableEntry<team_job_control_children> stoppedWaitEntry;
|
|
||||||
|
|
||||||
if (status == B_WOULD_BLOCK && (flags & WNOHANG) == 0) {
|
if (status == B_WOULD_BLOCK && (flags & WNOHANG) == 0)
|
||||||
deadWaitEntry.Add(team->dead_children);
|
deadWaitEntry.Add(team->dead_children);
|
||||||
|
|
||||||
if ((flags & WCONTINUED) != 0) {
|
|
||||||
continuedWaitEntry.Add(team->continued_children,
|
|
||||||
&deadWaitEntry);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((flags & WUNTRACED) != 0)
|
|
||||||
stoppedWaitEntry.Add(team->stopped_children, &deadWaitEntry);
|
|
||||||
}
|
|
||||||
|
|
||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
|
|
||||||
// we got our entry and can return to our caller
|
// we got our entry and can return to our caller
|
||||||
@@ -2453,13 +2435,6 @@ team_set_job_control_state(struct team* team, job_control_state newState,
|
|||||||
case JOB_CONTROL_STATE_DEAD:
|
case JOB_CONTROL_STATE_DEAD:
|
||||||
childList = team->parent->dead_children;
|
childList = team->parent->dead_children;
|
||||||
team->parent->dead_children->count++;
|
team->parent->dead_children->count++;
|
||||||
// When a child dies, we need to notify all lists, since that might
|
|
||||||
// have been the last of the parent's children, and a waiting
|
|
||||||
// parent thread wouldn't wake up otherwise.
|
|
||||||
team->parent->stopped_children->condition_variable.NotifyAll(
|
|
||||||
threadsLocked);
|
|
||||||
team->parent->continued_children->condition_variable.NotifyAll(
|
|
||||||
threadsLocked);
|
|
||||||
break;
|
break;
|
||||||
case JOB_CONTROL_STATE_STOPPED:
|
case JOB_CONTROL_STATE_STOPPED:
|
||||||
childList = team->parent->stopped_children;
|
childList = team->parent->stopped_children;
|
||||||
@@ -2471,7 +2446,8 @@ team_set_job_control_state(struct team* team, job_control_state newState,
|
|||||||
|
|
||||||
if (childList != NULL) {
|
if (childList != NULL) {
|
||||||
childList->entries.Add(entry);
|
childList->entries.Add(entry);
|
||||||
childList->condition_variable.NotifyAll(threadsLocked);
|
team->parent->dead_children->condition_variable.NotifyAll(
|
||||||
|
threadsLocked);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3059,11 +3035,8 @@ _user_setpgid(pid_t processID, pid_t groupID)
|
|||||||
|
|
||||||
// Changing the process group might have changed the situation for a parent
|
// Changing the process group might have changed the situation for a parent
|
||||||
// waiting in wait_for_child(). Hence we notify it.
|
// waiting in wait_for_child(). Hence we notify it.
|
||||||
if (status == B_OK) {
|
if (status == B_OK)
|
||||||
team->parent->dead_children->condition_variable.NotifyAll(false);
|
team->parent->dead_children->condition_variable.NotifyAll(false);
|
||||||
team->parent->stopped_children->condition_variable.NotifyAll(false);
|
|
||||||
team->parent->continued_children->condition_variable.NotifyAll(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
|
|
||||||
|
|||||||
@@ -1034,13 +1034,8 @@ _dump_thread_info(struct thread *thread)
|
|||||||
kprintf(" sem.acquire_status: %#lx\n", thread->sem.acquire_status);
|
kprintf(" sem.acquire_status: %#lx\n", thread->sem.acquire_status);
|
||||||
kprintf(" sem.flags: %#lx\n", thread->sem.flags);
|
kprintf(" sem.flags: %#lx\n", thread->sem.flags);
|
||||||
|
|
||||||
kprintf("condition variables:");
|
|
||||||
PrivateConditionVariableEntry* entry = thread->condition_variable_entry;
|
PrivateConditionVariableEntry* entry = thread->condition_variable_entry;
|
||||||
while (entry != NULL) {
|
kprintf("condition variable: %p\n", entry ? entry->Variable() : NULL);
|
||||||
kprintf(" %p", entry->Variable());
|
|
||||||
entry = entry->ThreadNext();
|
|
||||||
}
|
|
||||||
kprintf("\n");
|
|
||||||
|
|
||||||
kprintf("fault_handler: %p\n", (void *)thread->fault_handler);
|
kprintf("fault_handler: %p\n", (void *)thread->fault_handler);
|
||||||
kprintf("args: %p %p\n", thread->args1, thread->args2);
|
kprintf("args: %p %p\n", thread->args1, thread->args2);
|
||||||
|
|||||||
Reference in New Issue
Block a user