/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.compilers.opt.runtimesupport; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.jikesrvm.junit.runners.RequiresBuiltJikesRVM; import org.jikesrvm.junit.runners.VMRequirements; import org.jikesrvm.scheduler.RVMThread; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; @RunWith(VMRequirements.class) @Category(RequiresBuiltJikesRVM.class) public class CodePatchSyncRequestVisitorTest { private CodePatchSyncRequestVisitor codePatchSyncReqVisitor; @Before public void createVisitor() { codePatchSyncReqVisitor = new CodePatchSyncRequestVisitor(); } @Test public void normalThreadsTakePartInHandshake() throws Exception { RVMThread normalThread = RVMThread.getCurrentThread(); assertTrue(codePatchSyncReqVisitor.includeThread(normalThread)); } @Test public void checkAndSignalSetsCodePatchingFlag() throws Exception { Thread t = new ThreadWithTimeout(); t.start(); RVMThread rvmThread = JikesRVMSupport.getThread(t); assertFalse(rvmThread.codePatchSyncRequested); codePatchSyncReqVisitor.checkAndSignal(rvmThread); assertTrue(rvmThread.codePatchSyncRequested); t.interrupt(); } @Ignore("currently fails spuriously, see bug RVM-1096") @SuppressWarnings("deprecation") @Test(timeout = 100) public void codePatchingWorksWhenAThreadIsSuspended() throws Exception { Thread t = new SuspendedThread(); t.start(); RVMThread.softHandshake(codePatchSyncReqVisitor); t.interrupt(); t.resume(); } @Ignore("currently fails spuriously, see bug RVM-1096") @Test(timeout = 100) public void codePatchingWorksWhenAThreadIsWaiting() throws Exception { triggerCodePatching(new WaitingThread()); } @Ignore("currently fails spuriously, see bug RVM-1096") @Test(timeout = 100) public void codePatchingWorksWhenAThreadIsSleeping() throws Exception { triggerCodePatching(new SleepingThread()); } @Ignore("currently fails spuriously, see bug RVM-1096") @Test(timeout = 100) public void codePatchingWorksWhenAThreadIsParked() throws Exception { triggerCodePatching(new ParkedThread()); } private void triggerCodePatching(IdlingThread idlingThread) { idlingThread.start(); RVMThread.softHandshake(codePatchSyncReqVisitor); idlingThread.interrupt(); } private static class ThreadWithTimeout extends Thread { @Override public void run() { synchronized (this) { try { wait(1000); } catch (InterruptedException e) { return; } } } } private static class SuspendedThread extends Thread { @Override @SuppressWarnings("deprecation") public void run() { while (!interrupted()) { suspend(); } } } private abstract static class IdlingThread extends Thread { @Override public void run() { while (!interrupted()) { try { synchronized (this) { idleImpl(); } } catch (InterruptedException e) { return; } } } protected abstract void idleImpl() throws InterruptedException; } private static class WaitingThread extends IdlingThread { private final Object waitOnMe = new Object(); @Override protected void idleImpl() throws InterruptedException { while (true) { synchronized (waitOnMe) { waitOnMe.wait(); } } } } private static class SleepingThread extends IdlingThread { @Override protected void idleImpl() throws InterruptedException { sleep(Long.MAX_VALUE); } } private static class ParkedThread extends IdlingThread { @Override protected void idleImpl() throws InterruptedException { try { RVMThread.getCurrentThread().park(true, Long.MAX_VALUE); } catch (Throwable e) { e.printStackTrace(); } } } }