Skip to content

Commit

Permalink
more error info & fix deadlocks.
Browse files Browse the repository at this point in the history
  • Loading branch information
aoli-al committed Apr 24, 2024
1 parent 85bd4c1 commit 04aaeeb
Show file tree
Hide file tree
Showing 12 changed files with 63 additions and 47 deletions.
22 changes: 14 additions & 8 deletions core/src/main/kotlin/cmu/pasta/fray/core/GlobalContext.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import cmu.pasta.fray.core.concurrency.locks.LockManager
import cmu.pasta.fray.core.concurrency.locks.SemaphoreManager
import cmu.pasta.fray.core.concurrency.operations.*
import cmu.pasta.fray.core.logger.LoggerBase
import cmu.pasta.fray.core.runtime.AnalysisResult
import cmu.pasta.fray.core.scheduler.Choice
import cmu.pasta.fray.core.scheduler.FifoScheduler
import cmu.pasta.fray.core.scheduler.Scheduler
Expand All @@ -22,6 +21,7 @@ import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executors
import java.util.concurrent.Semaphore
import java.util.concurrent.locks.Condition
import java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReentrantLock
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock
Expand Down Expand Up @@ -100,6 +100,8 @@ object GlobalContext {
}
}
context.state = ThreadState.Completed
Runtime.DELEGATE = Delegate()
done()
}

fun start() {
Expand All @@ -118,8 +120,8 @@ object GlobalContext {
scheduleNextOperation(true)
}

fun done(result: AnalysisResult) {
loggers.forEach { it.executionDone(result) }
fun done() {
loggers.forEach { it.executionDone() }

assert(lockManager.waitingThreads.isEmpty())
assert(syncManager.synchronizationPoints.isEmpty())
Expand Down Expand Up @@ -175,7 +177,7 @@ object GlobalContext {
if (context.state == ThreadState.Running) {
return
}
assert(context.state == ThreadState.Paused)
assert(context.state == ThreadState.Enabled)
syncManager.signal(t)
context.block()
}
Expand All @@ -192,7 +194,7 @@ object GlobalContext {
}

fun threadUnparkDone(t: Thread) {
if (registeredThreads[t.id]!!.state == ThreadState.Paused) {
if (registeredThreads[t.id]!!.state != ThreadState.Paused) {
// SFuzz only needs to wait if `t` is parked and then
// waken up by this `unpark` operation.
syncManager.wait(t)
Expand Down Expand Up @@ -224,7 +226,6 @@ object GlobalContext {
size = it.size
}
syncManager.createWait(t, size)

executor.submit {
while (t.isAlive) {
Thread.yield()
Expand Down Expand Up @@ -392,7 +393,7 @@ object GlobalContext {
objectNotifyAllImpl(o, lockManager.lockFromCondition(o))
}

fun reentrantLockTrylock(lock: Any) {
fun lockTryLock(lock: Any) {
val t = Thread.currentThread().id
val objId = System.identityHashCode(lock)
registeredThreads[t]?.pendingOperation = LockLockOperation(objId)
Expand Down Expand Up @@ -514,7 +515,7 @@ object GlobalContext {
syncManager.wait(lock)
}

fun lockNewCondition(condition: Condition, lock: ReentrantLock) {
fun lockNewCondition(condition: Condition, lock: Lock) {
lockManager.registerNewCondition(condition, lock)
}

Expand Down Expand Up @@ -660,6 +661,11 @@ object GlobalContext {
}
}

fun yield() {
registeredThreads[Thread.currentThread().id]!!.state = ThreadState.Enabled
scheduleNextOperation(true)
}

fun scheduleNextOperation(shouldBlockCurrentThread: Boolean) {
try {
// Our current design makes sure that reschedule is only called
Expand Down
29 changes: 21 additions & 8 deletions core/src/main/kotlin/cmu/pasta/fray/core/RuntimeDelegate.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import cmu.pasta.fray.runtime.TargetTerminateException
import java.util.concurrent.CountDownLatch
import java.util.concurrent.Semaphore
import java.util.concurrent.locks.Condition
import java.util.concurrent.locks.ReentrantLock
import java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReentrantReadWriteLock

class RuntimeDelegate : Delegate() {
Expand Down Expand Up @@ -101,7 +101,7 @@ class RuntimeDelegate : Delegate() {
entered.set(false)
}

override fun onLockLockInterruptibly(l: ReentrantLock) {
override fun onLockLockInterruptibly(l: Lock) {
if (checkEntered()) {
skipFunctionEntered.set(1 + skipFunctionEntered.get())
return
Expand All @@ -114,7 +114,20 @@ class RuntimeDelegate : Delegate() {
}
}

override fun onLockLock(l: ReentrantLock) {
override fun onLockTryLock(l: Lock) {
if (checkEntered()) {
skipFunctionEntered.set(1 + skipFunctionEntered.get())
return
}
try {
GlobalContext.lockTryLock(l)
} finally {
entered.set(false)
skipFunctionEntered.set(skipFunctionEntered.get() + 1)
}
}

override fun onLockLock(l: Lock) {
if (checkEntered()) {
skipFunctionEntered.set(1 + skipFunctionEntered.get())
return
Expand All @@ -127,7 +140,7 @@ class RuntimeDelegate : Delegate() {
}
}

override fun onLockLockDone(l: ReentrantLock?) {
override fun onLockLockDone(l: Lock?) {
skipFunctionEntered.set(skipFunctionEntered.get() - 1)
}

Expand All @@ -140,7 +153,7 @@ class RuntimeDelegate : Delegate() {
}
}

override fun onLockUnlock(l: ReentrantLock) {
override fun onLockUnlock(l: Lock) {
if (checkEntered()) {
skipFunctionEntered.set(1 + skipFunctionEntered.get())
return
Expand All @@ -150,7 +163,7 @@ class RuntimeDelegate : Delegate() {
skipFunctionEntered.set(1 + skipFunctionEntered.get())
}

override fun onLockUnlockDone(l: ReentrantLock) {
override fun onLockUnlockDone(l: Lock) {
skipFunctionEntered.set(skipFunctionEntered.get() - 1)
if (checkEntered()) return
GlobalContext.lockUnlockDone(l)
Expand Down Expand Up @@ -178,7 +191,7 @@ class RuntimeDelegate : Delegate() {
entered.set(false)
}

override fun onLockNewCondition(c: Condition, l: ReentrantLock): Condition {
override fun onLockNewCondition(c: Condition, l: Lock): Condition {
if (checkEntered()) return c
GlobalContext.lockNewCondition(c, l)
entered.set(false)
Expand Down Expand Up @@ -283,7 +296,7 @@ class RuntimeDelegate : Delegate() {
override fun onYield() {
if (checkEntered()) return
try {
GlobalContext.scheduleNextOperation(true)
GlobalContext.yield()
} finally {
entered.set(false)
}
Expand Down
7 changes: 1 addition & 6 deletions core/src/main/kotlin/cmu/pasta/fray/core/TestRunner.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package cmu.pasta.fray.core

import cmu.pasta.fray.core.logger.ConsoleLogger
import cmu.pasta.fray.core.runtime.AnalysisResult
import cmu.pasta.fray.runtime.Delegate
import cmu.pasta.fray.runtime.Runtime
import java.nio.file.Paths
import kotlin.io.path.ExperimentalPathApi
Expand Down Expand Up @@ -39,12 +37,9 @@ class TestRunner(val config: Configuration) {
config.exec()
Runtime.onMainExit()
} catch (e: Throwable) {
GlobalContext.errorFound = true
Runtime.onReportError(e)
Runtime.onMainExit()
GlobalContext.log("Error found: $e")
}
Runtime.DELEGATE = Delegate()
GlobalContext.done(AnalysisResult.COMPLETE)
if (GlobalContext.errorFound) {
println("Error found at iter: $i")
break
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package cmu.pasta.fray.core.logger

import cmu.pasta.fray.core.concurrency.operations.Operation
import cmu.pasta.fray.core.runtime.AnalysisResult
import cmu.pasta.fray.core.scheduler.Choice

class ConsoleLogger : LoggerBase {
override fun executionStart() {}

override fun newOperationScheduled(op: Operation, choice: Choice) {}

override fun executionDone(result: AnalysisResult) {}
override fun executionDone() {}

override fun applicationEvent(event: String) {
println(event)
Expand Down
3 changes: 1 addition & 2 deletions core/src/main/kotlin/cmu/pasta/fray/core/logger/CsvLogger.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package cmu.pasta.fray.core.logger

import cmu.pasta.fray.core.concurrency.operations.Operation
import cmu.pasta.fray.core.runtime.AnalysisResult
import cmu.pasta.fray.core.scheduler.Choice
import java.io.File

Expand All @@ -20,7 +19,7 @@ class CsvLogger(private val baseFolder: String, private val fullSchedule: Boolea
"${choice.selected},${choice.threadId},${choice.enabled},${op.javaClass.name}\n")
}

override fun executionDone(result: AnalysisResult) {
override fun executionDone() {
index += 1
}

Expand Down
6 changes: 2 additions & 4 deletions core/src/main/kotlin/cmu/pasta/fray/core/logger/JsonLogger.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package cmu.pasta.fray.core.logger

import cmu.pasta.fray.core.concurrency.operations.Operation
import cmu.pasta.fray.core.runtime.AnalysisResult
import cmu.pasta.fray.core.scheduler.Choice
import cmu.pasta.fray.core.scheduler.Schedule
import java.io.File
Expand All @@ -13,7 +12,6 @@ import kotlinx.serialization.json.Json
data class Record(
val timeline: MutableList<Operation>,
val schedule: Schedule,
val result: AnalysisResult
)

class JsonLogger(val base: String, val fullSchedule: Boolean) : LoggerBase {
Expand All @@ -33,8 +31,8 @@ class JsonLogger(val base: String, val fullSchedule: Boolean) : LoggerBase {
schedule.choices.add(choice)
}

override fun executionDone(result: AnalysisResult) {
executions.add(Record(currentTimeline, schedule, result))
override fun executionDone() {
executions.add(Record(currentTimeline, schedule))
// if (result != AnalysisResult.COMPLETE) {
//
// File("$base/schedule_${savedSchedule++}.json").writeText(json.encodeToString(schedule))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package cmu.pasta.fray.core.logger

import cmu.pasta.fray.core.concurrency.operations.Operation
import cmu.pasta.fray.core.runtime.AnalysisResult
import cmu.pasta.fray.core.scheduler.Choice

interface LoggerBase {
fun executionStart()

fun newOperationScheduled(op: Operation, choice: Choice)

fun executionDone(result: AnalysisResult)
fun executionDone()

// fun logError(error: String)

Expand Down
1 change: 1 addition & 0 deletions integration-tests/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ tasks.test {
executable("${jdk.layout.buildDirectory.get().asFile}/java-inst/bin/java")
jvmArgs("-agentpath:$agentPath")
jvmArgs("-javaagent:${instrumentation.layout.buildDirectory.get().asFile}/libs/${instrumentation.name}-${instrumentation.version}-all.jar")
jvmArgs("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005")
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public void newOperationScheduled(Operation op, Choice choice) {
}

@Override
public void executionDone(AnalysisResult result) {
public void executionDone() {

}

Expand Down
4 changes: 4 additions & 0 deletions run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
while true
do
./gradlew cleanTest :integration-tests:test --tests "cmu.pasta.fray.it.lincheck.LogicalOrderingAVLTest.testConcurrentInsertRemove"
done
15 changes: 8 additions & 7 deletions runtime/src/main/java/cmu/pasta/fray/runtime/Delegate.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

Expand Down Expand Up @@ -32,27 +33,27 @@ public void onObjectNotify(Object o) {
public void onObjectNotifyAll(Object o) {
}

public void onReentrantLockTryLock(ReentrantLock l) {
public void onLockTryLock(Lock l) {
}

public void onLockLock(ReentrantLock l) {
public void onLockLock(Lock l) {
}
public void onLockLockInterruptibly(ReentrantLock l) {
public void onLockLockInterruptibly(Lock l) {
}

public void onLockLockDone(ReentrantLock l) {
public void onLockLockDone(Lock l) {
}

public void onLockUnlock(ReentrantLock l) {
public void onLockUnlock(Lock l) {
}

public void onLockUnlockDone(ReentrantLock l) {
public void onLockUnlockDone(Lock l) {
}

public void onAtomicOperation(Object o, MemoryOpType type) {
}

public Condition onLockNewCondition(Condition c, ReentrantLock l) {
public Condition onLockNewCondition(Condition c, Lock l) {
return c;
}

Expand Down
15 changes: 8 additions & 7 deletions runtime/src/main/java/cmu/pasta/fray/runtime/Runtime.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

Expand All @@ -28,27 +29,27 @@ public static void onThreadRun() {
DELEGATE.onThreadRun();
}

public static void onLockTryLock(ReentrantLock l) {
DELEGATE.onReentrantLockTryLock(l);
public static void onLockTryLock(Lock l) {
DELEGATE.onLockTryLock(l);
}

public static void onLockLock(ReentrantLock l) {
public static void onLockLock(Lock l) {
DELEGATE.onLockLock(l);
}

public static void onLockLockDone(ReentrantLock l) {
public static void onLockLockDone(Lock l) {
DELEGATE.onLockLockDone(l);
}

public static void onLockUnlock(ReentrantLock l) {
public static void onLockUnlock(Lock l) {
DELEGATE.onLockUnlock(l);
}

public static void onLockUnlockDone(ReentrantLock l) {
public static void onLockUnlockDone(Lock l) {
DELEGATE.onLockUnlockDone(l);
}

public static Condition onLockNewCondition(Condition c, ReentrantLock l) {
public static Condition onLockNewCondition(Condition c, Lock l) {
return DELEGATE.onLockNewCondition(c, l);
}

Expand Down

0 comments on commit 04aaeeb

Please sign in to comment.