/*
This file is part of JOP, the Java Optimized Processor
see <http://www.jopdesign.com/>
Copyright (C) 2011, Benedikt Huber (benedikt.huber@gmail.com)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package wcet.devel;
/*
make jsim P1=test P2=wcet/devel P3=Synchronized1
*/
import joprt.*;
import util.Timer;
import com.jopdesign.sys.Config;
import com.jopdesign.sys.Const;
import com.jopdesign.sys.Native;
public class Synchronized1 {
static class Mon {
public static final int LO = 0;
public static final int HI = 100;
private int value;
public Mon(int initial) { value = initial; }
public int getValue() { return value; }
public synchronized boolean increment() { value++; return (value < HI); }
public synchronized boolean decrement() { value--; return (value > LO); }
public synchronized boolean syncrement(Mon other) {
if(getValue() < HI && other.increment()) { return increment(); }
else { return false; }
}
public synchronized boolean check() {
int sum = 0;
for(int i = 0; i < value; i++) { //@WCA loop <= 100
sum += value;
}
return(sum==0 || sum==5050);
}
}
private static Mon monitor1 = new Mon(50);
private static Mon monitor2 = new Mon(50);
private static int shared1 = 1, shared2 = 1;
private static int unshared1 = 1, unshared2 = 1;
static int ts, te, to;
/**
* @param args
*/
public static void main(String[] args) {
// tests
ts = Native.rdMem(Const.IO_CNT);
te = Native.rdMem(Const.IO_CNT);
to = te-ts;
run1();
run2();
run3();
run4();
run5();
// initialization
new RtThread(1, 3000) {
public void run() {
for (;;) {
run4();
if (!waitForNextPeriod()) {
break;
}
}
}
};
new RtThread(2, 500) {
public void run() {
for (;;) {
run5();
if (!waitForNextPeriod()) {
break;
}
}
}
};
System.out.println("Start Mission");
RtThread.startMission();
for (;;) {
Timer.wd();
System.out.println("monitor1 (unsync): " + monitor1.getValue());
System.out.println("monitor2 (unsync): " + monitor2.getValue());
RtThread.sleepMs(1000);
}
}
/* For run1(), we expect one blocking time, namely Mon#check */
public static void run1() {
monitor1.check();
monitor2.check();
}
/* For run2(), we expect three blocking times, 2+3 should be the same
and larger than 1 */
public static void run2() {
ts = Native.rdMem(Const.IO_CNT);
synchronized(monitor1) {
shared1 = shared1 * shared2;
}
te = Native.rdMem(Const.IO_CNT);
System.out.print("[run2/1] ");
System.out.println(te-ts-to);
ts = Native.rdMem(Const.IO_CNT);
synchronized(monitor2) {
shared1 = shared1 * shared1 + shared2 * shared2;
}
te = Native.rdMem(Const.IO_CNT);
System.out.print("[run2/2] ");
System.out.println(te-ts-to);
for(int i = 0; i < 100; i++) { //@WCA loop=100
unshared1 = unshared1 * 3 + 1;
}
ts = Native.rdMem(Const.IO_CNT);
synchronized(monitor2) {
shared1 = shared1 * shared1 + shared2 * shared2;
}
te = Native.rdMem(Const.IO_CNT);
System.out.print("[run2/3] ");
System.out.println(te-ts-to);
}
/* run3(): triple nested synchronized */
public static void run3() {
int x = 0;
synchronized(monitor1) {
x += shared1;
synchronized(monitor2) {
if(monitor1.syncrement(monitor2)) {
x+=1;
}
}
x += shared1;
shared1 = 2 * x;
}
}
/* For run4(), we expect 5 blocking times:
Mon#check, the first synchronized block (nested: Mon#decrement),
the second synchronized block (nested: Mon#increment).
The nesting in this test accesses the same lock twice */
public static void run4() {
monitor1.check();
synchronized(monitor1) {
while(monitor1.decrement()) { // @WCA loop<=100
}
}
for(int i = 0; i < 32000; i++) { //@WCA loop = 32000
unshared1 = unshared1 * 3 + 1;
}
monitor2.check();
synchronized(monitor2) {
while(monitor2.increment()) { //@WCA loop<=100
}
}
}
/* run5() has true nested locks, and is otherwise similar to run3() */
public static void run5() {
monitor2.check();
synchronized(monitor1) {
while(monitor2.decrement()) { // @WCA loop<=100
}
}
for(int i = 0; i < 32000; i++) { //@WCA loop = 32000
unshared1 = unshared1 * 3 + 1;
}
monitor1.check();
synchronized(monitor2) {
while(monitor1.increment()) { //@WCA loop<=100
}
}
}
}