def join2(self, t1: Thread, t2: Thread) -> None: Requires(t1 is not t2) Requires(getMethod(t1) == Clazz.readX) Requires(getMethod(t2) == Clazz.readX) Requires(getArg(t1, 0) is self) Requires(getArg(t2, 0) is self) Requires(Joinable(t1)) Requires(Joinable(t2)) Requires(Acc(ThreadPost(t1))) Requires(Acc(ThreadPost(t2))) Requires(WaitLevel() < Level(t1)) Requires(WaitLevel() < Level(t2)) Ensures(Acc(self.x, getARP(t1) + getARP(t2))) t1.join(self.readX) t2.join(self.readX)
def client_fork(t: Thread, l: BaseLock) -> None: Requires(Acc(MayStart(t))) Requires(getMethod(t) == noop) Requires(l is getArg(t, 0)) Ensures(WaitLevel() < Level(t)) #:: ExpectedOutput(invalid.program:invalid.thread.start) t.start(noop)
def do_a_thing_6(self) -> None: Requires(Rd(self.l) and Rd(self.c) and self.l.get_locked() is self.c) Requires(WaitLevel() < Level(self.l)) Ensures(Rd(self.l) and Rd(self.c)) #:: ExpectedOutput(assignment.failed:insufficient.permission) self.c.value += 2 self.l.release()
def thread_join_not_joinable(t: Thread, cl: Cell) -> None: Requires(getMethod(t) == decr) Requires(getArg(t, 0) is cl) Requires(getArg(t, 1) is 7) Requires(getOld(t, arg(0).val) is 123) Requires(WaitLevel() < Level(t)) #:: ExpectedOutput(thread.join.failed:thread.not.joinable) t.join(Cell.incr, decr)
def __init__(self, c: Cell) -> None: Requires(Acc(c.rds) and Acc(c.value) and c.rds == 0) Ensures( Acc(self.c) and self.c == c and Acc(self.lock) and self.lock.get_locked() is self.c) Ensures(WaitLevel() < Level(self.lock)) self.c = c # type: Cell self.lock = CellLock(self.c) # type: CellLock
def acquire(self) -> None: """Acquire the lock.""" Requires(MustTerminate(1)) Requires(WaitLevel() < Level(self)) Requires(Low(self)) Requires(LowEvent()) Ensures(self.invariant()) Ensures(MustRelease(self))
def __init__(self) -> None: self.c = Cell(12) self.c.value = 14 self.l = CellLock(self.c) #:: ExpectedOutput(assignment.failed:insufficient.permission) self.c.value = 16 Ensures(Acc(self.c) and Acc(self.l) and self.l.get_locked() is self.c) Ensures(WaitLevel() < Level(self.l))
def printTwice(l: Lock[Cell], x: int) -> None: Requires(LowEvent()) Requires(Low(l) and Low(x)) Requires(MustTerminate(4)) Requires(WaitLevel() < Level(l)) l.acquire() sif_print(x) sif_print(x) l.release()
def join1(self, t: Thread) -> None: Requires(getMethod(t) == Clazz.readX) Requires(getArg(t, 0) is self) Requires(Joinable(t)) Requires(Acc(ThreadPost(t), 1)) Requires(Acc(self.x, 1 - getARP(t))) Requires(WaitLevel() < Level(t)) Ensures(Acc(self.x)) t.join(self.readX)
def do_a_thing(self) -> None: Requires(Rd(self.l) and Rd(self.c) and self.l.get_locked() is self.c) Requires(WaitLevel() < Level(self.l)) Ensures(Rd(self.l) and Rd(self.c)) #:: ExpectedOutput(postcondition.violated:assertion.false) Ensures(False) self.l.acquire() self.c.value += 2 self.l.release()
def thread1(l: CellLock, c: Cell) -> None: Requires(Low(l) and l.get_locked() is c) Requires(LowEvent() and WaitLevel() < Level(l)) ctr = 0 while ctr < 100: Invariant(Low(ctr)) ctr += 1 l.acquire() c.value = 1 l.release()
def thread2(l: CellLock, c: Cell, secret: int) -> None: Requires(Low(l) and l.get_locked() is c) Requires(LowEvent() and WaitLevel() < Level(l)) ctr = 0 while ctr < secret: Invariant(TerminatesSif(True, secret - ctr)) ctr += 1 l.acquire() c.value = 2 l.release()
def thread_join_no_post_perm(t: Thread, cl: Cell) -> None: Requires(getMethod(t) == decr) Requires(getArg(t, 0) is cl) Requires(getArg(t, 1) is 7) Requires(getOld(t, arg(0).val) is 123) Requires(Joinable(t)) Requires(WaitLevel() < Level(t)) t.join(Cell.incr, decr) #:: ExpectedOutput(assert.failed:insufficient.permission) assert cl.val == 116
def thread_join_wrong_method(t: Thread, cl: Cell) -> None: Requires(getMethod(t) == Cell.incr) Requires(getArg(t, 0) is cl) Requires(getArg(t, 1) is 7) Requires(getOld(t, arg(0).val) is 123) Requires(Acc(ThreadPost(t))) Requires(WaitLevel() < Level(t)) t.join(decr) #:: ExpectedOutput(assert.failed:insufficient.permission) assert cl.val == 116
def thread_join_part_perm(t: Thread, cl: Cell) -> None: Requires(getMethod(t) == decr) Requires(getArg(t, 0) is cl) Requires(getArg(t, 1) is 7) Requires(getOld(t, arg(0).val) is 123) Requires(Acc(ThreadPost(t), 1 / 2)) Requires(WaitLevel() < Level(t)) t.join(Cell.incr, decr) assert cl.val == 116 #:: ExpectedOutput(assignment.failed:insufficient.permission) cl.val = 11
def client_fork(t: Thread, b: bool, cell: Cell) -> None: Requires(Acc(MayStart(t))) Requires(getMethod(t) == Cell.incr) Requires(Acc(cell.val)) Requires(cell is getArg(t, 0)) Ensures(getOld(t, arg(0).val) == 12) Ensures(WaitLevel() < Level(t)) #:: ExpectedOutput(postcondition.violated:insufficient.permission) Ensures(Acc(MayStart(t))) cell.val = 12 t.start(decr, Cell.incr)
def thread2(l: CellLock, c: Cell, secret: int) -> None: Requires(Low(l) and l.get_locked() is c) Requires(LowEvent() and WaitLevel() < Level(l)) while secret > 0: # When writing TerminatesSif(e1, e2) as the last part of the invariant, Nagini does not check that the # termination condition is low (which is the default), but instead checks that the loop terminates if e1 holds # initially, using the ranking function e2. This is an alternative sufficient condition. Invariant(TerminatesSif(True, secret)) secret -= 1 l.acquire() c.leak = False l.release()
def do_write(self, writer: Writer) -> None: Requires(writer is not None) Requires(Rd(self.lock) and Rd(self.c) and self.lock.get_locked() is self.c) Requires(WaitLevel() < Level(self.lock)) Ensures(Rd(self.lock) and Rd(self.c)) self.lock.acquire() if self.c.rds != 0: #:: UnexpectedOutput(silicon)(lock.invariant.not.established:assertion.false,320) self.lock.release() self.do_write(writer) # try again else: writer.write(self.c) # lock acquired successfully self.lock.release()
def thread_join_pred(t: Thread, cl: Cell) -> None: Requires(getMethod(t) == decr_pred) Requires(getArg(t, 0) is cl) Requires(getArg(t, 1) is 7) Requires(getOld(t, arg(0).val) is 123) Requires(Acc(ThreadPost(t))) Requires(WaitLevel() < Level(t)) Ensures(Joinable(t)) #:: ExpectedOutput(postcondition.violated:assertion.false) Ensures(False) t.join(decr, decr_pred) Unfold(cell_pred(cl, 116)) assert cl.val == 116
def do_read(self, reader: Reader) -> None: Requires(reader is not None) Requires(Rd(self.lock) and Rd(self.c) and self.lock.get_locked() is self.c) Requires(WaitLevel() < Level(self.lock)) Ensures(Rd(self.lock) and Rd(self.c)) self.lock.acquire() self.c.rds += 1 #:: UnexpectedOutput(silicon)(lock.invariant.not.established:assertion.false,320) self.lock.release() reader.read(self.c) self.lock.acquire() self.c.rds -= 1 self.lock.release()
def thread_join_pred_partial(t: Thread, cl: Cell) -> None: Requires(getMethod(t) == decr_pred) Requires(getArg(t, 0) is cl) Requires(getArg(t, 1) is 7) Requires(getOld(t, arg(0).val) is 123) Requires(Acc(ThreadPost(t), 1 / 2)) Requires(WaitLevel() < Level(t)) Ensures(Joinable(t)) t.join(decr, decr_pred) Unfold(Acc(cell_pred(cl, 116), 1 / 2)) assert cl.val == 116 #:: ExpectedOutput(unfold.failed:insufficient.permission) Unfold(Acc(cell_pred(cl, 116), 1 / 2))
def __init__(self, locked_object: T, above: Optional[BaseLock] = None, below: Optional[BaseLock] = None) -> None: """ Create a lock whose level is below that of ``below`` and above that of ``above``, which protects ``locked_object``. Creating the lock "shares" the object (i.e., exhales the invariant). Create subclasses of this class and override ``invariant`` to create a lock with an invariant. ``Level(above)`` defaults to ``WaitLevel()``. """ Requires(MustTerminate(1)) Requires( Implies(above is None and below is not None, WaitLevel() < Level(below))) Requires( Implies(above is not None and below is not None, Level(above) < Level(below))) Requires(self.invariant()) Ensures(Implies(above is None, WaitLevel() < Level(self))) Ensures(Implies(above is not None, Level(above) < Level(self))) Ensures(Implies(below is not None, Level(self) < Level(below)))
def do_a_thing(self) -> None: Requires(Rd(self.l) and Rd(self.c) and self.l.get_locked() is self.c) Requires(WaitLevel() < Level(self.l)) Ensures(Rd(self.l) and Rd(self.c)) #:: ExpectedOutput(postcondition.violated:assertion.false)|MissingOutput(postcondition.violated:assertion.false, 320) Ensures(False) self.l.acquire() self.c.n += 1 #:: UnexpectedOutput(silicon)(lock.invariant.not.established:assertion.false, 320) self.l.release() self.need_value() t1 = Thread(None, self.need_value, args=()) t2 = Thread(None, self.need_value, args=()) t1.start(self.need_value) t2.start(self.need_value) t1.join(self.need_value) t2.join(self.need_value) #:: ExpectedOutput(carbon)(assert.failed:assertion.false) Assert(False) # Carbon does not terminate for the next statement self.need_value() self.l.acquire() self.c.n -= 1 self.l.release()
def __init__(self) -> None: self.c = Cell(12) self.c.value = 14 self.l = CellLock(self.c) Ensures(Acc(self.c) and Acc(self.l) and self.l.get_locked() is self.c) Ensures(WaitLevel() < Level(self.l))
def thread_join_minimal(t: Thread, cl: Cell) -> None: Requires(Joinable(t)) Requires(WaitLevel() < Level(t)) t.join(Cell.incr, decr) #:: ExpectedOutput(assert.failed:insufficient.permission) assert cl.val == 116
def do_a_thing_5(self) -> None: Requires(Rd(self.l) and Rd(self.c) and self.l.get_locked() is self.c) Requires(WaitLevel() < Level(self.l)) Ensures(Rd(self.l) and Rd(self.c)) self.l.acquire() self.c.value += 2