# Lock Words

A lock enforces mutual exclusion, typically with regard to control of a resource, between multiple tasks. It also serves as a queue for multiple tasks waiting on the lock which is held by another task. Furthermore, it provides a mechanism to avoid priority inversion, by temporarily elevating each task holding a lock's priority to the maximum priority of all the tasks waiting for it; this applies even when chaining together multiple locks held by tasks holding some locks and waiting on others. Recursive lockings are permitted, with a recursive locking count being maintained by a given lock, which is finally released when all the lockings are matched by releases.

### `lock`

The following words are in `lock`:

##### `x-not-currently-owned`
( -- )

Exception raised if a task attempts to unlock a lock it is not the holder of.

##### `lock-size`
( -- bytes )

Get the size of a lock in bytes.

##### `init-lock`
( addr -- )

Initialize a lock starting at the specified address *addr*; note that it must be `lock-size` bytes in size.

##### `claim-lock`
( lock -- )

Attempt to acquire a lock *lock*; if the lock is already held, put the current task in a queue and disable it. In that case, update the priority of the holder of a lock, and any subsequent holders of any locks waited for by the holder of this lock, in order to avoid priority inversion. Note that this must not be called within a critical section. Any number of lockings by the same task are permitted; the lock will be freed when they are balanced by an equal number of releasings.

##### `release-lock`
( lock -- )

Attempt to release a lock *lock* if it is not recursively locked; if the current task is not the holder of the lock, raise `x-not-currently-owned`. If releasing the lock is successful, restore the priority of the current task to what it would be had its priority not been updated in order to avoid priority inversion; afterwards, carry out all the functionality that `lock` would carry out had it been called by the task at the head of the queue if there is one. If a lock *lock* is recursively locked, decrement the recursive lock count by one. Note that this must not be called within a critical section.

##### `with-lock`
( xt lock -- )

Execute an xt with a given lock *lock* locked while it executes, unlocking it afterwards. If an exception is raised by *xt*, unlock *lock* and then re-raise the exception.
