/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.lang.reflect.Field;
import java.util.concurrent.atomic.AtomicBoolean;

import sun.misc.Unsafe;

/**
 * Checker test on the 1.8 unsafe operations. Note, this is by no means an
 * exhaustive unit test for these CAS (compare-and-swap) and fence operations.
 * Instead, this test ensures the methods are recognized as intrinsic and behave
 * as expected.
 */
public class Main {

  private static final Unsafe unsafe = getUnsafe();

  private static Thread[] sThreads = new Thread[10];

  //
  // Fields accessed by setters and adders, and by memory fence tests.
  //

  public int i = 0;
  public long l = 0;
  public Object o = null;

  public int x_value;
  public int y_value;
  public volatile boolean running;

  //
  // Setters.
  //

  /// CHECK-START: int Main.set32(java.lang.Object, long, int) builder (after)
  /// CHECK-DAG: <<Result:i\d+>> InvokeVirtual intrinsic:UnsafeGetAndSetInt
  /// CHECK-DAG:                 Return [<<Result>>]
  private static int set32(Object o, long offset, int newValue) {
    return unsafe.getAndSetInt(o, offset, newValue);
  }

  /// CHECK-START: long Main.set64(java.lang.Object, long, long) builder (after)
  /// CHECK-DAG: <<Result:j\d+>> InvokeVirtual intrinsic:UnsafeGetAndSetLong
  /// CHECK-DAG:                 Return [<<Result>>]
  private static long set64(Object o, long offset, long newValue) {
    return unsafe.getAndSetLong(o, offset, newValue);
  }

  /// CHECK-START: java.lang.Object Main.setObj(java.lang.Object, long, java.lang.Object) builder (after)
  /// CHECK-DAG: <<Result:l\d+>> InvokeVirtual intrinsic:UnsafeGetAndSetObject
  /// CHECK-DAG:                 Return [<<Result>>]
  private static Object setObj(Object o, long offset, Object newValue) {
    return unsafe.getAndSetObject(o, offset, newValue);
  }

  //
  // Adders.
  //

  /// CHECK-START: int Main.add32(java.lang.Object, long, int) builder (after)
  /// CHECK-DAG: <<Result:i\d+>> InvokeVirtual intrinsic:UnsafeGetAndAddInt
  /// CHECK-DAG:                 Return [<<Result>>]
  private static int add32(Object o, long offset, int delta) {
    return unsafe.getAndAddInt(o, offset, delta);
  }

  /// CHECK-START: long Main.add64(java.lang.Object, long, long) builder (after)
  /// CHECK-DAG: <<Result:j\d+>> InvokeVirtual intrinsic:UnsafeGetAndAddLong
  /// CHECK-DAG:                 Return [<<Result>>]
  private static long add64(Object o, long offset, long delta) {
    return unsafe.getAndAddLong(o, offset, delta);
  }

  //
  // Fences (native).
  //

  /// CHECK-START: void Main.load() builder (after)
  /// CHECK-NOT: InvokeVirtual
  //
  /// CHECK-START: void Main.load() builder (after)
  /// CHECK-DAG: MemoryBarrier kind:LoadAny
  private static void load() {
    unsafe.loadFence();
  }

  /// CHECK-START: void Main.store() builder (after)
  /// CHECK-NOT: InvokeVirtual
  //
  /// CHECK-START: void Main.store() builder (after)
  /// CHECK-DAG: MemoryBarrier kind:AnyStore
  private static void store() {
    unsafe.storeFence();
  }

  /// CHECK-START: void Main.full() builder (after)
  /// CHECK-NOT: InvokeVirtual
  //
  /// CHECK-START: void Main.full() builder (after)
  /// CHECK-DAG: MemoryBarrier kind:AnyAny
  private static void full() {
    unsafe.fullFence();
  }

  //
  // Thread fork/join.
  //

  private static void fork(Runnable r) {
    for (int i = 0; i < 10; i++) {
      sThreads[i] = new Thread(r);
    }
    // Start the threads only after the full array has been written with new threads,
    // because one test relies on the contents of this array to be consistent.
    for (int i = 0; i < 10; i++) {
      sThreads[i].start();
    }
  }

  private static void join() {
    try {
      for (int i = 0; i < 10; i++) {
        sThreads[i].join();
      }
    } catch (InterruptedException e) {
      throw new Error("Failed join: " + e);
    }
  }

  //
  // Driver.
  //

  public static void main(String[] args) {
    System.out.println("starting");

    final Main m = new Main();

    // Get the offsets.

    final long intOffset, longOffset, objOffset;
    try {
      Field intField = Main.class.getDeclaredField("i");
      Field longField = Main.class.getDeclaredField("l");
      Field objField = Main.class.getDeclaredField("o");

      intOffset = unsafe.objectFieldOffset(intField);
      longOffset = unsafe.objectFieldOffset(longField);
      objOffset = unsafe.objectFieldOffset(objField);

    } catch (NoSuchFieldException e) {
      throw new Error("No offset: " + e);
    }

    // Some checks on setters and adders within same thread.

    set32(m, intOffset, 3);
    expectEqual32(3, m.i);

    set64(m, longOffset, 7L);
    expectEqual64(7L, m.l);

    setObj(m, objOffset, m);
    expectEqualObj(m, m.o);

    add32(m, intOffset, 11);
    expectEqual32(14, m.i);

    add64(m, longOffset, 13L);
    expectEqual64(20L, m.l);

    // Some checks on setters within different threads.

    fork(new Runnable() {
      public void run() {
        for (int i = 0; i < 10; i++)
          set32(m, intOffset, i);
      }
    });
    join();
    expectEqual32(9, m.i);  // one thread's last value wins

    fork(new Runnable() {
      public void run() {
        for (int i = 0; i < 10; i++)
          set64(m, longOffset, (long) (100 + i));
      }
    });
    join();
    expectEqual64(109L, m.l);  // one thread's last value wins

    fork(new Runnable() {
      public void run() {
        for (int i = 0; i < 10; i++)
          setObj(m, objOffset, sThreads[i]);
      }
    });
    join();
    expectEqualObj(sThreads[9], m.o);  // one thread's last value wins

    // Some checks on adders within different threads.

    fork(new Runnable() {
      public void run() {
        for (int i = 0; i < 10; i++)
          add32(m, intOffset, i + 1);
      }
    });
    join();
    expectEqual32(559, m.i);  // all values accounted for

    fork(new Runnable() {
      public void run() {
        for (int i = 0; i < 10; i++)
          add64(m, longOffset, (long) (i + 1));
      }
    });
    join();
    expectEqual64(659L, m.l);  // all values accounted for

    // Some checks on fences within same thread. Note that memory fences within one
    // thread make little sense, but the assertion ensures nothing bad happens.

    m.i = -1;
    m.l = -2L;
    m.o = null;

    load();
    store();
    full();

    expectEqual32(-1, m.i);
    expectEqual64(-2L, m.l);
    expectEqualObj(null, m.o);

    // Some checks on full fence within different threads. We write the non-volatile m.l after
    // the fork(), which means there is no happens-before relation in the Java memory model
    // with respect to the read in the threads. This relation is enforced by the memory fences
    // and the weak-set() -> get() guard. Note that the guard semantics used here are actually
    // too strong and already enforce total memory visibility, but this test illustrates what
    // should still happen if Java had a true relaxed memory guard.

    final AtomicBoolean guard1 = new AtomicBoolean();
    m.l = 0L;

    fork(new Runnable() {
      public void run() {
        while (!guard1.get());  // busy-waiting
        full();
        expectEqual64(-123456789L, m.l);
      }
    });

    m.l = -123456789L;
    full();
    while (!guard1.weakCompareAndSet(false, true));  // relaxed memory order
    join();

    // Some checks on release/acquire fences within different threads. We write the non-volatile
    // m.l after the fork(), which means there is no happens-before relation in the Java memory
    // model with respect to the read in the threads. This relation is enforced by the memory fences
    // and the weak-set() -> get() guard. Note that the guard semantics used here are actually
    // too strong and already enforce total memory visibility, but this test illustrates what
    // should still happen if Java had a true relaxed memory guard.

    final AtomicBoolean guard2 = new AtomicBoolean();
    m.l = 0L;

    fork(new Runnable() {
      public void run() {
        while (!guard2.get());  // busy-waiting
        load();
        expectEqual64(-987654321L, m.l);
      }
    });

    m.l = -987654321L;
    store();
    while (!guard2.weakCompareAndSet(false, true));  // relaxed memory order
    join();

    // Some checks on release/acquire fences within different threads using a test suggested by
    // Hans Boehm. Even this test remains with the realm of soundness checking only, since having
    // the threads read the same value consistently would be a valid outcome.

    m.x_value = -1;
    m.y_value = -1;
    m.running = true;

    fork(new Runnable() {
      public void run() {
        while (m.running) {
          for (int few_times = 0; few_times < 1000; few_times++) {
            // Read y first, then load fence, then read x.
            // They should appear in order, if seen at all.
            int local_y = m.y_value;
            load();
            int local_x = m.x_value;
            expectLessThanOrEqual32(local_y, local_x);
          }
        }
      }
    });

    for (int many_times = 0; many_times < 100000; many_times++) {
      m.x_value = many_times;
      store();
      m.y_value = many_times;
    }
    m.running = false;
    join();

    // All done!

    System.out.println("passed");
  }

  // Use reflection to implement "Unsafe.getUnsafe()";
  private static Unsafe getUnsafe() {
    try {
      Class<?> unsafeClass = Unsafe.class;
      Field f = unsafeClass.getDeclaredField("theUnsafe");
      f.setAccessible(true);
      return (Unsafe) f.get(null);
    } catch (Exception e) {
      throw new Error("Cannot get Unsafe instance");
    }
  }

  private static void expectEqual32(int expected, int result) {
    if (expected != result) {
      throw new Error("Expected: " + expected + ", found: " + result);
    }
  }

  private static void expectLessThanOrEqual32(int val1, int val2) {
    if (val1 > val2) {
      throw new Error("Expected: " + val1 + " <= " + val2);
    }
  }

  private static void expectEqual64(long expected, long result) {
    if (expected != result) {
      throw new Error("Expected: " + expected + ", found: " + result);
    }
  }

  private static void expectEqualObj(Object expected, Object result) {
    if (expected != result) {
      throw new Error("Expected: " + expected + ", found: " + result);
    }
  }
}
