3738 jio_snprintf(ebuf, ebuflen, |
3738 jio_snprintf(ebuf, ebuflen, |
3739 "os::win32::load_windows_dll() cannot load %s from system directories.", name); |
3739 "os::win32::load_windows_dll() cannot load %s from system directories.", name); |
3740 return NULL; |
3740 return NULL; |
3741 } |
3741 } |
3742 |
3742 |
3743 #define MIN_EXIT_MUTEXES 1 |
3743 #define MAX_EXIT_HANDLES 16 |
3744 #define MAX_EXIT_MUTEXES 16 |
3744 #define EXIT_TIMEOUT 1000 /* 1 sec */ |
3745 |
3745 |
3746 struct ExitMutexes { |
3746 static BOOL CALLBACK init_crit_sect_call(PINIT_ONCE, PVOID pcrit_sect, PVOID*) { |
3747 DWORD count; |
3747 InitializeCriticalSection((CRITICAL_SECTION*)pcrit_sect); |
3748 HANDLE handles[MAX_EXIT_MUTEXES]; |
|
3749 }; |
|
3750 |
|
3751 static BOOL CALLBACK init_muts_call(PINIT_ONCE, PVOID ppmuts, PVOID*) { |
|
3752 static ExitMutexes muts; |
|
3753 |
|
3754 muts.count = os::processor_count(); |
|
3755 if (muts.count < MIN_EXIT_MUTEXES) { |
|
3756 muts.count = MIN_EXIT_MUTEXES; |
|
3757 } else if (muts.count > MAX_EXIT_MUTEXES) { |
|
3758 muts.count = MAX_EXIT_MUTEXES; |
|
3759 } |
|
3760 |
|
3761 for (DWORD i = 0; i < muts.count; ++i) { |
|
3762 muts.handles[i] = CreateMutex(NULL, FALSE, NULL); |
|
3763 if (muts.handles[i] == NULL) { |
|
3764 return FALSE; |
|
3765 } |
|
3766 } |
|
3767 *((ExitMutexes**)ppmuts) = &muts; |
|
3768 return TRUE; |
3748 return TRUE; |
3769 } |
3749 } |
3770 |
3750 |
3771 int os::win32::exit_process_or_thread(Ept what, int exit_code) { |
3751 int os::win32::exit_process_or_thread(Ept what, int exit_code) { |
|
3752 // Basic approach: |
|
3753 // - Each exiting thread registers its intent to exit and then does so. |
|
3754 // - A thread trying to terminate the process must wait for all |
|
3755 // threads currently exiting to complete their exit. |
|
3756 |
3772 if (os::win32::has_exit_bug()) { |
3757 if (os::win32::has_exit_bug()) { |
3773 static INIT_ONCE init_once_muts = INIT_ONCE_STATIC_INIT; |
3758 // The array holds handles of the threads that have started exiting by calling |
3774 static ExitMutexes* pmuts; |
3759 // _endthreadex(). |
3775 |
3760 // Should be large enough to avoid blocking the exiting thread due to lack of |
3776 if (!InitOnceExecuteOnce(&init_once_muts, init_muts_call, &pmuts, NULL)) { |
3761 // a free slot. |
3777 warning("ExitMutex initialization failed in %s: %d\n", __FILE__, __LINE__); |
3762 static HANDLE handles[MAX_EXIT_HANDLES]; |
3778 } else if (WaitForMultipleObjects(pmuts->count, pmuts->handles, |
3763 static int handle_count = 0; |
3779 (what != EPT_THREAD), // exiting process waits for all mutexes |
3764 |
3780 INFINITE) == WAIT_FAILED) { |
3765 static INIT_ONCE init_once_crit_sect = INIT_ONCE_STATIC_INIT; |
3781 warning("ExitMutex acquisition failed in %s: %d\n", __FILE__, __LINE__); |
3766 static CRITICAL_SECTION crit_sect; |
3782 } |
3767 int i, j; |
3783 } |
3768 DWORD res; |
3784 |
3769 HANDLE hproc, hthr; |
3785 switch (what) { |
3770 |
3786 case EPT_THREAD: |
3771 // The first thread that reached this point, initializes the critical section. |
|
3772 if (!InitOnceExecuteOnce(&init_once_crit_sect, init_crit_sect_call, &crit_sect, NULL)) { |
|
3773 warning("crit_sect initialization failed in %s: %d\n", __FILE__, __LINE__); |
|
3774 } else { |
|
3775 EnterCriticalSection(&crit_sect); |
|
3776 |
|
3777 if (what == EPT_THREAD) { |
|
3778 // Remove from the array those handles of the threads that have completed exiting. |
|
3779 for (i = 0, j = 0; i < handle_count; ++i) { |
|
3780 res = WaitForSingleObject(handles[i], 0 /* don't wait */); |
|
3781 if (res == WAIT_TIMEOUT) { |
|
3782 handles[j++] = handles[i]; |
|
3783 } else { |
|
3784 if (res != WAIT_OBJECT_0) { |
|
3785 warning("WaitForSingleObject failed in %s: %d\n", __FILE__, __LINE__); |
|
3786 // Don't keep the handle, if we failed waiting for it. |
|
3787 } |
|
3788 CloseHandle(handles[i]); |
|
3789 } |
|
3790 } |
|
3791 |
|
3792 // If there's no free slot in the array of the kept handles, we'll have to |
|
3793 // wait until at least one thread completes exiting. |
|
3794 if ((handle_count = j) == MAX_EXIT_HANDLES) { |
|
3795 res = WaitForMultipleObjects(MAX_EXIT_HANDLES, handles, FALSE, EXIT_TIMEOUT); |
|
3796 if (res >= WAIT_OBJECT_0 && res < (WAIT_OBJECT_0 + MAX_EXIT_HANDLES)) { |
|
3797 i = (res - WAIT_OBJECT_0); |
|
3798 handle_count = MAX_EXIT_HANDLES - 1; |
|
3799 for (; i < handle_count; ++i) { |
|
3800 handles[i] = handles[i + 1]; |
|
3801 } |
|
3802 } else { |
|
3803 warning("WaitForMultipleObjects failed in %s: %d\n", __FILE__, __LINE__); |
|
3804 // Don't keep handles, if we failed waiting for them. |
|
3805 for (i = 0; i < MAX_EXIT_HANDLES; ++i) { |
|
3806 CloseHandle(handles[i]); |
|
3807 } |
|
3808 handle_count = 0; |
|
3809 } |
|
3810 } |
|
3811 |
|
3812 // Store a duplicate of the current thread handle in the array of handles. |
|
3813 hproc = GetCurrentProcess(); |
|
3814 hthr = GetCurrentThread(); |
|
3815 if (!DuplicateHandle(hproc, hthr, hproc, &handles[handle_count], |
|
3816 0, FALSE, DUPLICATE_SAME_ACCESS)) { |
|
3817 warning("DuplicateHandle failed in %s: %d\n", __FILE__, __LINE__); |
|
3818 } else { |
|
3819 ++handle_count; |
|
3820 } |
|
3821 |
|
3822 // The current exiting thread has stored its handle in the array, and now |
|
3823 // should leave the critical section before calling _endthreadex(). |
|
3824 |
|
3825 } else { // what != EPT_THREAD |
|
3826 if (handle_count > 0) { |
|
3827 // Before ending the process, make sure all the threads that had called |
|
3828 // _endthreadex() completed. |
|
3829 res = WaitForMultipleObjects(handle_count, handles, TRUE, EXIT_TIMEOUT); |
|
3830 if (res == WAIT_FAILED) { |
|
3831 warning("WaitForMultipleObjects failed in %s: %d\n", __FILE__, __LINE__); |
|
3832 } |
|
3833 for (i = 0; i < handle_count; ++i) { |
|
3834 CloseHandle(handles[i]); |
|
3835 } |
|
3836 handle_count = 0; |
|
3837 } |
|
3838 |
|
3839 // End the process, not leaving critical section. |
|
3840 // This makes sure no other thread executes exit-related code at the same |
|
3841 // time, thus a race is avoided. |
|
3842 if (what == EPT_PROCESS) { |
|
3843 ::exit(exit_code); |
|
3844 } else { |
|
3845 _exit(exit_code); |
|
3846 } |
|
3847 } |
|
3848 |
|
3849 LeaveCriticalSection(&crit_sect); |
|
3850 } |
|
3851 } |
|
3852 |
|
3853 // We are here if either |
|
3854 // - there's no 'race at exit' bug on this OS release; |
|
3855 // - initialization of the critical section failed (unlikely); |
|
3856 // - the current thread has stored its handle and left the critical section. |
|
3857 if (what == EPT_THREAD) { |
3787 _endthreadex((unsigned)exit_code); |
3858 _endthreadex((unsigned)exit_code); |
3788 break; |
3859 } else if (what == EPT_PROCESS) { |
3789 |
|
3790 case EPT_PROCESS: |
|
3791 ::exit(exit_code); |
3860 ::exit(exit_code); |
3792 break; |
3861 } else { |
3793 |
|
3794 case EPT_PROCESS_DIE: |
|
3795 _exit(exit_code); |
3862 _exit(exit_code); |
3796 break; |
3863 } |
3797 } |
3864 |
3798 |
3865 // Should not reach here |
3799 // should not reach here |
|
3800 return exit_code; |
3866 return exit_code; |
3801 } |
3867 } |
3802 |
3868 |
3803 #undef MIN_EXIT_MUTEXES |
3869 #undef MAX_EXIT_HANDLES |
3804 #undef MAX_EXIT_MUTEXES |
3870 #undef EXIT_TIMEOUT |
3805 |
3871 |
3806 void os::win32::setmode_streams() { |
3872 void os::win32::setmode_streams() { |
3807 _setmode(_fileno(stdin), _O_BINARY); |
3873 _setmode(_fileno(stdin), _O_BINARY); |
3808 _setmode(_fileno(stdout), _O_BINARY); |
3874 _setmode(_fileno(stdout), _O_BINARY); |
3809 _setmode(_fileno(stderr), _O_BINARY); |
3875 _setmode(_fileno(stderr), _O_BINARY); |