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 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 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_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 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_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 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 __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, 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 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
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