| 702 | #endif |
| 703 | |
| 704 | void ThreadPool_Exit(void) |
| 705 | { |
| 706 | gRunCount = CL_INT_MAX; |
| 707 | |
| 708 | #if defined(__GNUC__) |
| 709 | // GCC extension: |
| 710 | // http://gcc.gnu.org/onlinedocs/gcc/Atomic-Builtins.html#Atomic-Builtins |
| 711 | __sync_synchronize(); |
| 712 | #elif defined(_MSC_VER) |
| 713 | #if defined(_M_IX86) || defined(_M_X64) |
| 714 | _mm_mfence(); |
| 715 | #elif defined(_M_ARM64) |
| 716 | __dmb(_ARM64_BARRIER_ISHST); |
| 717 | #else |
| 718 | #error Architecture needs an implementation |
| 719 | #endif |
| 720 | #else |
| 721 | #warning If this is a weakly ordered memory system, please add a memory barrier here to force this and everything else to memory before we proceed |
| 722 | #endif |
| 723 | |
| 724 | // spin waiting for threads to die |
| 725 | for (int count = 0; 0 != gThreadCount && count < 1000; count++) |
| 726 | { |
| 727 | #if defined(_WIN32) |
| 728 | _WakeAllConditionVariable(cond_var); |
| 729 | Sleep(1); |
| 730 | #else // !_WIN32 |
| 731 | if (int err = pthread_cond_broadcast(&cond_var)) |
| 732 | { |
| 733 | log_error("Error %d from pthread_cond_broadcast. Unable to wake up " |
| 734 | "work threads. ThreadPool_Exit failed.\n", |
| 735 | err); |
| 736 | break; |
| 737 | } |
| 738 | usleep(1000); |
| 739 | #endif // !_WIN32 |
| 740 | } |
| 741 | |
| 742 | if (gThreadCount) |
| 743 | log_error("Error: Thread pool timed out after 1 second with %d threads " |
| 744 | "still active.\n", |
| 745 | gThreadCount.load()); |
| 746 | else |
| 747 | { |
| 748 | #if !defined(_WIN32) |
| 749 | for (pthread_t pthread : pthreads) |
| 750 | { |
| 751 | if (int err = pthread_join(pthread, nullptr)) |
| 752 | { |
| 753 | log_error("Error from %d from pthread_join. Unable to join " |
| 754 | "work threads. ThreadPool_Exit failed.\n", |
| 755 | err); |
| 756 | } |
| 757 | } |
| 758 | #endif |
| 759 | log_info("Thread pool exited in a orderly fashion.\n"); |
| 760 | } |
| 761 | } |
nothing calls this directly
no test coverage detected