* @brief Check that getting and setting OS thread affinity works. */
| 3040 | * @brief Check that getting and setting OS thread affinity works. |
| 3041 | */ |
| 3042 | void check_os_thread_affinity() |
| 3043 | { |
| 3044 | BS::thread_pool pool; |
| 3045 | pool.detach_task( |
| 3046 | [] |
| 3047 | { |
| 3048 | // Since the thread affinity must be a subset of the process affinity, we first set its affinity to all CPUs if it wasn't already. |
| 3049 | const std::optional<std::vector<bool>> initial_process_affinity = BS::get_os_process_affinity(); |
| 3050 | const std::size_t num_process_bits = initial_process_affinity.has_value() ? initial_process_affinity->size() : std::thread::hardware_concurrency(); |
| 3051 | const std::vector<bool> all_enabled(num_process_bits, true); |
| 3052 | BS::set_os_process_affinity(all_enabled); |
| 3053 | |
| 3054 | logln("Checking OS thread affinity for pool threads..."); |
| 3055 | |
| 3056 | log("Obtaining initial thread affinity "); |
| 3057 | const std::optional<std::vector<bool>> initial_affinity = BS::this_thread::get_os_thread_affinity(); |
| 3058 | check(initial_affinity.has_value()); |
| 3059 | logln("Initial affinity is: ", affinity_to_string(initial_affinity)); |
| 3060 | const std::size_t num_bits = initial_affinity.has_value() ? initial_affinity->size() : std::thread::hardware_concurrency(); |
| 3061 | |
| 3062 | log("Setting affinity to CPU 1 only "); |
| 3063 | std::vector<bool> cpu_1_in(num_bits, false); |
| 3064 | cpu_1_in[0] = true; |
| 3065 | check(BS::this_thread::set_os_thread_affinity(cpu_1_in)); |
| 3066 | log("Obtaining new affinity "); |
| 3067 | const std::optional<std::vector<bool>> cpu_1_out = BS::this_thread::get_os_thread_affinity(); |
| 3068 | check(cpu_1_out.has_value()); |
| 3069 | check(affinity_to_string(cpu_1_in), affinity_to_string(cpu_1_out)); |
| 3070 | |
| 3071 | log("Setting affinity to alternating CPUs "); |
| 3072 | std::vector<bool> alternating_in(num_bits, false); |
| 3073 | for (std::size_t i = 0; i < num_bits; ++i) |
| 3074 | alternating_in[i] = (i % 2 == 1); |
| 3075 | check(BS::this_thread::set_os_thread_affinity(alternating_in)); |
| 3076 | log("Obtaining new affinity "); |
| 3077 | const std::optional<std::vector<bool>> alternating_out = BS::this_thread::get_os_thread_affinity(); |
| 3078 | check(alternating_out.has_value()); |
| 3079 | check(affinity_to_string(alternating_in), affinity_to_string(alternating_out)); |
| 3080 | |
| 3081 | if (initial_affinity.has_value()) |
| 3082 | { |
| 3083 | log("Setting affinity back to initial value "); |
| 3084 | check(BS::this_thread::set_os_thread_affinity(*initial_affinity)); |
| 3085 | log("Obtaining new affinity "); |
| 3086 | const std::optional<std::vector<bool>> initial_out = BS::this_thread::get_os_thread_affinity(); |
| 3087 | check(initial_out.has_value()); |
| 3088 | check(affinity_to_string(initial_affinity), affinity_to_string(initial_out)); |
| 3089 | } |
| 3090 | |
| 3091 | if (initial_process_affinity.has_value()) |
| 3092 | BS::set_os_process_affinity(*initial_process_affinity); |
| 3093 | }); |
| 3094 | } |
| 3095 | #endif |
| 3096 | |
| 3097 | /** |
no test coverage detected