Commit 51d3bbbf authored by Kunshan Wang's avatar Kunshan Wang

Implementing futex...

parent 7e5164ee
......@@ -28,6 +28,8 @@ object CommInsts extends SimpleNamespace[CommInst] {
commInst(0x21a, "@uvm.tr64.to_tag")
commInst(0x220, "@uvm.futex.wait")
commInst(0x221, "@uvm.futex.wake")
commInst(0x221, "@uvm.futex.wait_timeout")
commInst(0x222, "@uvm.futex.wake")
commInst(0x223, "@uvm.futex.cmp_requeue")
}
\ No newline at end of file
......@@ -23,6 +23,7 @@ object InternalTypes {
val I1 = TypeInt(1) := internal("i1")
val I6 = TypeInt(6) := internal("i6")
val I32 = TypeInt(32) := internal("i32")
val I52 = TypeInt(52) := internal("i52")
val I64 = TypeInt(52) := internal("i64")
val DOUBLE = TypeDouble() := internal("double")
......@@ -125,8 +126,10 @@ object TypeInferer {
case "@uvm.tr64.to_int" => I52
case "@uvm.tr64.to_ref" => REF_VOID
case "@uvm.tr64.to_tag" => I6
case "@uvm.futex.wait" => I64
case "@uvm.futex.wake" => I64
case "@uvm.futex.wait" => I32
case "@uvm.futex.wait_timeout" => I32
case "@uvm.futex.wake" => I32
case "@uvm.futex.cmp_requeue" => I32
}
}
}
\ No newline at end of file
package uvm.refimpl.itpr
import uvm.refimpl.mem.TypeSizes.Word
import scala.collection.mutable.{ HashSet, HashMap, MultiMap, ListBuffer, Set, TreeSet }
import scala.math.Ordering
/**
* This class manages Futexes.
*/
class FutexManager {
case class WaitRecord(val objRef: Word, val offset: Word, val loc: Word, val thread: InterpreterThread, val autoWakeup: Option[Long])
type WaitingQueueType = ListBuffer[WaitRecord]
type WaitingQueuesType = HashMap[Word, WaitingQueueType]
/** One waiting queue for each memory location (address). */
private val waitingQueues = new WaitingQueuesType()
/** Maps each object address to all its internal locations. Non-heap locations has objRef==0. */
private val objIndex = new HashMap[Word, Set[Word]] with MultiMap[Word, Word]
/** Waiting threads with timeout */
private val timeoutSet = new TreeSet[WaitRecord]()(Ordering.by(_.autoWakeup.get))
def futexWaitNoCheck(objRef: Word, offset: Word, thread: InterpreterThread, maybeTimeout: Option[Long] = None): Unit = {
thread.isFutexWaiting = true
val loc = objRef + offset
val autoWakeup = maybeTimeout.map { timeout =>
val now = System.currentTimeMillis()
timeout + now * 1000000L
}
val wr = WaitRecord(objRef, offset, loc, thread, autoWakeup)
val q = waitingQueues.getOrElseUpdate(loc, new WaitingQueueType)
q.append(wr)
objIndex.addBinding(objRef, loc)
if (autoWakeup.isDefined) {
timeoutSet.add(wr)
}
}
def futexWake(objRef: Word, offset: Word, nThread: Int): Unit = {
val loc = objRef + offset
waitingQueues.get(loc).foreach { q =>
val wrs = q.take(nThread)
for (wr <- wrs) {
wr.thread.isFutexWaiting = false
timeoutSet.remove(wr)
}
if (wrs.size <= q.size) {
waitingQueues.remove(loc)
objIndex.removeBinding(objRef, loc)
} else {
q.remove(0, wrs.size)
}
}
}
def futexWakeTimeout(): Unit = {
val now = System.currentTimeMillis() * 1000000L
while (!timeoutSet.isEmpty) {
val first = timeoutSet.firstKey
if (first.autoWakeup.get <= now) {
first.thread.isFutexWaiting = false
timeoutSet.remove(first)
}
}
}
def futexRequeue(objRefSrc: Word, offsetSrc: Word, objRefDst: Word, offsetDst: Word, nThread: Int): Unit = {
val locSrc = objRefSrc + offsetSrc
val locDst = objRefDst + offsetDst
waitingQueues.get(locSrc).foreach { q =>
waitingQueues.remove(locSrc)
objIndex.removeBinding(objRefSrc, locSrc)
val wakes = q.take(nThread)
for (wr <- wakes) {
wr.thread.isFutexWaiting = false
timeoutSet.remove(wr)
}
val moves = q.drop(nThread)
if (!moves.isEmpty) {
objIndex.addBinding(objRefDst, locDst)
waitingQueues.get(locDst) match {
case None => {
waitingQueues(locDst) = moves
}
case Some(qDst) => {
qDst.appendAll(moves)
}
}
}
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment