Mercurial > hg > truffle
diff src/os/windows/vm/os_windows.cpp @ 1980:828eafbd85cc
6348631: remove the use of the HPI library from Hotspot
Summary: move functions from hpi library to hotspot, communicate with licensees and open source community, check jdk for dependency, file CCC request
Reviewed-by: coleenp, acorn, dsamersoff
author | ikrylov |
---|---|
date | Wed, 01 Dec 2010 18:26:32 -0500 |
parents | f95d63e2154a |
children | cb2d0a362639 |
line wrap: on
line diff
--- a/src/os/windows/vm/os_windows.cpp Tue Nov 23 13:22:55 2010 -0800 +++ b/src/os/windows/vm/os_windows.cpp Wed Dec 01 18:26:32 2010 -0500 @@ -47,7 +47,6 @@ #include "runtime/arguments.hpp" #include "runtime/extendedPC.hpp" #include "runtime/globals.hpp" -#include "runtime/hpi.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" @@ -1044,8 +1043,6 @@ return 0; } -const char* os::dll_file_extension() { return ".dll"; } - const char* os::get_temp_directory() { const char *prop = Arguments::get_property("java.io.tmpdir"); if (prop != 0) return prop; @@ -1067,7 +1064,6 @@ void os::dll_build_name(char *buffer, size_t buflen, const char* pname, const char* fname) { - // Copied from libhpi const size_t pnamelen = pname ? strlen(pname) : 0; const char c = (pnamelen > 0) ? pname[pnamelen-1] : 0; @@ -1378,10 +1374,6 @@ return false; } -void* os::dll_lookup(void* handle, const char* name) { - return GetProcAddress((HMODULE)handle, name); -} - // save the start and end address of jvm.dll into param[0] and param[1] static int _locate_jvm_dll(int pid, char* mod_fname, address base_addr, unsigned size, void * param) { @@ -1734,6 +1726,44 @@ #endif } +// This method is a copy of JDK's sysGetLastErrorString +// from src/windows/hpi/src/system_md.c + +size_t os::lasterror(char *buf, size_t len) { + long errval; + + if ((errval = GetLastError()) != 0) { + /* DOS error */ + int n = (int)FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + errval, + 0, + buf, + (DWORD)len, + NULL); + if (n > 3) { + /* Drop final '.', CR, LF */ + if (buf[n - 1] == '\n') n--; + if (buf[n - 1] == '\r') n--; + if (buf[n - 1] == '.') n--; + buf[n] = '\0'; + } + return n; + } + + if (errno != 0) { + /* C runtime error that has no corresponding DOS error code */ + const char *s = strerror(errno); + size_t n = strlen(s); + if (n >= len) n = len - 1; + strncpy(buf, s, n); + buf[n] = '\0'; + return n; + } + return 0; +} + // sun.misc.Signal // NOTE that this is a workaround for an apparent kernel bug where if // a signal handler for SIGBREAK is installed then that signal handler @@ -2941,10 +2971,6 @@ assert(ret != SYS_THREAD_ERROR, "StartThread failed"); // should propagate back } -size_t os::read(int fd, void *buf, unsigned int nBytes) { - return ::read(fd, buf, nBytes); -} - class HighResolutionInterval { // The default timer resolution seems to be 10 milliseconds. // (Where is this written down?) @@ -3423,10 +3449,6 @@ #endif } - // Initialize HPI. - jint hpi_result = hpi::initialize(); - if (hpi_result != JNI_OK) { return hpi_result; } - // If stack_commit_size is 0, windows will reserve the default size, // but only commit a small portion of it. size_t stack_commit_size = round_to(ThreadStackSize*K, os::vm_page_size()); @@ -3531,7 +3553,7 @@ errno = ENAMETOOLONG; return -1; } - hpi::native_path(strcpy(pathbuf, path)); + os::native_path(strcpy(pathbuf, path)); int ret = ::stat(pathbuf, sbuf); if (sbuf != NULL && UseUTCFileTimestamp) { // Fix for 6539723. st_mtime returned from stat() is dependent on @@ -3675,6 +3697,20 @@ return DontYieldALot; } +// This method is a slightly reworked copy of JDK's sysOpen +// from src/windows/hpi/src/sys_api_md.c + +int os::open(const char *path, int oflag, int mode) { + char pathbuf[MAX_PATH]; + + if (strlen(path) > MAX_PATH - 1) { + errno = ENAMETOOLONG; + return -1; + } + os::native_path(strcpy(pathbuf, path)); + return ::open(pathbuf, oflag | O_BINARY | O_NOINHERIT, mode); +} + // Is a (classpath) directory empty? bool os::dir_is_empty(const char* path) { WIN32_FIND_DATA fd; @@ -3706,6 +3742,297 @@ } +jlong os::lseek(int fd, jlong offset, int whence) { + return (jlong) ::_lseeki64(fd, offset, whence); +} + +// This method is a slightly reworked copy of JDK's sysNativePath +// from src/windows/hpi/src/path_md.c + +/* Convert a pathname to native format. On win32, this involves forcing all + separators to be '\\' rather than '/' (both are legal inputs, but Win95 + sometimes rejects '/') and removing redundant separators. The input path is + assumed to have been converted into the character encoding used by the local + system. Because this might be a double-byte encoding, care is taken to + treat double-byte lead characters correctly. + + This procedure modifies the given path in place, as the result is never + longer than the original. There is no error return; this operation always + succeeds. */ +char * os::native_path(char *path) { + char *src = path, *dst = path, *end = path; + char *colon = NULL; /* If a drive specifier is found, this will + point to the colon following the drive + letter */ + + /* Assumption: '/', '\\', ':', and drive letters are never lead bytes */ + assert(((!::IsDBCSLeadByte('/')) + && (!::IsDBCSLeadByte('\\')) + && (!::IsDBCSLeadByte(':'))), + "Illegal lead byte"); + + /* Check for leading separators */ +#define isfilesep(c) ((c) == '/' || (c) == '\\') + while (isfilesep(*src)) { + src++; + } + + if (::isalpha(*src) && !::IsDBCSLeadByte(*src) && src[1] == ':') { + /* Remove leading separators if followed by drive specifier. This + hack is necessary to support file URLs containing drive + specifiers (e.g., "file://c:/path"). As a side effect, + "/c:/path" can be used as an alternative to "c:/path". */ + *dst++ = *src++; + colon = dst; + *dst++ = ':'; + src++; + } else { + src = path; + if (isfilesep(src[0]) && isfilesep(src[1])) { + /* UNC pathname: Retain first separator; leave src pointed at + second separator so that further separators will be collapsed + into the second separator. The result will be a pathname + beginning with "\\\\" followed (most likely) by a host name. */ + src = dst = path + 1; + path[0] = '\\'; /* Force first separator to '\\' */ + } + } + + end = dst; + + /* Remove redundant separators from remainder of path, forcing all + separators to be '\\' rather than '/'. Also, single byte space + characters are removed from the end of the path because those + are not legal ending characters on this operating system. + */ + while (*src != '\0') { + if (isfilesep(*src)) { + *dst++ = '\\'; src++; + while (isfilesep(*src)) src++; + if (*src == '\0') { + /* Check for trailing separator */ + end = dst; + if (colon == dst - 2) break; /* "z:\\" */ + if (dst == path + 1) break; /* "\\" */ + if (dst == path + 2 && isfilesep(path[0])) { + /* "\\\\" is not collapsed to "\\" because "\\\\" marks the + beginning of a UNC pathname. Even though it is not, by + itself, a valid UNC pathname, we leave it as is in order + to be consistent with the path canonicalizer as well + as the win32 APIs, which treat this case as an invalid + UNC pathname rather than as an alias for the root + directory of the current drive. */ + break; + } + end = --dst; /* Path does not denote a root directory, so + remove trailing separator */ + break; + } + end = dst; + } else { + if (::IsDBCSLeadByte(*src)) { /* Copy a double-byte character */ + *dst++ = *src++; + if (*src) *dst++ = *src++; + end = dst; + } else { /* Copy a single-byte character */ + char c = *src++; + *dst++ = c; + /* Space is not a legal ending character */ + if (c != ' ') end = dst; + } + } + } + + *end = '\0'; + + /* For "z:", add "." to work around a bug in the C runtime library */ + if (colon == dst - 1) { + path[2] = '.'; + path[3] = '\0'; + } + + #ifdef DEBUG + jio_fprintf(stderr, "sysNativePath: %s\n", path); + #endif DEBUG + return path; +} + +// This code is a copy of JDK's sysSetLength +// from src/windows/hpi/src/sys_api_md.c + +int os::ftruncate(int fd, jlong length) { + HANDLE h = (HANDLE)::_get_osfhandle(fd); + long high = (long)(length >> 32); + DWORD ret; + + if (h == (HANDLE)(-1)) { + return -1; + } + + ret = ::SetFilePointer(h, (long)(length), &high, FILE_BEGIN); + if ((ret == 0xFFFFFFFF) && (::GetLastError() != NO_ERROR)) { + return -1; + } + + if (::SetEndOfFile(h) == FALSE) { + return -1; + } + + return 0; +} + + +// This code is a copy of JDK's sysSync +// from src/windows/hpi/src/sys_api_md.c +// except for the legacy workaround for a bug in Win 98 + +int os::fsync(int fd) { + HANDLE handle = (HANDLE)::_get_osfhandle(fd); + + if ( (!::FlushFileBuffers(handle)) && + (GetLastError() != ERROR_ACCESS_DENIED) ) { + /* from winerror.h */ + return -1; + } + return 0; +} + +static int nonSeekAvailable(int, long *); +static int stdinAvailable(int, long *); + +#define S_ISCHR(mode) (((mode) & _S_IFCHR) == _S_IFCHR) +#define S_ISFIFO(mode) (((mode) & _S_IFIFO) == _S_IFIFO) + +// This code is a copy of JDK's sysAvailable +// from src/windows/hpi/src/sys_api_md.c + +int os::available(int fd, jlong *bytes) { + jlong cur, end; + struct _stati64 stbuf64; + + if (::_fstati64(fd, &stbuf64) >= 0) { + int mode = stbuf64.st_mode; + if (S_ISCHR(mode) || S_ISFIFO(mode)) { + int ret; + long lpbytes; + if (fd == 0) { + ret = stdinAvailable(fd, &lpbytes); + } else { + ret = nonSeekAvailable(fd, &lpbytes); + } + (*bytes) = (jlong)(lpbytes); + return ret; + } + if ((cur = ::_lseeki64(fd, 0L, SEEK_CUR)) == -1) { + return FALSE; + } else if ((end = ::_lseeki64(fd, 0L, SEEK_END)) == -1) { + return FALSE; + } else if (::_lseeki64(fd, cur, SEEK_SET) == -1) { + return FALSE; + } + *bytes = end - cur; + return TRUE; + } else { + return FALSE; + } +} + +// This code is a copy of JDK's nonSeekAvailable +// from src/windows/hpi/src/sys_api_md.c + +static int nonSeekAvailable(int fd, long *pbytes) { + /* This is used for available on non-seekable devices + * (like both named and anonymous pipes, such as pipes + * connected to an exec'd process). + * Standard Input is a special case. + * + */ + HANDLE han; + + if ((han = (HANDLE) ::_get_osfhandle(fd)) == (HANDLE)(-1)) { + return FALSE; + } + + if (! ::PeekNamedPipe(han, NULL, 0, NULL, (LPDWORD)pbytes, NULL)) { + /* PeekNamedPipe fails when at EOF. In that case we + * simply make *pbytes = 0 which is consistent with the + * behavior we get on Solaris when an fd is at EOF. + * The only alternative is to raise an Exception, + * which isn't really warranted. + */ + if (::GetLastError() != ERROR_BROKEN_PIPE) { + return FALSE; + } + *pbytes = 0; + } + return TRUE; +} + +#define MAX_INPUT_EVENTS 2000 + +// This code is a copy of JDK's stdinAvailable +// from src/windows/hpi/src/sys_api_md.c + +static int stdinAvailable(int fd, long *pbytes) { + HANDLE han; + DWORD numEventsRead = 0; /* Number of events read from buffer */ + DWORD numEvents = 0; /* Number of events in buffer */ + DWORD i = 0; /* Loop index */ + DWORD curLength = 0; /* Position marker */ + DWORD actualLength = 0; /* Number of bytes readable */ + BOOL error = FALSE; /* Error holder */ + INPUT_RECORD *lpBuffer; /* Pointer to records of input events */ + + if ((han = ::GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) { + return FALSE; + } + + /* Construct an array of input records in the console buffer */ + error = ::GetNumberOfConsoleInputEvents(han, &numEvents); + if (error == 0) { + return nonSeekAvailable(fd, pbytes); + } + + /* lpBuffer must fit into 64K or else PeekConsoleInput fails */ + if (numEvents > MAX_INPUT_EVENTS) { + numEvents = MAX_INPUT_EVENTS; + } + + lpBuffer = (INPUT_RECORD *)os::malloc(numEvents * sizeof(INPUT_RECORD)); + if (lpBuffer == NULL) { + return FALSE; + } + + error = ::PeekConsoleInput(han, lpBuffer, numEvents, &numEventsRead); + if (error == 0) { + os::free(lpBuffer); + return FALSE; + } + + /* Examine input records for the number of bytes available */ + for(i=0; i<numEvents; i++) { + if (lpBuffer[i].EventType == KEY_EVENT) { + + KEY_EVENT_RECORD *keyRecord = (KEY_EVENT_RECORD *) + &(lpBuffer[i].Event); + if (keyRecord->bKeyDown == TRUE) { + CHAR *keyPressed = (CHAR *) &(keyRecord->uChar); + curLength++; + if (*keyPressed == '\r') { + actualLength = curLength; + } + } + } + } + + if(lpBuffer != NULL) { + os::free(lpBuffer); + } + + *pbytes = (long) actualLength; + return TRUE; +} + // Map a block of memory. char* os::map_memory(int fd, const char* file_name, size_t file_offset, char *addr, size_t bytes, bool read_only, @@ -3871,7 +4198,7 @@ int fd = ::open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd != -1) { struct stat buf; - close(fd); + ::close(fd); while (::stat(filename, &buf) == 0) { Sleep(100); } @@ -4232,3 +4559,164 @@ // We don't build a headless jre for Windows bool os::is_headless_jre() { return false; } +// OS_SocketInterface +// Not used on Windows + +// OS_SocketInterface +typedef struct hostent * (PASCAL FAR *ws2_ifn_ptr_t)(...); +ws2_ifn_ptr_t *get_host_by_name_fn = NULL; + +typedef CRITICAL_SECTION mutex_t; +#define mutexInit(m) InitializeCriticalSection(m) +#define mutexDestroy(m) DeleteCriticalSection(m) +#define mutexLock(m) EnterCriticalSection(m) +#define mutexUnlock(m) LeaveCriticalSection(m) + +static bool sockfnptrs_initialized = FALSE; +static mutex_t sockFnTableMutex; + +/* is Winsock2 loaded? better to be explicit than to rely on sockfnptrs */ +static bool winsock2Available = FALSE; + + +static void initSockFnTable() { + int (PASCAL FAR* WSAStartupPtr)(WORD, LPWSADATA); + WSADATA wsadata; + + ::mutexInit(&sockFnTableMutex); + ::mutexLock(&sockFnTableMutex); + + if (sockfnptrs_initialized == FALSE) { + HMODULE hWinsock; + + /* try to load Winsock2, and if that fails, load Winsock */ + hWinsock = ::LoadLibrary("ws2_32.dll"); + + if (hWinsock == NULL) { + jio_fprintf(stderr, "Could not load Winsock 2 (error: %d)\n", + ::GetLastError()); + return; + } + + /* If we loaded a DLL, then we might as well initialize it. */ + WSAStartupPtr = (int (PASCAL FAR *)(WORD, LPWSADATA)) + ::GetProcAddress(hWinsock, "WSAStartup"); + + if (WSAStartupPtr(MAKEWORD(1,1), &wsadata) != 0) { + jio_fprintf(stderr, "Could not initialize Winsock\n"); + } + + get_host_by_name_fn + = (ws2_ifn_ptr_t*) GetProcAddress(hWinsock, "gethostbyname"); + } + + assert(get_host_by_name_fn != NULL, + "gethostbyname function not found"); + sockfnptrs_initialized = TRUE; + ::mutexUnlock(&sockFnTableMutex); +} + +struct hostent* os::get_host_by_name(char* name) { + if (!sockfnptrs_initialized) { + initSockFnTable(); + } + + assert(sockfnptrs_initialized == TRUE && get_host_by_name_fn != NULL, + "sockfnptrs is not initialized or pointer to gethostbyname function is NULL"); + return (*get_host_by_name_fn)(name); +} + + +int os::socket_close(int fd) { + ShouldNotReachHere(); + return 0; +} + +int os::socket_available(int fd, jint *pbytes) { + ShouldNotReachHere(); + return 0; +} + +int os::socket(int domain, int type, int protocol) { + ShouldNotReachHere(); + return 0; +} + +int os::listen(int fd, int count) { + ShouldNotReachHere(); + return 0; +} + +int os::connect(int fd, struct sockaddr *him, int len) { + ShouldNotReachHere(); + return 0; +} + +int os::accept(int fd, struct sockaddr *him, int *len) { + ShouldNotReachHere(); + return 0; +} + +int os::sendto(int fd, char *buf, int len, int flags, + struct sockaddr *to, int tolen) { + ShouldNotReachHere(); + return 0; +} + +int os::recvfrom(int fd, char *buf, int nBytes, int flags, + sockaddr *from, int *fromlen) { + ShouldNotReachHere(); + return 0; +} + +int os::recv(int fd, char *buf, int nBytes, int flags) { + ShouldNotReachHere(); + return 0; +} + +int os::send(int fd, char *buf, int nBytes, int flags) { + ShouldNotReachHere(); + return 0; +} + +int os::raw_send(int fd, char *buf, int nBytes, int flags) { + ShouldNotReachHere(); + return 0; +} + +int os::timeout(int fd, long timeout) { + ShouldNotReachHere(); + return 0; +} + +int os::get_host_name(char* name, int namelen) { + ShouldNotReachHere(); + return 0; +} + +int os::socket_shutdown(int fd, int howto) { + ShouldNotReachHere(); + return 0; +} + +int os::bind(int fd, struct sockaddr *him, int len) { + ShouldNotReachHere(); + return 0; +} + +int os::get_sock_name(int fd, struct sockaddr *him, int *len) { + ShouldNotReachHere(); + return 0; +} + +int os::get_sock_opt(int fd, int level, int optname, + char *optval, int* optlen) { + ShouldNotReachHere(); + return 0; +} + +int os::set_sock_opt(int fd, int level, int optname, + const char *optval, int optlen) { + ShouldNotReachHere(); + return 0; +}