4044 } 4045 4046 // Mark the polling page as unreadable 4047 void os::make_polling_page_unreadable(void) { 4048 DWORD old_status; 4049 if (!VirtualProtect((char *)_polling_page, os::vm_page_size(), 4050 PAGE_NOACCESS, &old_status)) { 4051 fatal("Could not disable polling page"); 4052 } 4053 } 4054 4055 // Mark the polling page as readable 4056 void os::make_polling_page_readable(void) { 4057 DWORD old_status; 4058 if (!VirtualProtect((char *)_polling_page, os::vm_page_size(), 4059 PAGE_READONLY, &old_status)) { 4060 fatal("Could not enable polling page"); 4061 } 4062 } 4063 4064 4065 int os::stat(const char *path, struct stat *sbuf) { 4066 char pathbuf[MAX_PATH]; 4067 if (strlen(path) > MAX_PATH - 1) { 4068 errno = ENAMETOOLONG; 4069 return -1; 4070 } 4071 os::native_path(strcpy(pathbuf, path)); 4072 int ret = ::stat(pathbuf, sbuf); 4073 if (sbuf != NULL && UseUTCFileTimestamp) { 4074 // Fix for 6539723. st_mtime returned from stat() is dependent on 4075 // the system timezone and so can return different values for the 4076 // same file if/when daylight savings time changes. This adjustment 4077 // makes sure the same timestamp is returned regardless of the TZ. 4078 // 4079 // See: 4080 // http://msdn.microsoft.com/library/ 4081 // default.asp?url=/library/en-us/sysinfo/base/ 4082 // time_zone_information_str.asp 4083 // and 4084 // http://msdn.microsoft.com/library/default.asp?url= 4085 // /library/en-us/sysinfo/base/settimezoneinformation.asp 4086 // 4087 // NOTE: there is a insidious bug here: If the timezone is changed 4088 // after the call to stat() but before 'GetTimeZoneInformation()', then 4089 // the adjustment we do here will be wrong and we'll return the wrong 4090 // value (which will likely end up creating an invalid class data 4091 // archive). Absent a better API for this, or some time zone locking 4092 // mechanism, we'll have to live with this risk. 4093 TIME_ZONE_INFORMATION tz; 4094 DWORD tzid = GetTimeZoneInformation(&tz); 4095 int daylightBias = 4096 (tzid == TIME_ZONE_ID_DAYLIGHT) ? tz.DaylightBias : tz.StandardBias; 4097 sbuf->st_mtime += (tz.Bias + daylightBias) * 60; 4098 } 4099 return ret; 4100 } 4101 4102 4103 #define FT2INT64(ft) \ 4104 ((jlong)((jlong)(ft).dwHighDateTime << 32 | (julong)(ft).dwLowDateTime)) 4105 4106 4107 // current_thread_cpu_time(bool) and thread_cpu_time(Thread*, bool) 4108 // are used by JVM M&M and JVMTI to get user+sys or user CPU time 4109 // of a thread. 4110 // 4111 // current_thread_cpu_time() and thread_cpu_time(Thread*) returns 4112 // the fast estimate available on the platform. 4113 4114 // current_thread_cpu_time() is not optimized for Windows yet 4115 jlong os::current_thread_cpu_time() { 4116 // return user + sys since the cost is the same 4117 return os::thread_cpu_time(Thread::current(), true /* user+sys */); 4118 } 4191 // just return the value of the global, avoiding the slow query. 4192 // 4193 // c) Sample a better answer using exponential decay to smooth the 4194 // value. This is basically the algorithm used by UNIX kernels. 4195 // 4196 // Note that sampling thread starvation could affect both (b) and (c). 4197 int os::loadavg(double loadavg[], int nelem) { 4198 return -1; 4199 } 4200 4201 4202 // DontYieldALot=false by default: dutifully perform all yields as requested by JVM_Yield() 4203 bool os::dont_yield() { 4204 return DontYieldALot; 4205 } 4206 4207 // This method is a slightly reworked copy of JDK's sysOpen 4208 // from src/windows/hpi/src/sys_api_md.c 4209 4210 int os::open(const char *path, int oflag, int mode) { 4211 char pathbuf[MAX_PATH]; 4212 4213 if (strlen(path) > MAX_PATH - 1) { 4214 errno = ENAMETOOLONG; 4215 return -1; 4216 } 4217 os::native_path(strcpy(pathbuf, path)); 4218 return ::open(pathbuf, oflag | O_BINARY | O_NOINHERIT, mode); 4219 } 4220 4221 FILE* os::open(int fd, const char* mode) { 4222 return ::_fdopen(fd, mode); 4223 } 4224 4225 // Is a (classpath) directory empty? 4226 bool os::dir_is_empty(const char* path) { 4227 WIN32_FIND_DATA fd; 4228 HANDLE f = FindFirstFile(path, &fd); 4229 if (f == INVALID_HANDLE_VALUE) { 4230 return true; 4231 } 4232 FindClose(f); 4233 return false; 4234 } 4235 4236 // create binary file, rewriting existing file if required 4237 int os::create_binary_file(const char* path, bool rewrite_existing) { 4238 int oflags = _O_CREAT | _O_WRONLY | _O_BINARY; | 4044 } 4045 4046 // Mark the polling page as unreadable 4047 void os::make_polling_page_unreadable(void) { 4048 DWORD old_status; 4049 if (!VirtualProtect((char *)_polling_page, os::vm_page_size(), 4050 PAGE_NOACCESS, &old_status)) { 4051 fatal("Could not disable polling page"); 4052 } 4053 } 4054 4055 // Mark the polling page as readable 4056 void os::make_polling_page_readable(void) { 4057 DWORD old_status; 4058 if (!VirtualProtect((char *)_polling_page, os::vm_page_size(), 4059 PAGE_READONLY, &old_status)) { 4060 fatal("Could not enable polling page"); 4061 } 4062 } 4063 4064 // combine the high and low DWORD into a ULONGLONG 4065 static ULONGLONG make_double_word(DWORD high_word, DWORD low_word) { 4066 ULONGLONG value = high_word; 4067 value <<= sizeof(high_word) * 8; 4068 value |= low_word; 4069 return value; 4070 } 4071 4072 // Transfers data from WIN32_FILE_ATTRIBUTE_DATA structure to struct stat 4073 static void file_attribute_data_to_stat(struct stat* sbuf, WIN32_FILE_ATTRIBUTE_DATA file_data) { 4074 ::memset((void*)sbuf, 0, sizeof(struct stat)); 4075 sbuf->st_size = (_off_t)make_double_word(file_data.nFileSizeHigh, file_data.nFileSizeLow); 4076 sbuf->st_mtime = make_double_word(file_data.ftLastWriteTime.dwHighDateTime, 4077 file_data.ftLastWriteTime.dwLowDateTime); 4078 sbuf->st_ctime = make_double_word(file_data.ftCreationTime.dwHighDateTime, 4079 file_data.ftCreationTime.dwLowDateTime); 4080 sbuf->st_atime = make_double_word(file_data.ftLastAccessTime.dwHighDateTime, 4081 file_data.ftLastAccessTime.dwLowDateTime); 4082 if ((file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { 4083 sbuf->st_mode |= S_IFDIR; 4084 } else { 4085 sbuf->st_mode |= S_IFREG; 4086 } 4087 } 4088 4089 // The following function is adapted from java.base/windows/native/libjava/canonicalize_md.c 4090 // Creates an UNC path from a single byte path. Return buffer is 4091 // allocated in C heap and needs to be freed by the caller. 4092 // Returns NULL on error. 4093 static wchar_t* create_unc_path(const char* path, errno_t &err) { 4094 wchar_t* wpath = NULL; 4095 size_t converted_chars = 0; 4096 size_t path_len = strlen(path) + 1; // includes the terminating NULL 4097 if (path[0] == '\\' && path[1] == '\\') { 4098 if (path[2] == '?' && path[3] == '\\'){ 4099 // if it already has a \\?\ don't do the prefix 4100 wpath = (wchar_t*)os::malloc(path_len * sizeof(wchar_t), mtInternal); 4101 if (wpath != NULL) { 4102 err = ::mbstowcs_s(&converted_chars, wpath, path_len, path, path_len); 4103 } else { 4104 err = ENOMEM; 4105 } 4106 } else { 4107 // only UNC pathname includes double slashes here 4108 wpath = (wchar_t*)os::malloc((path_len + 7) * sizeof(wchar_t), mtInternal); 4109 if (wpath != NULL) { 4110 ::wcscpy(wpath, L"\\\\?\\UNC\0"); 4111 err = ::mbstowcs_s(&converted_chars, &wpath[7], path_len, path, path_len); 4112 } else { 4113 err = ENOMEM; 4114 } 4115 } 4116 } else { 4117 wpath = (wchar_t*)os::malloc((path_len + 4) * sizeof(wchar_t), mtInternal); 4118 if (wpath != NULL) { 4119 ::wcscpy(wpath, L"\\\\?\\\0"); 4120 err = ::mbstowcs_s(&converted_chars, &wpath[4], path_len, path, path_len); 4121 } else { 4122 err = ENOMEM; 4123 } 4124 } 4125 return wpath; 4126 } 4127 4128 static void destroy_unc_path(wchar_t* wpath) { 4129 os::free(wpath); 4130 } 4131 4132 int os::stat(const char *path, struct stat *sbuf) { 4133 char* pathbuf = (char*)os::strdup(path, mtInternal); 4134 if (pathbuf == NULL) { 4135 errno = ENOMEM; 4136 return -1; 4137 } 4138 os::native_path(pathbuf); 4139 int ret; 4140 WIN32_FILE_ATTRIBUTE_DATA file_data; 4141 // Not using stat() to avoid the problem described in JDK-6539723 4142 if (strlen(path) < MAX_PATH) { 4143 BOOL bret = ::GetFileAttributesExA(pathbuf, GetFileExInfoStandard, &file_data); 4144 if (!bret) { 4145 errno = ::GetLastError(); 4146 ret = -1; 4147 } 4148 else { 4149 file_attribute_data_to_stat(sbuf, file_data); 4150 ret = 0; 4151 } 4152 } else { 4153 errno_t err = ERROR_SUCCESS; 4154 wchar_t* wpath = create_unc_path(pathbuf, err); 4155 if (err != ERROR_SUCCESS) { 4156 if (wpath != NULL) { 4157 destroy_unc_path(wpath); 4158 } 4159 os::free(pathbuf); 4160 errno = err; 4161 return -1; 4162 } 4163 BOOL bret = ::GetFileAttributesExW(wpath, GetFileExInfoStandard, &file_data); 4164 if (!bret) { 4165 errno = ::GetLastError(); 4166 ret = -1; 4167 } else { 4168 file_attribute_data_to_stat(sbuf, file_data); 4169 ret = 0; 4170 } 4171 destroy_unc_path(wpath); 4172 } 4173 os::free(pathbuf); 4174 return ret; 4175 } 4176 4177 4178 #define FT2INT64(ft) \ 4179 ((jlong)((jlong)(ft).dwHighDateTime << 32 | (julong)(ft).dwLowDateTime)) 4180 4181 4182 // current_thread_cpu_time(bool) and thread_cpu_time(Thread*, bool) 4183 // are used by JVM M&M and JVMTI to get user+sys or user CPU time 4184 // of a thread. 4185 // 4186 // current_thread_cpu_time() and thread_cpu_time(Thread*) returns 4187 // the fast estimate available on the platform. 4188 4189 // current_thread_cpu_time() is not optimized for Windows yet 4190 jlong os::current_thread_cpu_time() { 4191 // return user + sys since the cost is the same 4192 return os::thread_cpu_time(Thread::current(), true /* user+sys */); 4193 } 4266 // just return the value of the global, avoiding the slow query. 4267 // 4268 // c) Sample a better answer using exponential decay to smooth the 4269 // value. This is basically the algorithm used by UNIX kernels. 4270 // 4271 // Note that sampling thread starvation could affect both (b) and (c). 4272 int os::loadavg(double loadavg[], int nelem) { 4273 return -1; 4274 } 4275 4276 4277 // DontYieldALot=false by default: dutifully perform all yields as requested by JVM_Yield() 4278 bool os::dont_yield() { 4279 return DontYieldALot; 4280 } 4281 4282 // This method is a slightly reworked copy of JDK's sysOpen 4283 // from src/windows/hpi/src/sys_api_md.c 4284 4285 int os::open(const char *path, int oflag, int mode) { 4286 char* pathbuf = (char*)os::strdup(path, mtInternal); 4287 if (pathbuf == NULL) { 4288 errno = ENOMEM; 4289 return -1; 4290 } 4291 os::native_path(pathbuf); 4292 int ret; 4293 if (strlen(path) < MAX_PATH) { 4294 ret = ::open(pathbuf, oflag | O_BINARY | O_NOINHERIT, mode); 4295 } else { 4296 errno_t err = ERROR_SUCCESS; 4297 wchar_t* wpath = create_unc_path(pathbuf, err); 4298 if (err != ERROR_SUCCESS) { 4299 if (wpath != NULL) { 4300 destroy_unc_path(wpath); 4301 } 4302 os::free(pathbuf); 4303 errno = err; 4304 return -1; 4305 } 4306 ret = ::_wopen(wpath, oflag | O_BINARY | O_NOINHERIT, mode); 4307 if (ret == -1) { 4308 errno = ::GetLastError(); 4309 } 4310 destroy_unc_path(wpath); 4311 } 4312 os::free(pathbuf); 4313 return ret; 4314 } 4315 4316 FILE* os::open(int fd, const char* mode) { 4317 return ::_fdopen(fd, mode); 4318 } 4319 4320 // Is a (classpath) directory empty? 4321 bool os::dir_is_empty(const char* path) { 4322 WIN32_FIND_DATA fd; 4323 HANDLE f = FindFirstFile(path, &fd); 4324 if (f == INVALID_HANDLE_VALUE) { 4325 return true; 4326 } 4327 FindClose(f); 4328 return false; 4329 } 4330 4331 // create binary file, rewriting existing file if required 4332 int os::create_binary_file(const char* path, bool rewrite_existing) { 4333 int oflags = _O_CREAT | _O_WRONLY | _O_BINARY; |