1 /* 2 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* @test TestLargePagesFlags 25 * @summary Tests how large pages are choosen depending on the given large pages flag combinations. 26 * @library /testlibrary 27 * @run main TestLargePagesFlags 28 */ 29 30 import com.oracle.java.testlibrary.OutputAnalyzer; 31 import com.oracle.java.testlibrary.Platform; 32 import com.oracle.java.testlibrary.ProcessTools; 33 import java.util.ArrayList; 34 35 public class TestLargePagesFlags { 36 37 public static void main(String [] args) throws Exception { 38 if (!Platform.isLinux()) { 39 System.out.println("Skipping. TestLargePagesFlags has only been implemented for Linux."); 40 return; 41 } 42 43 testUseTransparentHugePages(); 44 testUseHugeTLBFS(); 45 testUseSHM(); 46 testCombinations(); 47 } 48 49 public static void testUseTransparentHugePages() throws Exception { 50 if (!canUse(UseTransparentHugePages(true))) { 51 System.out.println("Skipping testUseTransparentHugePages"); 52 return; 53 } 54 55 // -XX:-UseLargePages overrides all other flags. 56 new FlagTester() 57 .use(UseLargePages(false), 58 UseTransparentHugePages(true)) 59 .expect( 60 UseLargePages(false), 61 UseTransparentHugePages(false), 62 UseHugeTLBFS(false), 63 UseSHM(false)); 64 65 // Explicitly turn on UseTransparentHugePages. 66 new FlagTester() 67 .use(UseTransparentHugePages(true)) 68 .expect( 69 UseLargePages(true), 70 UseTransparentHugePages(true), 71 UseHugeTLBFS(false), 72 UseSHM(false)); 73 74 new FlagTester() 75 .use(UseLargePages(true), 76 UseTransparentHugePages(true)) 77 .expect( 78 UseLargePages(true), 79 UseTransparentHugePages(true), 80 UseHugeTLBFS(false), 81 UseSHM(false)); 82 83 // Setting a specific large pages flag will turn 84 // off heuristics to choose large pages type. 85 new FlagTester() 86 .use(UseLargePages(true), 87 UseTransparentHugePages(false)) 88 .expect( 89 UseLargePages(false), 90 UseTransparentHugePages(false), 91 UseHugeTLBFS(false), 92 UseSHM(false)); 93 94 // Don't turn on UseTransparentHugePages 95 // unless the user explicitly asks for them. 96 new FlagTester() 97 .use(UseLargePages(true)) 98 .expect( 99 UseTransparentHugePages(false)); 100 } 101 102 public static void testUseHugeTLBFS() throws Exception { 103 if (!canUse(UseHugeTLBFS(true))) { 104 System.out.println("Skipping testUseHugeTLBFS"); 105 return; 106 } 107 108 // -XX:-UseLargePages overrides all other flags. 109 new FlagTester() 110 .use(UseLargePages(false), 111 UseHugeTLBFS(true)) 112 .expect( 113 UseLargePages(false), 114 UseTransparentHugePages(false), 115 UseHugeTLBFS(false), 116 UseSHM(false)); 117 118 // Explicitly turn on UseHugeTLBFS. 119 new FlagTester() 120 .use(UseHugeTLBFS(true)) 121 .expect( 122 UseLargePages(true), 123 UseTransparentHugePages(false), 124 UseHugeTLBFS(true), 125 UseSHM(false)); 126 127 new FlagTester() 128 .use(UseLargePages(true), 129 UseHugeTLBFS(true)) 130 .expect( 131 UseLargePages(true), 132 UseTransparentHugePages(false), 133 UseHugeTLBFS(true), 134 UseSHM(false)); 135 136 // Setting a specific large pages flag will turn 137 // off heuristics to choose large pages type. 138 new FlagTester() 139 .use(UseLargePages(true), 140 UseHugeTLBFS(false)) 141 .expect( 142 UseLargePages(false), 143 UseTransparentHugePages(false), 144 UseHugeTLBFS(false), 145 UseSHM(false)); 146 147 // Using UseLargePages will default to UseHugeTLBFS large pages. 148 new FlagTester() 149 .use(UseLargePages(true)) 150 .expect( 151 UseLargePages(true), 152 UseTransparentHugePages(false), 153 UseHugeTLBFS(true), 154 UseSHM(false)); 155 } 156 157 public static void testUseSHM() throws Exception { 158 if (!canUse(UseSHM(true))) { 159 System.out.println("Skipping testUseSHM"); 160 return; 161 } 162 163 // -XX:-UseLargePages overrides all other flags. 164 new FlagTester() 165 .use(UseLargePages(false), 166 UseSHM(true)) 167 .expect( 168 UseLargePages(false), 169 UseTransparentHugePages(false), 170 UseHugeTLBFS(false), 171 UseSHM(false)); 172 173 // Explicitly turn on UseSHM. 174 new FlagTester() 175 .use(UseSHM(true)) 176 .expect( 177 UseLargePages(true), 178 UseTransparentHugePages(false), 179 UseHugeTLBFS(false), 180 UseSHM(true)) ; 181 182 new FlagTester() 183 .use(UseLargePages(true), 184 UseSHM(true)) 185 .expect( 186 UseLargePages(true), 187 UseTransparentHugePages(false), 188 UseHugeTLBFS(false), 189 UseSHM(true)) ; 190 191 // Setting a specific large pages flag will turn 192 // off heuristics to choose large pages type. 193 new FlagTester() 194 .use(UseLargePages(true), 195 UseSHM(false)) 196 .expect( 197 UseLargePages(false), 198 UseTransparentHugePages(false), 199 UseHugeTLBFS(false), 200 UseSHM(false)); 201 202 // Setting UseLargePages can allow the system to choose 203 // UseHugeTLBFS instead of UseSHM, but never UseTransparentHugePages. 204 new FlagTester() 205 .use(UseLargePages(true)) 206 .expect( 207 UseLargePages(true), 208 UseTransparentHugePages(false)); 209 } 210 211 public static void testCombinations() throws Exception { 212 if (!canUse(UseSHM(true)) || !canUse(UseHugeTLBFS(true))) { 213 System.out.println("Skipping testUseHugeTLBFSAndUseSHMCombination"); 214 return; 215 } 216 217 // UseHugeTLBFS takes precedence over SHM. 218 219 new FlagTester() 220 .use(UseLargePages(true), 221 UseHugeTLBFS(true), 222 UseSHM(true)) 223 .expect( 224 UseLargePages(true), 225 UseTransparentHugePages(false), 226 UseHugeTLBFS(true), 227 UseSHM(false)); 228 229 new FlagTester() 230 .use(UseLargePages(true), 231 UseHugeTLBFS(false), 232 UseSHM(true)) 233 .expect( 234 UseLargePages(true), 235 UseTransparentHugePages(false), 236 UseHugeTLBFS(false), 237 UseSHM(true)); 238 239 new FlagTester() 240 .use(UseLargePages(true), 241 UseHugeTLBFS(true), 242 UseSHM(false)) 243 .expect( 244 UseLargePages(true), 245 UseTransparentHugePages(false), 246 UseHugeTLBFS(true), 247 UseSHM(false)); 248 249 new FlagTester() 250 .use(UseLargePages(true), 251 UseHugeTLBFS(false), 252 UseSHM(false)) 253 .expect( 254 UseLargePages(false), 255 UseTransparentHugePages(false), 256 UseHugeTLBFS(false), 257 UseSHM(false)); 258 259 260 if (!canUse(UseTransparentHugePages(true))) { 261 return; 262 } 263 264 // UseTransparentHugePages takes precedence. 265 266 new FlagTester() 267 .use(UseLargePages(true), 268 UseTransparentHugePages(true), 269 UseHugeTLBFS(true), 270 UseSHM(true)) 271 .expect( 272 UseLargePages(true), 273 UseTransparentHugePages(true), 274 UseHugeTLBFS(false), 275 UseSHM(false)); 276 277 new FlagTester() 278 .use(UseTransparentHugePages(true), 279 UseHugeTLBFS(true), 280 UseSHM(true)) 281 .expect( 282 UseLargePages(true), 283 UseTransparentHugePages(true), 284 UseHugeTLBFS(false), 285 UseSHM(false)); 286 } 287 288 private static class FlagTester { 289 private Flag [] useFlags; 290 291 public FlagTester use(Flag... useFlags) { 292 this.useFlags = useFlags; 293 return this; 294 } 295 296 public void expect(Flag... expectedFlags) throws Exception { 297 if (useFlags == null) { 298 throw new IllegalStateException("Must run use() before expect()"); 299 } 300 301 OutputAnalyzer output = executeNewJVM(useFlags); 302 303 for (Flag flag : expectedFlags) { 304 System.out.println("Looking for: " + flag.flagString()); 305 String strValue = output.firstMatch(".* " + flag.name() + " .* :?= (\\S+).*", 1); 306 307 if (strValue == null) { 308 throw new RuntimeException("Flag " + flag.name() + " couldn't be found"); 309 } 310 311 if (!flag.value().equals(strValue)) { 312 throw new RuntimeException("Wrong value for: " + flag.name() 313 + " expected: " + flag.value() 314 + " got: " + strValue); 315 } 316 } 317 318 output.shouldHaveExitValue(0); 319 } 320 } 321 322 private static OutputAnalyzer executeNewJVM(Flag... flags) throws Exception { 323 ArrayList<String> args = new ArrayList<>(); 324 for (Flag flag : flags) { 325 args.add(flag.flagString()); 326 } 327 args.add("-XX:+PrintFlagsFinal"); 328 args.add("-version"); 329 330 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args.toArray(new String[args.size()])); 331 OutputAnalyzer output = new OutputAnalyzer(pb.start()); 332 333 return output; 334 } 335 336 private static boolean canUse(Flag flag) { 337 try { 338 new FlagTester().use(flag).expect(flag); 339 } catch (Exception e) { 340 return false; 341 } 342 343 return true; 344 } 345 346 private static Flag UseLargePages(boolean value) { 347 return new BooleanFlag("UseLargePages", value); 348 } 349 350 private static Flag UseTransparentHugePages(boolean value) { 351 return new BooleanFlag("UseTransparentHugePages", value); 352 } 353 354 private static Flag UseHugeTLBFS(boolean value) { 355 return new BooleanFlag("UseHugeTLBFS", value); 356 } 357 358 private static Flag UseSHM(boolean value) { 359 return new BooleanFlag("UseSHM", value); 360 } 361 362 private static class BooleanFlag implements Flag { 363 private String name; 364 private boolean value; 365 366 BooleanFlag(String name, boolean value) { 367 this.name = name; 368 this.value = value; 369 } 370 371 public String flagString() { 372 return "-XX:" + (value ? "+" : "-") + name; 373 } 374 375 public String name() { 376 return name; 377 } 378 379 public String value() { 380 return Boolean.toString(value); 381 } 382 } 383 384 private static interface Flag { 385 public String flagString(); 386 public String name(); 387 public String value(); 388 } 389 }