diff options
author | Marek Olšák <[email protected]> | 2018-09-12 20:29:19 -0400 |
---|---|---|
committer | Marek Olšák <[email protected]> | 2018-09-14 21:15:39 -0400 |
commit | 914bd3014f6cb05f0893485487e69ca87e7c972c (patch) | |
tree | 0463042a4a54967ac01bebf301f3e680a9b4b459 | |
parent | 7d41a7593a540d118926691a77ad4c59e9559143 (diff) |
gallium/util: don't let child processes inherit our thread affinity
v2: corrected the comment
-rw-r--r-- | src/gallium/auxiliary/util/u_helpers.c | 36 |
1 files changed, 32 insertions, 4 deletions
diff --git a/src/gallium/auxiliary/util/u_helpers.c b/src/gallium/auxiliary/util/u_helpers.c index 14367e5a118..b6cebf96329 100644 --- a/src/gallium/auxiliary/util/u_helpers.c +++ b/src/gallium/auxiliary/util/u_helpers.c @@ -121,17 +121,40 @@ util_upload_index_buffer(struct pipe_context *pipe, 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 child processes to prevent them 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. @@ -146,18 +169,23 @@ util_init_cache_number(void) 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); } |