1363 |
1356 |
1364 // Loads .dll/.so and |
1357 // Loads .dll/.so and |
1365 // in case of error it checks if .dll/.so was built for the |
1358 // in case of error it checks if .dll/.so was built for the |
1366 // same architecture as Hotspot is running on |
1359 // same architecture as Hotspot is running on |
1367 void * os::dll_load(const char *name, char *ebuf, int ebuflen) { |
1360 void * os::dll_load(const char *name, char *ebuf, int ebuflen) { |
|
1361 log_info(os)("attempting shared library load of %s", name); |
|
1362 |
1368 void * result = LoadLibrary(name); |
1363 void * result = LoadLibrary(name); |
1369 if (result != NULL) { |
1364 if (result != NULL) { |
|
1365 Events::log(NULL, "Loaded shared library %s", name); |
1370 // Recalculate pdb search path if a DLL was loaded successfully. |
1366 // Recalculate pdb search path if a DLL was loaded successfully. |
1371 SymbolEngine::recalc_search_path(); |
1367 SymbolEngine::recalc_search_path(); |
|
1368 log_info(os)("shared library load of %s was successful", name); |
1372 return result; |
1369 return result; |
1373 } |
1370 } |
1374 |
|
1375 DWORD errcode = GetLastError(); |
1371 DWORD errcode = GetLastError(); |
|
1372 // Read system error message into ebuf |
|
1373 // It may or may not be overwritten below (in the for loop and just above) |
|
1374 lasterror(ebuf, (size_t) ebuflen); |
|
1375 ebuf[ebuflen - 1] = '\0'; |
|
1376 Events::log(NULL, "Loading shared library %s failed, error code %lu", name, errcode); |
|
1377 log_info(os)("shared library load of %s failed, error code %lu", name, errcode); |
|
1378 |
1376 if (errcode == ERROR_MOD_NOT_FOUND) { |
1379 if (errcode == ERROR_MOD_NOT_FOUND) { |
1377 strncpy(ebuf, "Can't find dependent libraries", ebuflen - 1); |
1380 strncpy(ebuf, "Can't find dependent libraries", ebuflen - 1); |
1378 ebuf[ebuflen - 1] = '\0'; |
1381 ebuf[ebuflen - 1] = '\0'; |
1379 return NULL; |
1382 return NULL; |
1380 } |
1383 } |
3465 // 1: Thread is running now |
3469 // 1: Thread is running now |
3466 // >1: Thread is still suspended. |
3470 // >1: Thread is still suspended. |
3467 assert(ret != SYS_THREAD_ERROR, "StartThread failed"); // should propagate back |
3471 assert(ret != SYS_THREAD_ERROR, "StartThread failed"); // should propagate back |
3468 } |
3472 } |
3469 |
3473 |
3470 class HighResolutionInterval : public CHeapObj<mtThread> { |
|
3471 // The default timer resolution seems to be 10 milliseconds. |
|
3472 // (Where is this written down?) |
|
3473 // If someone wants to sleep for only a fraction of the default, |
|
3474 // then we set the timer resolution down to 1 millisecond for |
|
3475 // the duration of their interval. |
|
3476 // We carefully set the resolution back, since otherwise we |
|
3477 // seem to incur an overhead (3%?) that we don't need. |
|
3478 // CONSIDER: if ms is small, say 3, then we should run with a high resolution time. |
|
3479 // Buf if ms is large, say 500, or 503, we should avoid the call to timeBeginPeriod(). |
|
3480 // Alternatively, we could compute the relative error (503/500 = .6%) and only use |
|
3481 // timeBeginPeriod() if the relative error exceeded some threshold. |
|
3482 // timeBeginPeriod() has been linked to problems with clock drift on win32 systems and |
|
3483 // to decreased efficiency related to increased timer "tick" rates. We want to minimize |
|
3484 // (a) calls to timeBeginPeriod() and timeEndPeriod() and (b) time spent with high |
|
3485 // resolution timers running. |
|
3486 private: |
|
3487 jlong resolution; |
|
3488 public: |
|
3489 HighResolutionInterval(jlong ms) { |
|
3490 resolution = ms % 10L; |
|
3491 if (resolution != 0) { |
|
3492 MMRESULT result = timeBeginPeriod(1L); |
|
3493 } |
|
3494 } |
|
3495 ~HighResolutionInterval() { |
|
3496 if (resolution != 0) { |
|
3497 MMRESULT result = timeEndPeriod(1L); |
|
3498 } |
|
3499 resolution = 0L; |
|
3500 } |
|
3501 }; |
|
3502 |
|
3503 int os::sleep(Thread* thread, jlong ms, bool interruptable) { |
|
3504 jlong limit = (jlong) MAXDWORD; |
|
3505 |
|
3506 while (ms > limit) { |
|
3507 int res; |
|
3508 if ((res = sleep(thread, limit, interruptable)) != OS_TIMEOUT) { |
|
3509 return res; |
|
3510 } |
|
3511 ms -= limit; |
|
3512 } |
|
3513 |
|
3514 assert(thread == Thread::current(), "thread consistency check"); |
|
3515 OSThread* osthread = thread->osthread(); |
|
3516 OSThreadWaitState osts(osthread, false /* not Object.wait() */); |
|
3517 int result; |
|
3518 if (interruptable) { |
|
3519 assert(thread->is_Java_thread(), "must be java thread"); |
|
3520 JavaThread *jt = (JavaThread *) thread; |
|
3521 ThreadBlockInVM tbivm(jt); |
|
3522 |
|
3523 jt->set_suspend_equivalent(); |
|
3524 // cleared by handle_special_suspend_equivalent_condition() or |
|
3525 // java_suspend_self() via check_and_wait_while_suspended() |
|
3526 |
|
3527 HANDLE events[1]; |
|
3528 events[0] = osthread->interrupt_event(); |
|
3529 HighResolutionInterval *phri=NULL; |
|
3530 if (!ForceTimeHighResolution) { |
|
3531 phri = new HighResolutionInterval(ms); |
|
3532 } |
|
3533 if (WaitForMultipleObjects(1, events, FALSE, (DWORD)ms) == WAIT_TIMEOUT) { |
|
3534 result = OS_TIMEOUT; |
|
3535 } else { |
|
3536 ResetEvent(osthread->interrupt_event()); |
|
3537 osthread->set_interrupted(false); |
|
3538 result = OS_INTRPT; |
|
3539 } |
|
3540 delete phri; //if it is NULL, harmless |
|
3541 |
|
3542 // were we externally suspended while we were waiting? |
|
3543 jt->check_and_wait_while_suspended(); |
|
3544 } else { |
|
3545 assert(!thread->is_Java_thread(), "must not be java thread"); |
|
3546 Sleep((long) ms); |
|
3547 result = OS_TIMEOUT; |
|
3548 } |
|
3549 return result; |
|
3550 } |
|
3551 |
3474 |
3552 // Short sleep, direct OS call. |
3475 // Short sleep, direct OS call. |
3553 // |
3476 // |
3554 // ms = 0, means allow others (if any) to run. |
3477 // ms = 0, means allow others (if any) to run. |
3555 // |
3478 // |
3652 assert(false, "GetThreadPriority failed"); |
3575 assert(false, "GetThreadPriority failed"); |
3653 return OS_ERR; |
3576 return OS_ERR; |
3654 } |
3577 } |
3655 *priority_ptr = os_prio; |
3578 *priority_ptr = os_prio; |
3656 return OS_OK; |
3579 return OS_OK; |
3657 } |
|
3658 |
|
3659 void os::interrupt(Thread* thread) { |
|
3660 debug_only(Thread::check_for_dangling_thread_pointer(thread);) |
|
3661 |
|
3662 OSThread* osthread = thread->osthread(); |
|
3663 osthread->set_interrupted(true); |
|
3664 // More than one thread can get here with the same value of osthread, |
|
3665 // resulting in multiple notifications. We do, however, want the store |
|
3666 // to interrupted() to be visible to other threads before we post |
|
3667 // the interrupt event. |
|
3668 OrderAccess::release(); |
|
3669 SetEvent(osthread->interrupt_event()); |
|
3670 // For JSR166: unpark after setting status |
|
3671 if (thread->is_Java_thread()) { |
|
3672 ((JavaThread*)thread)->parker()->unpark(); |
|
3673 } |
|
3674 |
|
3675 ParkEvent * ev = thread->_ParkEvent; |
|
3676 if (ev != NULL) ev->unpark(); |
|
3677 } |
|
3678 |
|
3679 |
|
3680 bool os::is_interrupted(Thread* thread, bool clear_interrupted) { |
|
3681 debug_only(Thread::check_for_dangling_thread_pointer(thread);) |
|
3682 |
|
3683 OSThread* osthread = thread->osthread(); |
|
3684 // There is no synchronization between the setting of the interrupt |
|
3685 // and it being cleared here. It is critical - see 6535709 - that |
|
3686 // we only clear the interrupt state, and reset the interrupt event, |
|
3687 // if we are going to report that we were indeed interrupted - else |
|
3688 // an interrupt can be "lost", leading to spurious wakeups or lost wakeups |
|
3689 // depending on the timing. By checking thread interrupt event to see |
|
3690 // if the thread gets real interrupt thus prevent spurious wakeup. |
|
3691 bool interrupted = osthread->interrupted() && (WaitForSingleObject(osthread->interrupt_event(), 0) == WAIT_OBJECT_0); |
|
3692 if (interrupted && clear_interrupted) { |
|
3693 osthread->set_interrupted(false); |
|
3694 ResetEvent(osthread->interrupt_event()); |
|
3695 } // Otherwise leave the interrupted state alone |
|
3696 |
|
3697 return interrupted; |
|
3698 } |
3580 } |
3699 |
3581 |
3700 // GetCurrentThreadId() returns DWORD |
3582 // GetCurrentThreadId() returns DWORD |
3701 intx os::current_thread_id() { return GetCurrentThreadId(); } |
3583 intx os::current_thread_id() { return GetCurrentThreadId(); } |
3702 |
3584 |
4268 } else { |
4144 } else { |
4269 sbuf->st_mode |= S_IFREG; |
4145 sbuf->st_mode |= S_IFREG; |
4270 } |
4146 } |
4271 } |
4147 } |
4272 |
4148 |
4273 // The following function is adapted from java.base/windows/native/libjava/canonicalize_md.c |
4149 // Returns the given path as an absolute wide path in unc format. The returned path is NULL |
4274 // Creates an UNC path from a single byte path. Return buffer is |
4150 // on error (with err being set accordingly) and should be freed via os::free() otherwise. |
4275 // allocated in C heap and needs to be freed by the caller. |
4151 // additional_space is the number of additionally allocated wchars after the terminating L'\0'. |
4276 // Returns NULL on error. |
4152 // This is based on pathToNTPath() in io_util_md.cpp, but omits the optimizations for |
4277 static wchar_t* create_unc_path(const char* path, errno_t &err) { |
4153 // short paths. |
4278 wchar_t* wpath = NULL; |
4154 static wchar_t* wide_abs_unc_path(char const* path, errno_t & err, int additional_space = 0) { |
4279 size_t converted_chars = 0; |
4155 if ((path == NULL) || (path[0] == '\0')) { |
4280 size_t path_len = strlen(path) + 1; // includes the terminating NULL |
4156 err = ENOENT; |
4281 if (path[0] == '\\' && path[1] == '\\') { |
4157 return NULL; |
4282 if (path[2] == '?' && path[3] == '\\'){ |
4158 } |
4283 // if it already has a \\?\ don't do the prefix |
4159 |
4284 wpath = (wchar_t*)os::malloc(path_len * sizeof(wchar_t), mtInternal); |
4160 size_t path_len = strlen(path); |
4285 if (wpath != NULL) { |
4161 // Need to allocate at least room for 3 characters, since os::native_path transforms C: to C:. |
4286 err = ::mbstowcs_s(&converted_chars, wpath, path_len, path, path_len); |
4162 char* buf = (char*) os::malloc(1 + MAX2((size_t) 3, path_len), mtInternal); |
|
4163 wchar_t* result = NULL; |
|
4164 |
|
4165 if (buf == NULL) { |
|
4166 err = ENOMEM; |
|
4167 } else { |
|
4168 memcpy(buf, path, path_len + 1); |
|
4169 os::native_path(buf); |
|
4170 |
|
4171 wchar_t* prefix; |
|
4172 int prefix_off = 0; |
|
4173 bool is_abs = true; |
|
4174 bool needs_fullpath = true; |
|
4175 |
|
4176 if (::isalpha(buf[0]) && !::IsDBCSLeadByte(buf[0]) && buf[1] == ':' && buf[2] == '\\') { |
|
4177 prefix = L"\\\\?\\"; |
|
4178 } else if (buf[0] == '\\' && buf[1] == '\\') { |
|
4179 if (buf[2] == '?' && buf[3] == '\\') { |
|
4180 prefix = L""; |
|
4181 needs_fullpath = false; |
4287 } else { |
4182 } else { |
4288 err = ENOMEM; |
4183 prefix = L"\\\\?\\UNC"; |
|
4184 prefix_off = 1; // Overwrite the first char with the prefix, so \\share\path becomes \\?\UNC\share\path |
4289 } |
4185 } |
4290 } else { |
4186 } else { |
4291 // only UNC pathname includes double slashes here |
4187 is_abs = false; |
4292 wpath = (wchar_t*)os::malloc((path_len + 7) * sizeof(wchar_t), mtInternal); |
4188 prefix = L"\\\\?\\"; |
4293 if (wpath != NULL) { |
4189 } |
4294 ::wcscpy(wpath, L"\\\\?\\UNC\0"); |
4190 |
4295 err = ::mbstowcs_s(&converted_chars, &wpath[7], path_len, path, path_len); |
4191 size_t buf_len = strlen(buf); |
4296 } else { |
4192 size_t prefix_len = wcslen(prefix); |
4297 err = ENOMEM; |
4193 size_t full_path_size = is_abs ? 1 + buf_len : JVM_MAXPATHLEN; |
|
4194 size_t result_size = prefix_len + full_path_size - prefix_off; |
|
4195 result = (wchar_t*) os::malloc(sizeof(wchar_t) * (additional_space + result_size), mtInternal); |
|
4196 |
|
4197 if (result == NULL) { |
|
4198 err = ENOMEM; |
|
4199 } else { |
|
4200 size_t converted_chars; |
|
4201 wchar_t* path_start = result + prefix_len - prefix_off; |
|
4202 err = ::mbstowcs_s(&converted_chars, path_start, buf_len + 1, buf, buf_len); |
|
4203 |
|
4204 if ((err == ERROR_SUCCESS) && needs_fullpath) { |
|
4205 wchar_t* tmp = (wchar_t*) os::malloc(sizeof(wchar_t) * full_path_size, mtInternal); |
|
4206 |
|
4207 if (tmp == NULL) { |
|
4208 err = ENOMEM; |
|
4209 } else { |
|
4210 if (!_wfullpath(tmp, path_start, full_path_size)) { |
|
4211 err = ENOENT; |
|
4212 } else { |
|
4213 ::memcpy(path_start, tmp, (1 + wcslen(tmp)) * sizeof(wchar_t)); |
|
4214 } |
|
4215 |
|
4216 os::free(tmp); |
|
4217 } |
4298 } |
4218 } |
4299 } |
4219 |
4300 } else { |
4220 memcpy(result, prefix, sizeof(wchar_t) * prefix_len); |
4301 wpath = (wchar_t*)os::malloc((path_len + 4) * sizeof(wchar_t), mtInternal); |
4221 |
4302 if (wpath != NULL) { |
4222 // Remove trailing pathsep (not for \\?\<DRIVE>:\, since it would make it relative) |
4303 ::wcscpy(wpath, L"\\\\?\\\0"); |
4223 size_t result_len = wcslen(result); |
4304 err = ::mbstowcs_s(&converted_chars, &wpath[4], path_len, path, path_len); |
4224 |
4305 } else { |
4225 if (result[result_len - 1] == L'\\') { |
4306 err = ENOMEM; |
4226 if (!(::iswalpha(result[4]) && result[5] == L':' && result_len == 7)) { |
4307 } |
4227 result[result_len - 1] = L'\0'; |
4308 } |
4228 } |
4309 return wpath; |
4229 } |
4310 } |
4230 } |
4311 |
4231 } |
4312 static void destroy_unc_path(wchar_t* wpath) { |
4232 |
4313 os::free(wpath); |
4233 os::free(buf); |
|
4234 |
|
4235 if (err != ERROR_SUCCESS) { |
|
4236 os::free(result); |
|
4237 result = NULL; |
|
4238 } |
|
4239 |
|
4240 return result; |
4314 } |
4241 } |
4315 |
4242 |
4316 int os::stat(const char *path, struct stat *sbuf) { |
4243 int os::stat(const char *path, struct stat *sbuf) { |
4317 char* pathbuf = (char*)os::strdup(path, mtInternal); |
4244 errno_t err; |
4318 if (pathbuf == NULL) { |
4245 wchar_t* wide_path = wide_abs_unc_path(path, err); |
4319 errno = ENOMEM; |
4246 |
|
4247 if (wide_path == NULL) { |
|
4248 errno = err; |
4320 return -1; |
4249 return -1; |
4321 } |
4250 } |
4322 os::native_path(pathbuf); |
4251 |
4323 int ret; |
4252 WIN32_FILE_ATTRIBUTE_DATA file_data;; |
4324 WIN32_FILE_ATTRIBUTE_DATA file_data; |
4253 BOOL bret = ::GetFileAttributesExW(wide_path, GetFileExInfoStandard, &file_data); |
4325 // Not using stat() to avoid the problem described in JDK-6539723 |
4254 os::free(wide_path); |
4326 if (strlen(path) < MAX_PATH) { |
4255 |
4327 BOOL bret = ::GetFileAttributesExA(pathbuf, GetFileExInfoStandard, &file_data); |
4256 if (!bret) { |
4328 if (!bret) { |
4257 errno = ::GetLastError(); |
4329 errno = ::GetLastError(); |
4258 return -1; |
4330 ret = -1; |
4259 } |
4331 } |
4260 |
4332 else { |
4261 file_attribute_data_to_stat(sbuf, file_data); |
4333 file_attribute_data_to_stat(sbuf, file_data); |
4262 return 0; |
4334 ret = 0; |
4263 } |
4335 } |
4264 |
4336 } else { |
4265 static HANDLE create_read_only_file_handle(const char* file) { |
4337 errno_t err = ERROR_SUCCESS; |
4266 errno_t err; |
4338 wchar_t* wpath = create_unc_path(pathbuf, err); |
4267 wchar_t* wide_path = wide_abs_unc_path(file, err); |
4339 if (err != ERROR_SUCCESS) { |
4268 |
4340 if (wpath != NULL) { |
4269 if (wide_path == NULL) { |
4341 destroy_unc_path(wpath); |
4270 errno = err; |
|
4271 return INVALID_HANDLE_VALUE; |
|
4272 } |
|
4273 |
|
4274 HANDLE handle = ::CreateFileW(wide_path, 0, FILE_SHARE_READ, |
|
4275 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); |
|
4276 os::free(wide_path); |
|
4277 |
|
4278 return handle; |
|
4279 } |
|
4280 |
|
4281 bool os::same_files(const char* file1, const char* file2) { |
|
4282 |
|
4283 if (file1 == NULL && file2 == NULL) { |
|
4284 return true; |
|
4285 } |
|
4286 |
|
4287 if (file1 == NULL || file2 == NULL) { |
|
4288 return false; |
|
4289 } |
|
4290 |
|
4291 if (strcmp(file1, file2) == 0) { |
|
4292 return true; |
|
4293 } |
|
4294 |
|
4295 HANDLE handle1 = create_read_only_file_handle(file1); |
|
4296 HANDLE handle2 = create_read_only_file_handle(file2); |
|
4297 bool result = false; |
|
4298 |
|
4299 // if we could open both paths... |
|
4300 if (handle1 != INVALID_HANDLE_VALUE && handle2 != INVALID_HANDLE_VALUE) { |
|
4301 BY_HANDLE_FILE_INFORMATION fileInfo1; |
|
4302 BY_HANDLE_FILE_INFORMATION fileInfo2; |
|
4303 if (::GetFileInformationByHandle(handle1, &fileInfo1) && |
|
4304 ::GetFileInformationByHandle(handle2, &fileInfo2)) { |
|
4305 // the paths are the same if they refer to the same file (fileindex) on the same volume (volume serial number) |
|
4306 if (fileInfo1.dwVolumeSerialNumber == fileInfo2.dwVolumeSerialNumber && |
|
4307 fileInfo1.nFileIndexHigh == fileInfo2.nFileIndexHigh && |
|
4308 fileInfo1.nFileIndexLow == fileInfo2.nFileIndexLow) { |
|
4309 result = true; |
4342 } |
4310 } |
4343 os::free(pathbuf); |
4311 } |
4344 errno = err; |
4312 } |
4345 return -1; |
4313 |
4346 } |
4314 //free the handles |
4347 BOOL bret = ::GetFileAttributesExW(wpath, GetFileExInfoStandard, &file_data); |
4315 if (handle1 != INVALID_HANDLE_VALUE) { |
4348 if (!bret) { |
4316 ::CloseHandle(handle1); |
4349 errno = ::GetLastError(); |
4317 } |
4350 ret = -1; |
4318 |
4351 } else { |
4319 if (handle2 != INVALID_HANDLE_VALUE) { |
4352 file_attribute_data_to_stat(sbuf, file_data); |
4320 ::CloseHandle(handle2); |
4353 ret = 0; |
4321 } |
4354 } |
4322 |
4355 destroy_unc_path(wpath); |
4323 return result; |
4356 } |
4324 } |
4357 os::free(pathbuf); |
|
4358 return ret; |
|
4359 } |
|
4360 |
|
4361 |
4325 |
4362 #define FT2INT64(ft) \ |
4326 #define FT2INT64(ft) \ |
4363 ((jlong)((jlong)(ft).dwHighDateTime << 32 | (julong)(ft).dwLowDateTime)) |
4327 ((jlong)((jlong)(ft).dwHighDateTime << 32 | (julong)(ft).dwLowDateTime)) |
4364 |
4328 |
4365 |
4329 |
4461 // DontYieldALot=false by default: dutifully perform all yields as requested by JVM_Yield() |
4425 // DontYieldALot=false by default: dutifully perform all yields as requested by JVM_Yield() |
4462 bool os::dont_yield() { |
4426 bool os::dont_yield() { |
4463 return DontYieldALot; |
4427 return DontYieldALot; |
4464 } |
4428 } |
4465 |
4429 |
4466 // This method is a slightly reworked copy of JDK's sysOpen |
|
4467 // from src/windows/hpi/src/sys_api_md.c |
|
4468 |
|
4469 int os::open(const char *path, int oflag, int mode) { |
4430 int os::open(const char *path, int oflag, int mode) { |
4470 char* pathbuf = (char*)os::strdup(path, mtInternal); |
4431 errno_t err; |
4471 if (pathbuf == NULL) { |
4432 wchar_t* wide_path = wide_abs_unc_path(path, err); |
4472 errno = ENOMEM; |
4433 |
|
4434 if (wide_path == NULL) { |
|
4435 errno = err; |
4473 return -1; |
4436 return -1; |
4474 } |
4437 } |
4475 os::native_path(pathbuf); |
4438 int fd = ::_wopen(wide_path, oflag | O_BINARY | O_NOINHERIT, mode); |
4476 int ret; |
4439 os::free(wide_path); |
4477 if (strlen(path) < MAX_PATH) { |
4440 |
4478 ret = ::open(pathbuf, oflag | O_BINARY | O_NOINHERIT, mode); |
4441 if (fd == -1) { |
4479 } else { |
4442 errno = ::GetLastError(); |
4480 errno_t err = ERROR_SUCCESS; |
4443 } |
4481 wchar_t* wpath = create_unc_path(pathbuf, err); |
4444 |
4482 if (err != ERROR_SUCCESS) { |
4445 return fd; |
4483 if (wpath != NULL) { |
|
4484 destroy_unc_path(wpath); |
|
4485 } |
|
4486 os::free(pathbuf); |
|
4487 errno = err; |
|
4488 return -1; |
|
4489 } |
|
4490 ret = ::_wopen(wpath, oflag | O_BINARY | O_NOINHERIT, mode); |
|
4491 if (ret == -1) { |
|
4492 errno = ::GetLastError(); |
|
4493 } |
|
4494 destroy_unc_path(wpath); |
|
4495 } |
|
4496 os::free(pathbuf); |
|
4497 return ret; |
|
4498 } |
4446 } |
4499 |
4447 |
4500 FILE* os::open(int fd, const char* mode) { |
4448 FILE* os::open(int fd, const char* mode) { |
4501 return ::_fdopen(fd, mode); |
4449 return ::_fdopen(fd, mode); |
4502 } |
4450 } |
4503 |
4451 |
4504 // Is a (classpath) directory empty? |
4452 // Is a (classpath) directory empty? |
4505 bool os::dir_is_empty(const char* path) { |
4453 bool os::dir_is_empty(const char* path) { |
4506 char* search_path = (char*)os::malloc(strlen(path) + 3, mtInternal); |
4454 errno_t err; |
4507 if (search_path == NULL) { |
4455 wchar_t* wide_path = wide_abs_unc_path(path, err, 2); |
4508 errno = ENOMEM; |
4456 |
4509 return false; |
4457 if (wide_path == NULL) { |
4510 } |
|
4511 strcpy(search_path, path); |
|
4512 os::native_path(search_path); |
|
4513 // Append "*", or possibly "\\*", to path |
|
4514 if (search_path[1] == ':' && |
|
4515 (search_path[2] == '\0' || |
|
4516 (search_path[2] == '\\' && search_path[3] == '\0'))) { |
|
4517 // No '\\' needed for cases like "Z:" or "Z:\" |
|
4518 strcat(search_path, "*"); |
|
4519 } |
|
4520 else { |
|
4521 strcat(search_path, "\\*"); |
|
4522 } |
|
4523 errno_t err = ERROR_SUCCESS; |
|
4524 wchar_t* wpath = create_unc_path(search_path, err); |
|
4525 if (err != ERROR_SUCCESS) { |
|
4526 if (wpath != NULL) { |
|
4527 destroy_unc_path(wpath); |
|
4528 } |
|
4529 os::free(search_path); |
|
4530 errno = err; |
4458 errno = err; |
4531 return false; |
4459 return false; |
4532 } |
4460 } |
|
4461 |
|
4462 // Make sure we end with "\\*" |
|
4463 if (wide_path[wcslen(wide_path) - 1] == L'\\') { |
|
4464 wcscat(wide_path, L"*"); |
|
4465 } else { |
|
4466 wcscat(wide_path, L"\\*"); |
|
4467 } |
|
4468 |
4533 WIN32_FIND_DATAW fd; |
4469 WIN32_FIND_DATAW fd; |
4534 HANDLE f = ::FindFirstFileW(wpath, &fd); |
4470 HANDLE f = ::FindFirstFileW(wide_path, &fd); |
4535 destroy_unc_path(wpath); |
4471 os::free(wide_path); |
4536 bool is_empty = true; |
4472 bool is_empty = true; |
|
4473 |
4537 if (f != INVALID_HANDLE_VALUE) { |
4474 if (f != INVALID_HANDLE_VALUE) { |
4538 while (is_empty && ::FindNextFileW(f, &fd)) { |
4475 while (is_empty && ::FindNextFileW(f, &fd)) { |
4539 // An empty directory contains only the current directory file |
4476 // An empty directory contains only the current directory file |
4540 // and the previous directory file. |
4477 // and the previous directory file. |
4541 if ((wcscmp(fd.cFileName, L".") != 0) && |
4478 if ((wcscmp(fd.cFileName, L".") != 0) && |
4542 (wcscmp(fd.cFileName, L"..") != 0)) { |
4479 (wcscmp(fd.cFileName, L"..") != 0)) { |
4543 is_empty = false; |
4480 is_empty = false; |
4544 } |
4481 } |
4545 } |
4482 } |
4546 FindClose(f); |
4483 FindClose(f); |
4547 } |
4484 } else { |
4548 os::free(search_path); |
4485 errno = ::GetLastError(); |
|
4486 } |
|
4487 |
4549 return is_empty; |
4488 return is_empty; |
4550 } |
4489 } |
4551 |
4490 |
4552 // create binary file, rewriting existing file if required |
4491 // create binary file, rewriting existing file if required |
4553 int os::create_binary_file(const char* path, bool rewrite_existing) { |
4492 int os::create_binary_file(const char* path, bool rewrite_existing) { |
5069 _crash_protection = NULL; |
5011 _crash_protection = NULL; |
5070 _protected_thread = NULL; |
5012 _protected_thread = NULL; |
5071 Thread::muxRelease(&_crash_mux); |
5013 Thread::muxRelease(&_crash_mux); |
5072 return success; |
5014 return success; |
5073 } |
5015 } |
|
5016 |
|
5017 |
|
5018 class HighResolutionInterval : public CHeapObj<mtThread> { |
|
5019 // The default timer resolution seems to be 10 milliseconds. |
|
5020 // (Where is this written down?) |
|
5021 // If someone wants to sleep for only a fraction of the default, |
|
5022 // then we set the timer resolution down to 1 millisecond for |
|
5023 // the duration of their interval. |
|
5024 // We carefully set the resolution back, since otherwise we |
|
5025 // seem to incur an overhead (3%?) that we don't need. |
|
5026 // CONSIDER: if ms is small, say 3, then we should run with a high resolution time. |
|
5027 // Buf if ms is large, say 500, or 503, we should avoid the call to timeBeginPeriod(). |
|
5028 // Alternatively, we could compute the relative error (503/500 = .6%) and only use |
|
5029 // timeBeginPeriod() if the relative error exceeded some threshold. |
|
5030 // timeBeginPeriod() has been linked to problems with clock drift on win32 systems and |
|
5031 // to decreased efficiency related to increased timer "tick" rates. We want to minimize |
|
5032 // (a) calls to timeBeginPeriod() and timeEndPeriod() and (b) time spent with high |
|
5033 // resolution timers running. |
|
5034 private: |
|
5035 jlong resolution; |
|
5036 public: |
|
5037 HighResolutionInterval(jlong ms) { |
|
5038 resolution = ms % 10L; |
|
5039 if (resolution != 0) { |
|
5040 MMRESULT result = timeBeginPeriod(1L); |
|
5041 } |
|
5042 } |
|
5043 ~HighResolutionInterval() { |
|
5044 if (resolution != 0) { |
|
5045 MMRESULT result = timeEndPeriod(1L); |
|
5046 } |
|
5047 resolution = 0L; |
|
5048 } |
|
5049 }; |
5074 |
5050 |
5075 // An Event wraps a win32 "CreateEvent" kernel handle. |
5051 // An Event wraps a win32 "CreateEvent" kernel handle. |
5076 // |
5052 // |
5077 // We have a number of choices regarding "CreateEvent" win32 handle leakage: |
5053 // We have a number of choices regarding "CreateEvent" win32 handle leakage: |
5078 // |
5054 // |