See header for documentation */
| 244 | |
| 245 | /* See header for documentation */ |
| 246 | void launch_threads( |
| 247 | const char* operation, |
| 248 | int thread_count, |
| 249 | void (*func)(int, int, void*), |
| 250 | void *payload |
| 251 | ) { |
| 252 | // Directly execute single threaded workloads on this thread |
| 253 | if (thread_count <= 1) |
| 254 | { |
| 255 | func(1, 0, payload); |
| 256 | return; |
| 257 | } |
| 258 | |
| 259 | // Otherwise spawn worker threads |
| 260 | std::vector<launch_desc> thread_descs(thread_count); |
| 261 | int actual_thread_count { 0 }; |
| 262 | |
| 263 | for (int i = 0; i < thread_count; i++) |
| 264 | { |
| 265 | thread_descs[actual_thread_count].thread_count = thread_count; |
| 266 | thread_descs[actual_thread_count].thread_id = actual_thread_count; |
| 267 | thread_descs[actual_thread_count].payload = payload; |
| 268 | thread_descs[actual_thread_count].func = func; |
| 269 | |
| 270 | // Handle pthread_create failing by simply using fewer threads |
| 271 | int error = pthread_create( |
| 272 | &(thread_descs[actual_thread_count].thread_handle), |
| 273 | nullptr, |
| 274 | launch_threads_helper, |
| 275 | reinterpret_cast<void*>(&thread_descs[actual_thread_count])); |
| 276 | |
| 277 | // Track how many threads we actually created |
| 278 | if (!error) |
| 279 | { |
| 280 | // Windows needs explicit thread assignment to handle large core count systems |
| 281 | #if defined(_WIN32) && !defined(__CYGWIN__) |
| 282 | set_group_affinity( |
| 283 | thread_descs[actual_thread_count].thread_handle, |
| 284 | actual_thread_count); |
| 285 | #endif |
| 286 | |
| 287 | actual_thread_count++; |
| 288 | } |
| 289 | } |
| 290 | |
| 291 | // If we did not create thread_count threads then emit a warning |
| 292 | if (actual_thread_count != thread_count) |
| 293 | { |
| 294 | int log_count = actual_thread_count == 0 ? 1 : actual_thread_count; |
| 295 | const char* log_s = log_count == 1 ? "" : "s"; |
| 296 | printf("WARNING: %s using %d thread%s due to thread creation error\n\n", |
| 297 | operation, log_count, log_s); |
| 298 | } |
| 299 | |
| 300 | // If we managed to spawn any threads wait for them to complete |
| 301 | if (actual_thread_count != 0) |
| 302 | { |
| 303 | for (int i = 0; i < actual_thread_count; i++) |
no test coverage detected