Skip to content

Commit 8bb6b8f

Browse files
committed
Fix JULIA_EXCLUSIVE setting affinity on non-worker threads
With JULIA_EXCLUSIVE=1, we would try to give both worker and interactive threads an exclusive CPU, causing --threads=auto to produce a "Too many threads requested" error. Fixes JuliaLang#50702.
1 parent b70761f commit 8bb6b8f

File tree

2 files changed

+18
-12
lines changed

2 files changed

+18
-12
lines changed

src/threading.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,9 @@ void jl_start_threads(void)
794794
{
795795
int nthreads = jl_atomic_load_relaxed(&jl_n_threads);
796796
int ngcthreads = jl_n_gcthreads;
797+
int nthreadsi = jl_n_threads_per_pool[0];
798+
int nmutator_threads = nthreads - ngcthreads;
799+
797800
int cpumasksize = uv_cpumask_size();
798801
char *cp;
799802
int i, exclusive;
@@ -812,32 +815,33 @@ void jl_start_threads(void)
812815
// according to a 'compact' policy
813816
// non-exclusive: no affinity settings; let the kernel move threads about
814817
if (exclusive) {
815-
if (nthreads > jl_cpu_threads()) {
818+
if (nmutator_threads - nthreadsi > jl_cpu_threads()) {
816819
jl_printf(JL_STDERR, "ERROR: Too many threads requested for %s option.\n", MACHINE_EXCLUSIVE_NAME);
817820
exit(1);
818821
}
819822
memset(mask, 0, cpumasksize);
820-
mask[0] = 1;
821-
uvtid = uv_thread_self();
822-
uv_thread_setaffinity(&uvtid, mask, NULL, cpumasksize);
823-
mask[0] = 0;
823+
824+
if (nthreadsi == 0) {
825+
mask[0] = 1;
826+
uvtid = uv_thread_self();
827+
uv_thread_setaffinity(&uvtid, mask, NULL, cpumasksize);
828+
mask[0] = 0;
829+
}
824830
}
825831

826832
// create threads
827833
uv_barrier_init(&thread_init_done, nthreads);
828834

829835
// GC/System threads need to be after the worker threads.
830-
int nmutator_threads = nthreads - ngcthreads;
831-
832836
for (i = 1; i < nmutator_threads; ++i) {
833837
jl_threadarg_t *t = (jl_threadarg_t *)malloc_s(sizeof(jl_threadarg_t)); // ownership will be passed to the thread
834838
t->tid = i;
835839
t->barrier = &thread_init_done;
836840
uv_thread_create(&uvtid, jl_threadfun, t);
837-
if (exclusive) {
838-
mask[i] = 1;
841+
if (exclusive && i > nthreadsi) {
842+
mask[i - nthreadsi] = 1;
839843
uv_thread_setaffinity(&uvtid, mask, NULL, cpumasksize);
840-
mask[i] = 0;
844+
mask[i - nthreadsi] = 0;
841845
}
842846
uv_thread_detach(&uvtid);
843847
}

test/threads.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,11 @@ if AFFINITY_SUPPORTED
123123
end
124124
end
125125

126-
function get_nthreads(options = ``; cpus = nothing)
126+
function get_nthreads(options = ``; cpus = nothing, exclusive = false)
127127
cmd = `$(Base.julia_cmd()) --startup-file=no $(options)`
128128
cmd = `$cmd -e "print(Threads.threadpoolsize())"`
129-
cmd = addenv(cmd, "JULIA_EXCLUSIVE" => "0", "JULIA_NUM_THREADS" => "auto")
129+
cmd = addenv(cmd, "JULIA_EXCLUSIVE" => exclusive ? "1" : "0",
130+
"JULIA_NUM_THREADS" => "auto")
130131
if cpus !== nothing
131132
cmd = setcpuaffinity(cmd, cpus)
132133
end
@@ -138,6 +139,7 @@ end
138139
allowed_cpus = findall(uv_thread_getaffinity())
139140
if length(allowed_cpus) 2
140141
@test get_nthreads() 2
142+
@test get_nthreads(exclusive = true) 2
141143
@test get_nthreads(cpus = allowed_cpus[1:1]) == 1
142144
@test get_nthreads(cpus = allowed_cpus[2:2]) == 1
143145
@test get_nthreads(cpus = allowed_cpus[1:2]) == 2

0 commit comments

Comments
 (0)