123 |
123 |
124 BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved) { |
124 BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved) { |
125 switch (reason) { |
125 switch (reason) { |
126 case DLL_PROCESS_ATTACH: |
126 case DLL_PROCESS_ATTACH: |
127 vm_lib_handle = hinst; |
127 vm_lib_handle = hinst; |
128 if(ForceTimeHighResolution) |
128 if (ForceTimeHighResolution) |
129 timeBeginPeriod(1L); |
129 timeBeginPeriod(1L); |
130 break; |
130 break; |
131 case DLL_PROCESS_DETACH: |
131 case DLL_PROCESS_DETACH: |
132 if(ForceTimeHighResolution) |
132 if (ForceTimeHighResolution) |
133 timeEndPeriod(1L); |
133 timeEndPeriod(1L); |
134 |
134 |
135 // Workaround for issue when a custom launcher doesn't call |
135 // Workaround for issue when a custom launcher doesn't call |
136 // DestroyJavaVM and NMT is trying to track memory when free is |
136 // DestroyJavaVM and NMT is trying to track memory when free is |
137 // called from a static destructor |
137 // called from a static destructor |
997 dumpType = (MINIDUMP_TYPE)(dumpType | MiniDumpWithFullMemoryInfo | MiniDumpWithThreadInfo | |
997 dumpType = (MINIDUMP_TYPE)(dumpType | MiniDumpWithFullMemoryInfo | MiniDumpWithThreadInfo | |
998 MiniDumpWithUnloadedModules); |
998 MiniDumpWithUnloadedModules); |
999 #endif |
999 #endif |
1000 |
1000 |
1001 cwd = get_current_directory(NULL, 0); |
1001 cwd = get_current_directory(NULL, 0); |
1002 jio_snprintf(buffer, bufferSize, "%s\\hs_err_pid%u.mdmp",cwd, current_process_id()); |
1002 jio_snprintf(buffer, bufferSize, "%s\\hs_err_pid%u.mdmp", cwd, current_process_id()); |
1003 dumpFile = CreateFile(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); |
1003 dumpFile = CreateFile(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); |
1004 |
1004 |
1005 if (dumpFile == INVALID_HANDLE_VALUE) { |
1005 if (dumpFile == INVALID_HANDLE_VALUE) { |
1006 VMError::report_coredump_status("Failed to create file for dumping", false); |
1006 VMError::report_coredump_status("Failed to create file for dumping", false); |
1007 return; |
1007 return; |
1302 typedef int (*EnumModulesCallbackFunc)(int, char *, address, unsigned, void *); |
1302 typedef int (*EnumModulesCallbackFunc)(int, char *, address, unsigned, void *); |
1303 |
1303 |
1304 // enumerate_modules for Windows NT, using PSAPI |
1304 // enumerate_modules for Windows NT, using PSAPI |
1305 static int _enumerate_modules_winnt( int pid, EnumModulesCallbackFunc func, void * param) |
1305 static int _enumerate_modules_winnt( int pid, EnumModulesCallbackFunc func, void * param) |
1306 { |
1306 { |
1307 HANDLE hProcess ; |
1307 HANDLE hProcess; |
1308 |
1308 |
1309 # define MAX_NUM_MODULES 128 |
1309 # define MAX_NUM_MODULES 128 |
1310 HMODULE modules[MAX_NUM_MODULES]; |
1310 HMODULE modules[MAX_NUM_MODULES]; |
1311 static char filename[ MAX_PATH ]; |
1311 static char filename[MAX_PATH]; |
1312 int result = 0; |
1312 int result = 0; |
1313 |
1313 |
1314 if (!os::PSApiDll::PSApiAvailable()) { |
1314 if (!os::PSApiDll::PSApiAvailable()) { |
1315 return 0; |
1315 return 0; |
1316 } |
1316 } |
1317 |
1317 |
1318 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, |
1318 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, |
1319 FALSE, pid ) ; |
1319 FALSE, pid); |
1320 if (hProcess == NULL) return 0; |
1320 if (hProcess == NULL) return 0; |
1321 |
1321 |
1322 DWORD size_needed; |
1322 DWORD size_needed; |
1323 if (!os::PSApiDll::EnumProcessModules(hProcess, modules, |
1323 if (!os::PSApiDll::EnumProcessModules(hProcess, modules, |
1324 sizeof(modules), &size_needed)) { |
1324 sizeof(modules), &size_needed)) { |
1325 CloseHandle( hProcess ); |
1325 CloseHandle(hProcess); |
1326 return 0; |
1326 return 0; |
1327 } |
1327 } |
1328 |
1328 |
1329 // number of modules that are currently loaded |
1329 // number of modules that are currently loaded |
1330 int num_modules = size_needed / sizeof(HMODULE); |
1330 int num_modules = size_needed / sizeof(HMODULE); |
1331 |
1331 |
1332 for (int i = 0; i < MIN2(num_modules, MAX_NUM_MODULES); i++) { |
1332 for (int i = 0; i < MIN2(num_modules, MAX_NUM_MODULES); i++) { |
1333 // Get Full pathname: |
1333 // Get Full pathname: |
1334 if(!os::PSApiDll::GetModuleFileNameEx(hProcess, modules[i], |
1334 if (!os::PSApiDll::GetModuleFileNameEx(hProcess, modules[i], |
1335 filename, sizeof(filename))) { |
1335 filename, sizeof(filename))) { |
1336 filename[0] = '\0'; |
1336 filename[0] = '\0'; |
1337 } |
1337 } |
1338 |
1338 |
1339 MODULEINFO modinfo; |
1339 MODULEINFO modinfo; |
1347 result = func(pid, filename, (address)modinfo.lpBaseOfDll, |
1347 result = func(pid, filename, (address)modinfo.lpBaseOfDll, |
1348 modinfo.SizeOfImage, param); |
1348 modinfo.SizeOfImage, param); |
1349 if (result) break; |
1349 if (result) break; |
1350 } |
1350 } |
1351 |
1351 |
1352 CloseHandle( hProcess ) ; |
1352 CloseHandle(hProcess); |
1353 return result; |
1353 return result; |
1354 } |
1354 } |
1355 |
1355 |
1356 |
1356 |
1357 // enumerate_modules for Windows 95/98/ME, using TOOLHELP |
1357 // enumerate_modules for Windows 95/98/ME, using TOOLHELP |
1358 static int _enumerate_modules_windows( int pid, EnumModulesCallbackFunc func, void *param) |
1358 static int _enumerate_modules_windows( int pid, EnumModulesCallbackFunc func, void *param) |
1359 { |
1359 { |
1360 HANDLE hSnapShot ; |
1360 HANDLE hSnapShot; |
1361 static MODULEENTRY32 modentry ; |
1361 static MODULEENTRY32 modentry; |
1362 int result = 0; |
1362 int result = 0; |
1363 |
1363 |
1364 if (!os::Kernel32Dll::HelpToolsAvailable()) { |
1364 if (!os::Kernel32Dll::HelpToolsAvailable()) { |
1365 return 0; |
1365 return 0; |
1366 } |
1366 } |
1367 |
1367 |
1368 // Get a handle to a Toolhelp snapshot of the system |
1368 // Get a handle to a Toolhelp snapshot of the system |
1369 hSnapShot = os::Kernel32Dll::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid ) ; |
1369 hSnapShot = os::Kernel32Dll::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid); |
1370 if( hSnapShot == INVALID_HANDLE_VALUE ) { |
1370 if (hSnapShot == INVALID_HANDLE_VALUE) { |
1371 return FALSE ; |
1371 return FALSE; |
1372 } |
1372 } |
1373 |
1373 |
1374 // iterate through all modules |
1374 // iterate through all modules |
1375 modentry.dwSize = sizeof(MODULEENTRY32) ; |
1375 modentry.dwSize = sizeof(MODULEENTRY32); |
1376 bool not_done = os::Kernel32Dll::Module32First( hSnapShot, &modentry ) != 0; |
1376 bool not_done = os::Kernel32Dll::Module32First( hSnapShot, &modentry ) != 0; |
1377 |
1377 |
1378 while( not_done ) { |
1378 while (not_done) { |
1379 // invoke the callback |
1379 // invoke the callback |
1380 result=func(pid, modentry.szExePath, (address)modentry.modBaseAddr, |
1380 result=func(pid, modentry.szExePath, (address)modentry.modBaseAddr, |
1381 modentry.modBaseSize, param); |
1381 modentry.modBaseSize, param); |
1382 if (result) break; |
1382 if (result) break; |
1383 |
1383 |
1384 modentry.dwSize = sizeof(MODULEENTRY32) ; |
1384 modentry.dwSize = sizeof(MODULEENTRY32); |
1385 not_done = os::Kernel32Dll::Module32Next( hSnapShot, &modentry ) != 0; |
1385 not_done = os::Kernel32Dll::Module32Next( hSnapShot, &modentry ) != 0; |
1386 } |
1386 } |
1387 |
1387 |
1388 CloseHandle(hSnapShot); |
1388 CloseHandle(hSnapShot); |
1389 return result; |
1389 return result; |
1963 // such as a service process. |
1963 // such as a service process. |
1964 USEROBJECTFLAGS flags; |
1964 USEROBJECTFLAGS flags; |
1965 HANDLE handle = GetProcessWindowStation(); |
1965 HANDLE handle = GetProcessWindowStation(); |
1966 if (handle != NULL && |
1966 if (handle != NULL && |
1967 GetUserObjectInformation(handle, UOI_FLAGS, &flags, |
1967 GetUserObjectInformation(handle, UOI_FLAGS, &flags, |
1968 sizeof( USEROBJECTFLAGS), NULL)) { |
1968 sizeof(USEROBJECTFLAGS), NULL)) { |
1969 // If it is a non-interactive session, let next handler to deal |
1969 // If it is a non-interactive session, let next handler to deal |
1970 // with it. |
1970 // with it. |
1971 if ((flags.dwFlags & WSF_VISIBLE) == 0) { |
1971 if ((flags.dwFlags & WSF_VISIBLE) == 0) { |
1972 return FALSE; |
1972 return FALSE; |
1973 } |
1973 } |
2420 |
2420 |
2421 // Check to see if we caught the safepoint code in the |
2421 // Check to see if we caught the safepoint code in the |
2422 // process of write protecting the memory serialization page. |
2422 // process of write protecting the memory serialization page. |
2423 // It write enables the page immediately after protecting it |
2423 // It write enables the page immediately after protecting it |
2424 // so just return. |
2424 // so just return. |
2425 if ( exception_code == EXCEPTION_ACCESS_VIOLATION ) { |
2425 if (exception_code == EXCEPTION_ACCESS_VIOLATION) { |
2426 JavaThread* thread = (JavaThread*) t; |
2426 JavaThread* thread = (JavaThread*) t; |
2427 PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord; |
2427 PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord; |
2428 address addr = (address) exceptionRecord->ExceptionInformation[1]; |
2428 address addr = (address) exceptionRecord->ExceptionInformation[1]; |
2429 if ( os::is_memory_serialize_page(thread, addr) ) { |
2429 if (os::is_memory_serialize_page(thread, addr)) { |
2430 // Block current thread until the memory serialize page permission restored. |
2430 // Block current thread until the memory serialize page permission restored. |
2431 os::block_on_serialize_page_trap(); |
2431 os::block_on_serialize_page_trap(); |
2432 return EXCEPTION_CONTINUE_EXECUTION; |
2432 return EXCEPTION_CONTINUE_EXECUTION; |
2433 } |
2433 } |
2434 } |
2434 } |
2541 // |
2541 // |
2542 // If it's a legal stack address map the entire region in |
2542 // If it's a legal stack address map the entire region in |
2543 // |
2543 // |
2544 PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord; |
2544 PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord; |
2545 address addr = (address) exceptionRecord->ExceptionInformation[1]; |
2545 address addr = (address) exceptionRecord->ExceptionInformation[1]; |
2546 if (addr > thread->stack_yellow_zone_base() && addr < thread->stack_base() ) { |
2546 if (addr > thread->stack_yellow_zone_base() && addr < thread->stack_base()) { |
2547 addr = (address)((uintptr_t)addr & |
2547 addr = (address)((uintptr_t)addr & |
2548 (~((uintptr_t)os::vm_page_size() - (uintptr_t)1))); |
2548 (~((uintptr_t)os::vm_page_size() - (uintptr_t)1))); |
2549 os::commit_memory((char *)addr, thread->stack_base() - addr, |
2549 os::commit_memory((char *)addr, thread->stack_base() - addr, |
2550 !ExecMem); |
2550 !ExecMem); |
2551 return EXCEPTION_CONTINUE_EXECUTION; |
2551 return EXCEPTION_CONTINUE_EXECUTION; |
2621 M37 handle_wrong_method_break(0, NativeJump::HANDLE_WRONG_METHOD, PR0); |
2621 M37 handle_wrong_method_break(0, NativeJump::HANDLE_WRONG_METHOD, PR0); |
2622 |
2622 |
2623 // Compiled method patched to be non entrant? Following conditions must apply: |
2623 // Compiled method patched to be non entrant? Following conditions must apply: |
2624 // 1. must be first instruction in bundle |
2624 // 1. must be first instruction in bundle |
2625 // 2. must be a break instruction with appropriate code |
2625 // 2. must be a break instruction with appropriate code |
2626 if((((uint64_t) pc & 0x0F) == 0) && |
2626 if ((((uint64_t) pc & 0x0F) == 0) && |
2627 (((IPF_Bundle*) pc)->get_slot0() == handle_wrong_method_break.bits())) { |
2627 (((IPF_Bundle*) pc)->get_slot0() == handle_wrong_method_break.bits())) { |
2628 return Handle_Exception(exceptionInfo, |
2628 return Handle_Exception(exceptionInfo, |
2629 (address)SharedRuntime::get_handle_wrong_method_stub()); |
2629 (address)SharedRuntime::get_handle_wrong_method_stub()); |
2630 } |
2630 } |
2631 } // /EXCEPTION_ILLEGAL_INSTRUCTION |
2631 } // /EXCEPTION_ILLEGAL_INSTRUCTION |
3110 bool use_individual = (UseNUMAInterleaving && !UseLargePages); |
3110 bool use_individual = (UseNUMAInterleaving && !UseLargePages); |
3111 if (!use_individual) { |
3111 if (!use_individual) { |
3112 res = (char*)VirtualAlloc(addr, bytes, MEM_RESERVE, PAGE_READWRITE); |
3112 res = (char*)VirtualAlloc(addr, bytes, MEM_RESERVE, PAGE_READWRITE); |
3113 } else { |
3113 } else { |
3114 elapsedTimer reserveTimer; |
3114 elapsedTimer reserveTimer; |
3115 if( Verbose && PrintMiscellaneous ) reserveTimer.start(); |
3115 if (Verbose && PrintMiscellaneous) reserveTimer.start(); |
3116 // in numa interleaving, we have to allocate pages individually |
3116 // in numa interleaving, we have to allocate pages individually |
3117 // (well really chunks of NUMAInterleaveGranularity size) |
3117 // (well really chunks of NUMAInterleaveGranularity size) |
3118 res = allocate_pages_individually(bytes, addr, MEM_RESERVE, PAGE_READWRITE); |
3118 res = allocate_pages_individually(bytes, addr, MEM_RESERVE, PAGE_READWRITE); |
3119 if (res == NULL) { |
3119 if (res == NULL) { |
3120 warning("NUMA page allocation failed"); |
3120 warning("NUMA page allocation failed"); |
3121 } |
3121 } |
3122 if( Verbose && PrintMiscellaneous ) { |
3122 if (Verbose && PrintMiscellaneous) { |
3123 reserveTimer.stop(); |
3123 reserveTimer.stop(); |
3124 tty->print_cr("reserve_memory of %Ix bytes took " JLONG_FORMAT " ms (" JLONG_FORMAT " ticks)", bytes, |
3124 tty->print_cr("reserve_memory of %Ix bytes took " JLONG_FORMAT " ms (" JLONG_FORMAT " ticks)", bytes, |
3125 reserveTimer.milliseconds(), reserveTimer.ticks()); |
3125 reserveTimer.milliseconds(), reserveTimer.ticks()); |
3126 } |
3126 } |
3127 } |
3127 } |
3448 }; |
3448 }; |
3449 |
3449 |
3450 int os::sleep(Thread* thread, jlong ms, bool interruptable) { |
3450 int os::sleep(Thread* thread, jlong ms, bool interruptable) { |
3451 jlong limit = (jlong) MAXDWORD; |
3451 jlong limit = (jlong) MAXDWORD; |
3452 |
3452 |
3453 while(ms > limit) { |
3453 while (ms > limit) { |
3454 int res; |
3454 int res; |
3455 if ((res = sleep(thread, limit, interruptable)) != OS_TIMEOUT) |
3455 if ((res = sleep(thread, limit, interruptable)) != OS_TIMEOUT) |
3456 return res; |
3456 return res; |
3457 ms -= limit; |
3457 ms -= limit; |
3458 } |
3458 } |
3459 |
3459 |
3460 assert(thread == Thread::current(), "thread consistency check"); |
3460 assert(thread == Thread::current(), "thread consistency check"); |
3461 OSThread* osthread = thread->osthread(); |
3461 OSThread* osthread = thread->osthread(); |
3462 OSThreadWaitState osts(osthread, false /* not Object.wait() */); |
3462 OSThreadWaitState osts(osthread, false /* not Object.wait() */); |
3463 int result; |
3463 int result; |
3464 if (interruptable) { |
3464 if (interruptable) { |
3465 assert(thread->is_Java_thread(), "must be java thread"); |
3465 assert(thread->is_Java_thread(), "must be java thread"); |
3471 // java_suspend_self() via check_and_wait_while_suspended() |
3471 // java_suspend_self() via check_and_wait_while_suspended() |
3472 |
3472 |
3473 HANDLE events[1]; |
3473 HANDLE events[1]; |
3474 events[0] = osthread->interrupt_event(); |
3474 events[0] = osthread->interrupt_event(); |
3475 HighResolutionInterval *phri=NULL; |
3475 HighResolutionInterval *phri=NULL; |
3476 if(!ForceTimeHighResolution) |
3476 if (!ForceTimeHighResolution) |
3477 phri = new HighResolutionInterval( ms ); |
3477 phri = new HighResolutionInterval(ms); |
3478 if (WaitForMultipleObjects(1, events, FALSE, (DWORD)ms) == WAIT_TIMEOUT) { |
3478 if (WaitForMultipleObjects(1, events, FALSE, (DWORD)ms) == WAIT_TIMEOUT) { |
3479 result = OS_TIMEOUT; |
3479 result = OS_TIMEOUT; |
3480 } else { |
3480 } else { |
3481 ResetEvent(osthread->interrupt_event()); |
3481 ResetEvent(osthread->interrupt_event()); |
3482 osthread->set_interrupted(false); |
3482 osthread->set_interrupted(false); |
3509 while (true) { // sleep forever ... |
3509 while (true) { // sleep forever ... |
3510 Sleep(100000); // ... 100 seconds at a time |
3510 Sleep(100000); // ... 100 seconds at a time |
3511 } |
3511 } |
3512 } |
3512 } |
3513 |
3513 |
3514 typedef BOOL (WINAPI * STTSignature)(void) ; |
3514 typedef BOOL (WINAPI * STTSignature)(void); |
3515 |
3515 |
3516 os::YieldResult os::NakedYield() { |
3516 os::YieldResult os::NakedYield() { |
3517 // Use either SwitchToThread() or Sleep(0) |
3517 // Use either SwitchToThread() or Sleep(0) |
3518 // Consider passing back the return value from SwitchToThread(). |
3518 // Consider passing back the return value from SwitchToThread(). |
3519 if (os::Kernel32Dll::SwitchToThreadAvailable()) { |
3519 if (os::Kernel32Dll::SwitchToThreadAvailable()) { |
3520 return SwitchToThread() ? os::YIELD_SWITCHED : os::YIELD_NONEREADY ; |
3520 return SwitchToThread() ? os::YIELD_SWITCHED : os::YIELD_NONEREADY; |
3521 } else { |
3521 } else { |
3522 Sleep(0); |
3522 Sleep(0); |
3523 } |
3523 } |
3524 return os::YIELD_UNKNOWN ; |
3524 return os::YIELD_UNKNOWN; |
3525 } |
3525 } |
3526 |
3526 |
3527 void os::yield() { os::NakedYield(); } |
3527 void os::yield() { os::NakedYield(); } |
3528 |
3528 |
3529 void os::yield_all() { |
3529 void os::yield_all() { |
3896 |
3896 |
3897 // this is called _after_ the global arguments have been parsed |
3897 // this is called _after_ the global arguments have been parsed |
3898 jint os::init_2(void) { |
3898 jint os::init_2(void) { |
3899 // Allocate a single page and mark it as readable for safepoint polling |
3899 // Allocate a single page and mark it as readable for safepoint polling |
3900 address polling_page = (address)VirtualAlloc(NULL, os::vm_page_size(), MEM_RESERVE, PAGE_READONLY); |
3900 address polling_page = (address)VirtualAlloc(NULL, os::vm_page_size(), MEM_RESERVE, PAGE_READONLY); |
3901 guarantee( polling_page != NULL, "Reserve Failed for polling page"); |
3901 guarantee(polling_page != NULL, "Reserve Failed for polling page"); |
3902 |
3902 |
3903 address return_page = (address)VirtualAlloc(polling_page, os::vm_page_size(), MEM_COMMIT, PAGE_READONLY); |
3903 address return_page = (address)VirtualAlloc(polling_page, os::vm_page_size(), MEM_COMMIT, PAGE_READONLY); |
3904 guarantee( return_page != NULL, "Commit Failed for polling page"); |
3904 guarantee(return_page != NULL, "Commit Failed for polling page"); |
3905 |
3905 |
3906 os::set_polling_page( polling_page ); |
3906 os::set_polling_page(polling_page); |
3907 |
3907 |
3908 #ifndef PRODUCT |
3908 #ifndef PRODUCT |
3909 if( Verbose && PrintMiscellaneous ) |
3909 if (Verbose && PrintMiscellaneous) |
3910 tty->print("[SafePoint Polling address: " INTPTR_FORMAT "]\n", (intptr_t)polling_page); |
3910 tty->print("[SafePoint Polling address: " INTPTR_FORMAT "]\n", (intptr_t)polling_page); |
3911 #endif |
3911 #endif |
3912 |
3912 |
3913 if (!UseMembar) { |
3913 if (!UseMembar) { |
3914 address mem_serialize_page = (address)VirtualAlloc(NULL, os::vm_page_size(), MEM_RESERVE, PAGE_READWRITE); |
3914 address mem_serialize_page = (address)VirtualAlloc(NULL, os::vm_page_size(), MEM_RESERVE, PAGE_READWRITE); |
3915 guarantee( mem_serialize_page != NULL, "Reserve Failed for memory serialize page"); |
3915 guarantee(mem_serialize_page != NULL, "Reserve Failed for memory serialize page"); |
3916 |
3916 |
3917 return_page = (address)VirtualAlloc(mem_serialize_page, os::vm_page_size(), MEM_COMMIT, PAGE_READWRITE); |
3917 return_page = (address)VirtualAlloc(mem_serialize_page, os::vm_page_size(), MEM_COMMIT, PAGE_READWRITE); |
3918 guarantee( return_page != NULL, "Commit Failed for memory serialize page"); |
3918 guarantee(return_page != NULL, "Commit Failed for memory serialize page"); |
3919 |
3919 |
3920 os::set_memory_serialize_page( mem_serialize_page ); |
3920 os::set_memory_serialize_page(mem_serialize_page); |
3921 |
3921 |
3922 #ifndef PRODUCT |
3922 #ifndef PRODUCT |
3923 if(Verbose && PrintMiscellaneous) |
3923 if (Verbose && PrintMiscellaneous) |
3924 tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", (intptr_t)mem_serialize_page); |
3924 tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", (intptr_t)mem_serialize_page); |
3925 #endif |
3925 #endif |
3926 } |
3926 } |
3927 |
3927 |
3928 // Setup Windows Exceptions |
3928 // Setup Windows Exceptions |
4034 } |
4034 } |
4035 |
4035 |
4036 // Mark the polling page as unreadable |
4036 // Mark the polling page as unreadable |
4037 void os::make_polling_page_unreadable(void) { |
4037 void os::make_polling_page_unreadable(void) { |
4038 DWORD old_status; |
4038 DWORD old_status; |
4039 if( !VirtualProtect((char *)_polling_page, os::vm_page_size(), PAGE_NOACCESS, &old_status) ) |
4039 if (!VirtualProtect((char *)_polling_page, os::vm_page_size(), PAGE_NOACCESS, &old_status)) |
4040 fatal("Could not disable polling page"); |
4040 fatal("Could not disable polling page"); |
4041 }; |
4041 }; |
4042 |
4042 |
4043 // Mark the polling page as readable |
4043 // Mark the polling page as readable |
4044 void os::make_polling_page_readable(void) { |
4044 void os::make_polling_page_readable(void) { |
4045 DWORD old_status; |
4045 DWORD old_status; |
4046 if( !VirtualProtect((char *)_polling_page, os::vm_page_size(), PAGE_READONLY, &old_status) ) |
4046 if (!VirtualProtect((char *)_polling_page, os::vm_page_size(), PAGE_READONLY, &old_status)) |
4047 fatal("Could not enable polling page"); |
4047 fatal("Could not enable polling page"); |
4048 }; |
4048 }; |
4049 |
4049 |
4050 |
4050 |
4051 int os::stat(const char *path, struct stat *sbuf) { |
4051 int os::stat(const char *path, struct stat *sbuf) { |
4788 // |
4788 // |
4789 // Another possible encoding of _Event would be |
4789 // Another possible encoding of _Event would be |
4790 // with explicit "PARKED" and "SIGNALED" bits. |
4790 // with explicit "PARKED" and "SIGNALED" bits. |
4791 |
4791 |
4792 int os::PlatformEvent::park (jlong Millis) { |
4792 int os::PlatformEvent::park (jlong Millis) { |
4793 guarantee (_ParkHandle != NULL , "Invariant") ; |
4793 guarantee(_ParkHandle != NULL , "Invariant"); |
4794 guarantee (Millis > 0 , "Invariant") ; |
4794 guarantee(Millis > 0 , "Invariant"); |
4795 int v ; |
4795 int v; |
4796 |
4796 |
4797 // CONSIDER: defer assigning a CreateEvent() handle to the Event until |
4797 // CONSIDER: defer assigning a CreateEvent() handle to the Event until |
4798 // the initial park() operation. |
4798 // the initial park() operation. |
4799 |
4799 |
4800 for (;;) { |
4800 for (;;) { |
4801 v = _Event ; |
4801 v = _Event; |
4802 if (Atomic::cmpxchg (v-1, &_Event, v) == v) break ; |
4802 if (Atomic::cmpxchg(v-1, &_Event, v) == v) break; |
4803 } |
4803 } |
4804 guarantee ((v == 0) || (v == 1), "invariant") ; |
4804 guarantee((v == 0) || (v == 1), "invariant"); |
4805 if (v != 0) return OS_OK ; |
4805 if (v != 0) return OS_OK; |
4806 |
4806 |
4807 // Do this the hard way by blocking ... |
4807 // Do this the hard way by blocking ... |
4808 // TODO: consider a brief spin here, gated on the success of recent |
4808 // TODO: consider a brief spin here, gated on the success of recent |
4809 // spin attempts by this thread. |
4809 // spin attempts by this thread. |
4810 // |
4810 // |
4818 // WAIT_OBJECT_0 but _Event is still < 0) we don't bother to recompute Millis to compensate |
4818 // WAIT_OBJECT_0 but _Event is still < 0) we don't bother to recompute Millis to compensate |
4819 // for the already waited time. This policy does not admit any new outcomes. |
4819 // for the already waited time. This policy does not admit any new outcomes. |
4820 // In the future, however, we might want to track the accumulated wait time and |
4820 // In the future, however, we might want to track the accumulated wait time and |
4821 // adjust Millis accordingly if we encounter a spurious wakeup. |
4821 // adjust Millis accordingly if we encounter a spurious wakeup. |
4822 |
4822 |
4823 const int MAXTIMEOUT = 0x10000000 ; |
4823 const int MAXTIMEOUT = 0x10000000; |
4824 DWORD rv = WAIT_TIMEOUT ; |
4824 DWORD rv = WAIT_TIMEOUT; |
4825 while (_Event < 0 && Millis > 0) { |
4825 while (_Event < 0 && Millis > 0) { |
4826 DWORD prd = Millis ; // set prd = MAX (Millis, MAXTIMEOUT) |
4826 DWORD prd = Millis; // set prd = MAX (Millis, MAXTIMEOUT) |
4827 if (Millis > MAXTIMEOUT) { |
4827 if (Millis > MAXTIMEOUT) { |
4828 prd = MAXTIMEOUT ; |
4828 prd = MAXTIMEOUT; |
4829 } |
4829 } |
4830 rv = ::WaitForSingleObject (_ParkHandle, prd) ; |
4830 rv = ::WaitForSingleObject(_ParkHandle, prd); |
4831 assert (rv == WAIT_OBJECT_0 || rv == WAIT_TIMEOUT, "WaitForSingleObject failed") ; |
4831 assert(rv == WAIT_OBJECT_0 || rv == WAIT_TIMEOUT, "WaitForSingleObject failed"); |
4832 if (rv == WAIT_TIMEOUT) { |
4832 if (rv == WAIT_TIMEOUT) { |
4833 Millis -= prd ; |
4833 Millis -= prd; |
4834 } |
4834 } |
4835 } |
4835 } |
4836 v = _Event ; |
4836 v = _Event; |
4837 _Event = 0 ; |
4837 _Event = 0; |
4838 // see comment at end of os::PlatformEvent::park() below: |
4838 // see comment at end of os::PlatformEvent::park() below: |
4839 OrderAccess::fence() ; |
4839 OrderAccess::fence(); |
4840 // If we encounter a nearly simultanous timeout expiry and unpark() |
4840 // If we encounter a nearly simultanous timeout expiry and unpark() |
4841 // we return OS_OK indicating we awoke via unpark(). |
4841 // we return OS_OK indicating we awoke via unpark(). |
4842 // Implementor's license -- returning OS_TIMEOUT would be equally valid, however. |
4842 // Implementor's license -- returning OS_TIMEOUT would be equally valid, however. |
4843 return (v >= 0) ? OS_OK : OS_TIMEOUT ; |
4843 return (v >= 0) ? OS_OK : OS_TIMEOUT; |
4844 } |
4844 } |
4845 |
4845 |
4846 void os::PlatformEvent::park () { |
4846 void os::PlatformEvent::park() { |
4847 guarantee (_ParkHandle != NULL, "Invariant") ; |
4847 guarantee(_ParkHandle != NULL, "Invariant"); |
4848 // Invariant: Only the thread associated with the Event/PlatformEvent |
4848 // Invariant: Only the thread associated with the Event/PlatformEvent |
4849 // may call park(). |
4849 // may call park(). |
4850 int v ; |
4850 int v; |
4851 for (;;) { |
4851 for (;;) { |
4852 v = _Event ; |
4852 v = _Event; |
4853 if (Atomic::cmpxchg (v-1, &_Event, v) == v) break ; |
4853 if (Atomic::cmpxchg(v-1, &_Event, v) == v) break; |
4854 } |
4854 } |
4855 guarantee ((v == 0) || (v == 1), "invariant") ; |
4855 guarantee((v == 0) || (v == 1), "invariant"); |
4856 if (v != 0) return ; |
4856 if (v != 0) return; |
4857 |
4857 |
4858 // Do this the hard way by blocking ... |
4858 // Do this the hard way by blocking ... |
4859 // TODO: consider a brief spin here, gated on the success of recent |
4859 // TODO: consider a brief spin here, gated on the success of recent |
4860 // spin attempts by this thread. |
4860 // spin attempts by this thread. |
4861 while (_Event < 0) { |
4861 while (_Event < 0) { |
4862 DWORD rv = ::WaitForSingleObject (_ParkHandle, INFINITE) ; |
4862 DWORD rv = ::WaitForSingleObject(_ParkHandle, INFINITE); |
4863 assert (rv == WAIT_OBJECT_0, "WaitForSingleObject failed") ; |
4863 assert(rv == WAIT_OBJECT_0, "WaitForSingleObject failed"); |
4864 } |
4864 } |
4865 |
4865 |
4866 // Usually we'll find _Event == 0 at this point, but as |
4866 // Usually we'll find _Event == 0 at this point, but as |
4867 // an optional optimization we clear it, just in case can |
4867 // an optional optimization we clear it, just in case can |
4868 // multiple unpark() operations drove _Event up to 1. |
4868 // multiple unpark() operations drove _Event up to 1. |
4869 _Event = 0 ; |
4869 _Event = 0; |
4870 OrderAccess::fence() ; |
4870 OrderAccess::fence(); |
4871 guarantee (_Event >= 0, "invariant") ; |
4871 guarantee(_Event >= 0, "invariant"); |
4872 } |
4872 } |
4873 |
4873 |
4874 void os::PlatformEvent::unpark() { |
4874 void os::PlatformEvent::unpark() { |
4875 guarantee (_ParkHandle != NULL, "Invariant") ; |
4875 guarantee(_ParkHandle != NULL, "Invariant"); |
4876 |
4876 |
4877 // Transitions for _Event: |
4877 // Transitions for _Event: |
4878 // 0 :=> 1 |
4878 // 0 :=> 1 |
4879 // 1 :=> 1 |
4879 // 1 :=> 1 |
4880 // -1 :=> either 0 or 1; must signal target thread |
4880 // -1 :=> either 0 or 1; must signal target thread |
4939 else { |
4939 else { |
4940 ThreadBlockInVM tbivm(jt); |
4940 ThreadBlockInVM tbivm(jt); |
4941 OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */); |
4941 OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */); |
4942 jt->set_suspend_equivalent(); |
4942 jt->set_suspend_equivalent(); |
4943 |
4943 |
4944 WaitForSingleObject(_ParkEvent, time); |
4944 WaitForSingleObject(_ParkEvent, time); |
4945 ResetEvent(_ParkEvent); |
4945 ResetEvent(_ParkEvent); |
4946 |
4946 |
4947 // If externally suspended while waiting, re-suspend |
4947 // If externally suspended while waiting, re-suspend |
4948 if (jt->handle_special_suspend_equivalent_condition()) { |
4948 if (jt->handle_special_suspend_equivalent_condition()) { |
4949 jt->java_suspend_self(); |
4949 jt->java_suspend_self(); |
4950 } |
4950 } |
4951 } |
4951 } |
4952 } |
4952 } |
4953 |
4953 |
4954 void Parker::unpark() { |
4954 void Parker::unpark() { |
4955 guarantee (_ParkEvent != NULL, "invariant") ; |
4955 guarantee(_ParkEvent != NULL, "invariant"); |
4956 SetEvent(_ParkEvent); |
4956 SetEvent(_ParkEvent); |
4957 } |
4957 } |
4958 |
4958 |
4959 // Run the specified command in a separate process. Return its exit value, |
4959 // Run the specified command in a separate process. Return its exit value, |
4960 // or -1 on failure (e.g. can't create a new process). |
4960 // or -1 on failure (e.g. can't create a new process). |