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