From: Marek Olšák <marek.ol...@amd.com> --- src/gallium/auxiliary/util/u_helpers.c | 37 +++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 4 deletions(-)
diff --git a/src/gallium/auxiliary/util/u_helpers.c b/src/gallium/auxiliary/util/u_helpers.c index 14367e5a118..3194c2e4e7a 100644 --- a/src/gallium/auxiliary/util/u_helpers.c +++ b/src/gallium/auxiliary/util/u_helpers.c @@ -114,57 +114,86 @@ util_upload_index_buffer(struct pipe_context *pipe, u_upload_data(pipe->stream_uploader, start_offset, info->count * info->index_size, 4, (char*)info->index.user + start_offset, out_offset, out_buffer); u_upload_unmap(pipe->stream_uploader); *out_offset -= start_offset; return *out_buffer != NULL; } +#ifdef HAVE_PTHREAD_SETAFFINITY + static unsigned L3_cache_number; -static once_flag init_cache_number_flag = ONCE_FLAG_INIT; +static once_flag thread_pinning_once_flag = ONCE_FLAG_INIT; + +static void +util_set_full_cpu_affinity(void) +{ + cpu_set_t cpuset; + + CPU_ZERO(&cpuset); + for (unsigned i = 0; i < CPU_SETSIZE; i++) + CPU_SET(i, &cpuset); + + pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset); +} static void -util_init_cache_number(void) +util_init_thread_pinning(void) { /* Get a semi-random number. */ int64_t t = os_time_get_nano(); L3_cache_number = (t ^ (t >> 8) ^ (t >> 16)); + + /* Reset thread affinity for all children of fork and exec to prevent + * spawned processes and threads from inheriting the current thread's + * affinity. + * + * What happens if a driver is unloaded and the app creates a thread? + */ + pthread_atfork(NULL, NULL, util_set_full_cpu_affinity); } +#endif + /** * Called by MakeCurrent. Used to notify the driver that the application * thread may have been changed. * * The function pins the current thread and driver threads to a group of * CPU cores that share the same L3 cache. This is needed for good multi- * threading performance on AMD Zen CPUs. * * \param upper_thread thread in the state tracker that also needs to be * pinned. */ void util_context_thread_changed(struct pipe_context *ctx, thrd_t *upper_thread) { -#ifdef HAVE_PTHREAD +#ifdef HAVE_PTHREAD_SETAFFINITY + /* If pinning has no effect, don't do anything. */ + if (util_cpu_caps.nr_cpus == util_cpu_caps.cores_per_L3) + return; + thrd_t current = thrd_current(); int cache = util_get_L3_for_pinned_thread(current, util_cpu_caps.cores_per_L3); + call_once(&thread_pinning_once_flag, util_init_thread_pinning); + /* If the main thread is not pinned, choose the L3 cache. */ if (cache == -1) { unsigned num_L3_caches = util_cpu_caps.nr_cpus / util_cpu_caps.cores_per_L3; /* Choose a different L3 cache for each subsequent MakeCurrent. */ - call_once(&init_cache_number_flag, util_init_cache_number); cache = p_atomic_inc_return(&L3_cache_number) % num_L3_caches; util_pin_thread_to_L3(current, cache, util_cpu_caps.cores_per_L3); } /* Tell the driver to pin its threads to the same L3 cache. */ if (ctx->set_context_param) { ctx->set_context_param(ctx, PIPE_CONTEXT_PARAM_PIN_THREADS_TO_L3_CACHE, cache); } -- 2.17.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev