src/os/windows/vm/os_windows.cpp

changeset 824
ee21eaa8ffe1
parent 791
1ee8caae33af
child 897
85f1b9537f70
child 900
dc16daa0329d
     1.1 --- a/src/os/windows/vm/os_windows.cpp	Wed Oct 01 15:05:06 2008 -0400
     1.2 +++ b/src/os/windows/vm/os_windows.cpp	Thu Oct 02 12:01:08 2008 -0700
     1.3 @@ -2593,9 +2593,104 @@
     1.4  }
     1.5  
     1.6  char* os::reserve_memory_special(size_t bytes) {
     1.7 -  DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES;
     1.8 -  char * res = (char *)VirtualAlloc(NULL, bytes, flag, PAGE_EXECUTE_READWRITE);
     1.9 -  return res;
    1.10 +
    1.11 +  if (UseLargePagesIndividualAllocation) {
    1.12 +    if (TracePageSizes && Verbose) {
    1.13 +       tty->print_cr("Reserving large pages individually.");
    1.14 +    }
    1.15 +    char * p_buf;
    1.16 +    // first reserve enough address space in advance since we want to be
    1.17 +    // able to break a single contiguous virtual address range into multiple
    1.18 +    // large page commits but WS2003 does not allow reserving large page space
    1.19 +    // so we just use 4K pages for reserve, this gives us a legal contiguous
    1.20 +    // address space. then we will deallocate that reservation, and re alloc
    1.21 +    // using large pages
    1.22 +    const size_t size_of_reserve = bytes + _large_page_size;
    1.23 +    if (bytes > size_of_reserve) {
    1.24 +      // Overflowed.
    1.25 +      warning("Individually allocated large pages failed, "
    1.26 +        "use -XX:-UseLargePagesIndividualAllocation to turn off");
    1.27 +      return NULL;
    1.28 +    }
    1.29 +    p_buf = (char *) VirtualAlloc(NULL,
    1.30 +                                 size_of_reserve,  // size of Reserve
    1.31 +                                 MEM_RESERVE,
    1.32 +                                 PAGE_EXECUTE_READWRITE);
    1.33 +    // If reservation failed, return NULL
    1.34 +    if (p_buf == NULL) return NULL;
    1.35 +
    1.36 +    release_memory(p_buf, bytes + _large_page_size);
    1.37 +    // round up to page boundary.  If the size_of_reserve did not
    1.38 +    // overflow and the reservation did not fail, this align up
    1.39 +    // should not overflow.
    1.40 +    p_buf = (char *) align_size_up((size_t)p_buf, _large_page_size);
    1.41 +
    1.42 +    // now go through and allocate one page at a time until all bytes are
    1.43 +    // allocated
    1.44 +    size_t  bytes_remaining = align_size_up(bytes, _large_page_size);
    1.45 +    // An overflow of align_size_up() would have been caught above
    1.46 +    // in the calculation of size_of_reserve.
    1.47 +    char * next_alloc_addr = p_buf;
    1.48 +
    1.49 +#ifdef ASSERT
    1.50 +    // Variable for the failure injection
    1.51 +    long ran_num = os::random();
    1.52 +    size_t fail_after = ran_num % bytes;
    1.53 +#endif
    1.54 +
    1.55 +    while (bytes_remaining) {
    1.56 +      size_t bytes_to_rq = MIN2(bytes_remaining, _large_page_size);
    1.57 +      // Note allocate and commit
    1.58 +      char * p_new;
    1.59 +
    1.60 +#ifdef ASSERT
    1.61 +      bool inject_error = LargePagesIndividualAllocationInjectError &&
    1.62 +          (bytes_remaining <= fail_after);
    1.63 +#else
    1.64 +      const bool inject_error = false;
    1.65 +#endif
    1.66 +
    1.67 +      if (inject_error) {
    1.68 +        p_new = NULL;
    1.69 +      } else {
    1.70 +        p_new = (char *) VirtualAlloc(next_alloc_addr,
    1.71 +                                    bytes_to_rq,
    1.72 +                                    MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES,
    1.73 +                                    PAGE_EXECUTE_READWRITE);
    1.74 +      }
    1.75 +
    1.76 +      if (p_new == NULL) {
    1.77 +        // Free any allocated pages
    1.78 +        if (next_alloc_addr > p_buf) {
    1.79 +          // Some memory was committed so release it.
    1.80 +          size_t bytes_to_release = bytes - bytes_remaining;
    1.81 +          release_memory(p_buf, bytes_to_release);
    1.82 +        }
    1.83 +#ifdef ASSERT
    1.84 +        if (UseLargePagesIndividualAllocation &&
    1.85 +            LargePagesIndividualAllocationInjectError) {
    1.86 +          if (TracePageSizes && Verbose) {
    1.87 +             tty->print_cr("Reserving large pages individually failed.");
    1.88 +          }
    1.89 +        }
    1.90 +#endif
    1.91 +        return NULL;
    1.92 +      }
    1.93 +      bytes_remaining -= bytes_to_rq;
    1.94 +      next_alloc_addr += bytes_to_rq;
    1.95 +    }
    1.96 +
    1.97 +    return p_buf;
    1.98 +
    1.99 +  } else {
   1.100 +    // normal policy just allocate it all at once
   1.101 +    DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES;
   1.102 +    char * res = (char *)VirtualAlloc(NULL,
   1.103 +                                      bytes,
   1.104 +                                      flag,
   1.105 +                                      PAGE_EXECUTE_READWRITE);
   1.106 +    return res;
   1.107 +  }
   1.108  }
   1.109  
   1.110  bool os::release_memory_special(char* base, size_t bytes) {
   1.111 @@ -2983,6 +3078,7 @@
   1.112  volatile intx os::win32::_os_thread_count    = 0;
   1.113  
   1.114  bool   os::win32::_is_nt              = false;
   1.115 +bool   os::win32::_is_windows_2003    = false;
   1.116  
   1.117  
   1.118  void os::win32::initialize_system_info() {
   1.119 @@ -3005,7 +3101,15 @@
   1.120    GetVersionEx(&oi);
   1.121    switch(oi.dwPlatformId) {
   1.122      case VER_PLATFORM_WIN32_WINDOWS: _is_nt = false; break;
   1.123 -    case VER_PLATFORM_WIN32_NT:      _is_nt = true;  break;
   1.124 +    case VER_PLATFORM_WIN32_NT:
   1.125 +      _is_nt = true;
   1.126 +      {
   1.127 +        int os_vers = oi.dwMajorVersion * 1000 + oi.dwMinorVersion;
   1.128 +        if (os_vers == 5002) {
   1.129 +          _is_windows_2003 = true;
   1.130 +        }
   1.131 +      }
   1.132 +      break;
   1.133      default: fatal("Unknown platform");
   1.134    }
   1.135  
   1.136 @@ -3103,9 +3207,13 @@
   1.137      NoYieldsInMicrolock = true;
   1.138    }
   1.139  #endif
   1.140 +  // This may be overridden later when argument processing is done.
   1.141 +  FLAG_SET_ERGO(bool, UseLargePagesIndividualAllocation,
   1.142 +    os::win32::is_windows_2003());
   1.143 +
   1.144    // Initialize main_process and main_thread
   1.145    main_process = GetCurrentProcess();  // Remember main_process is a pseudo handle
   1.146 -  if (!DuplicateHandle(main_process, GetCurrentThread(), main_process,
   1.147 + if (!DuplicateHandle(main_process, GetCurrentThread(), main_process,
   1.148                         &main_thread, THREAD_ALL_ACCESS, false, 0)) {
   1.149      fatal("DuplicateHandle failed\n");
   1.150    }

mercurial