Kernel/Threads: remove limit on number of dead threads in a team

When a thread is created, it is expected that some other thread (usually the
creating thread) will want to make sure it completes. This is done using the
pthread_join() or wait_for_thread() calls.

It is possible that threads end before another thread waits for its completion.
That's why there is a dead thread list for each team, which holds thread ids
and their exit status so that a call to pthread_join() or wait_for_thread() in
the future can complete succesfully.

The dead thread list was limited to 32 threads per team. If there would be
more, the oldest thread would be kicked off. This could cause issues in
situations where a team would create more than 32 threads, and would start
waiting for their result after they have finished. Some of the calls would fail
because the threads would no longer be in the dead list.

This specifically caused problems for cargo (the Rust package manager), which
could depending on the number of dependencies, could create more than 32
threads. See: https://github.com/nielx/rust/issues/3

This change removes the limit of dead threads within a team. Note that there is
a risk that a badly written program that does not detach or joins its threads
can make this an endless list, but the impact is relatively small (dead threads
only occupy a bit of kernel memory).

Change-Id: I0135dd54e10ee48a529f23228d21237d4f1a74e2
Reviewed-on: https://review.haiku-os.org/c/haiku/+/3178
Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
Niels Sascha Reedijk
2020-09-01 21:04:46 +00:00
parent 41853a8bbf
commit 331889d067
3 changed files with 1 additions and 17 deletions
-3
View File
@@ -96,8 +96,6 @@ struct team_watcher {
#define MAX_DEAD_CHILDREN 32
// this is a soft limit for the number of child death entries in a team
#define MAX_DEAD_THREADS 32
// this is a soft limit for the number of thread death entries in a team
struct job_control_entry : DoublyLinkedListLinkImpl<job_control_entry> {
@@ -238,7 +236,6 @@ struct Team : TeamThreadIteratorEntry<team_id>, KernelReferenceable,
struct xsi_sem_context *xsi_sem_context;
struct team_death_entry *death_entry; // protected by fLock
struct list dead_threads;
int dead_threads_count;
// protected by the team's fLock
team_dead_children dead_children;
-1
View File
@@ -470,7 +470,6 @@ Team::Team(team_id id, bool kernel)
// dead threads
list_init(&dead_threads);
dead_threads_count = 0;
// dead children
dead_children.count = 0;
+1 -13
View File
@@ -2139,17 +2139,8 @@ thread_exit(void)
threadDeathEntry->thread = thread->id;
threadDeathEntry->status = thread->exit.status;
// add entry -- remove an old one, if we hit the limit
// add entry to dead thread list
list_add_item(&team->dead_threads, threadDeathEntry);
team->dead_threads_count++;
threadDeathEntry = NULL;
if (team->dead_threads_count > MAX_DEAD_THREADS) {
threadDeathEntry
= (thread_death_entry*)list_remove_head_item(
&team->dead_threads);
team->dead_threads_count--;
}
}
threadCreationLocker.Unlock();
@@ -2164,8 +2155,6 @@ thread_exit(void)
thread->id));
}
free(threadDeathEntry);
// delete the team if we're its main thread
if (deleteTeam) {
team_delete_team(team, debuggerPort);
@@ -2505,7 +2494,6 @@ wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout,
&team->dead_threads, threadDeathEntry)) != NULL) {
if (threadDeathEntry->thread == id) {
list_remove_item(&team->dead_threads, threadDeathEntry);
team->dead_threads_count--;
death.status = threadDeathEntry->status;
free(threadDeathEntry);
break;