]> git.pld-linux.org Git - packages/tbb.git/blob - retry-pthread-create-eagain.patch
7188839905552b7b00d405181935c7f21cb5edcc
[packages/tbb.git] / retry-pthread-create-eagain.patch
1 From f12c93efd04991bc982a27e2fa6142538c33ca82 Mon Sep 17 00:00:00 2001
2 From: Rui Ueyama <ruiu@cs.stanford.edu>
3 Date: Sat, 7 May 2022 19:55:24 +0800
4 Subject: [PATCH] Retry if pthread_create fails with EAGAIN
5
6 On many Unix-like systems, pthread_create can fail spuriously even if
7 the running machine has enough resources to spawn a new thread.
8 Therefore, if EAGAIN is returned from pthread_create, we actually have
9 to try again.
10
11 I observed this issue when running the mold linker
12 (https://github.com/rui314/mold) under a heavy load. mold uses OneTBB
13 for parallelization.
14
15 As another data point, Go has the same logic to retry on EAGAIN:
16 https://go-review.googlesource.com/c/go/+/33894/
17
18 nanosleep is defined in POSIX 2001, so I believe that all Unix-like
19 systems support it.
20
21 Signed-off-by: Rui Ueyama <ruiu@cs.stanford.edu>
22 ---
23  src/tbb/rml_thread_monitor.h | 19 ++++++++++++++++++-
24  1 file changed, 18 insertions(+), 1 deletion(-)
25
26 diff --git a/src/tbb/rml_thread_monitor.h b/src/tbb/rml_thread_monitor.h
27 index 13b556380..5b844b232 100644
28 --- a/src/tbb/rml_thread_monitor.h
29 +++ b/src/tbb/rml_thread_monitor.h
30 @@ -31,6 +31,7 @@
31  #include <pthread.h>
32  #include <cstring>
33  #include <cstdlib>
34 +#include <time.h>
35  #else
36  #error Unsupported platform
37  #endif
38 @@ -191,8 +192,24 @@ inline thread_monitor::handle_type thread_monitor::launch( void* (*thread_routin
39      check(pthread_attr_init( &s ), "pthread_attr_init has failed");
40      if( stack_size>0 )
41          check(pthread_attr_setstacksize( &s, stack_size ), "pthread_attr_setstack_size has failed" );
42 +
43      pthread_t handle;
44 -    check( pthread_create( &handle, &s, thread_routine, arg ), "pthread_create has failed" );
45 +    int tries = 0;
46 +    for (;;) {
47 +      int error_code = pthread_create(&handle, &s, thread_routine, arg);
48 +      if (!error_code)
49 +        break;
50 +      if (error_code != EAGAIN || tries++ > 20) {
51 +        handle_perror(error_code, "pthread_create has failed");
52 +        break;
53 +      }
54 +
55 +      // pthreaed_create can spuriously fail on many Unix-like systems.
56 +      // Retry after tries * 1 millisecond.
57 +      struct timespec ts = {0, tries * 1000 * 1000};
58 +      nanosleep(&ts, NULL);
59 +    }
60 +
61      check( pthread_attr_destroy( &s ), "pthread_attr_destroy has failed" );
62      return handle;
63  }
This page took 0.04401 seconds and 2 git commands to generate.