index
Spinlocks
Internals
- they effectively spin until the lock becomes released. In each spin (while iteration) they check if the lock has been released yet; if not, they just spin further.
- optimization for UP: do nothing.
- new lock holder spins already, not sleeping, so no need to wakeup
Usage
- very lightweight, but should be held only for very short time (as other contenders spin and don't sleep!)
- read spinlocks (effectively shared) are also available, but not recommended for new implementations
- can not sleep while holding a spinlock; scheduler will panic about spinlocks being held by yielding thread XXX
- can never recurse!
- used to protect structures
LWKT serializing tokens
Internals
- uses atomic_cmpset* internally
- UP optimization: only check to see if preemption is happening, in which case acquisition of token fails.
- deeply integrated with lwkt scheduler (lwkt_yield, ...)
- scheduler takes care of acquiring the token before rescheduling
- so a thread won't run unless the scheduler can acquire all the tokens for it.
- tokens are not owned by the thread but by the CPU. threads only get token references
- no explicit wakeup when yielding a token reference
Usage
- a same thread can acquire multiple token references, but if that's the case, all tokens have to be acquired before the lwkt is scheduled!
- if thread sleeps while holding token references, other threads can acquire a token reference and run; so not completely safe to sleep
- used to protect heavier processing than spinlocks; but mostly also to protect data structures. Often used for global lists (allproc, etc)
- when acquiring token, not available, go to sleep, lose tokens
Lockmgr
Internals
- uses a spinlock inside
- sleeps while acquiring (at least if NO_WAIT is not specified) XXX
- heavyweight
- wakeup used to activate new lock holder
- no UP optimization
Usage
- supports shared locks or exclusive locks, shared locks can be upgraded, exclusive can be downgraded
- can be acquired recursively, if the thread is the same and LK_CANRECURSE is specified
- can sleep while holding the lock.
- used when there is a requirement or possibility of blocking/sleep/recursion/...
MTX
Internals
- based around atomic_cmpset_int instead of spinlocks
- uses wakeup to activate new lock holder
- much more lightweight than lockmgr (faster, much less space)
- no UP optimization
Usage
- can always be recursive
- can be shared/exclusive, so upgradable
- can be held across blocking/sleeps
- can pass lock ownership directly to new owner, so no wakeup needed and is guaranteed to reach the intended destination
MPLock
Internals
- internally uses atomic_cmpset
- logs when the mplock is contended to KTR
- clogs performance inmensely
Usage
- should be avoided at all cost
- must be held as little as possible
- one for the whole system (all CPUs!!)
LWKT Messages
Internals
- messages are passed by queueing them to the destination thread's message queue, then waking up the listener.
- messages have to be allocated/deallocated (typically using objcache_*)
- (usually use a drain to deallocate; set the replyport to be the drain and then just reply to the message)
- rather lightweight, except for inter-processor messages
Usage
- isn't a locking mechanism, rather serialization as everything can be processed in one thread if the others just send it to that one
- can be used to avoid races: just do all the processing in one single thread
- send all the work from other threads/entry points to that one thread using lwkt messages.
- requires no locking
Critical Sections
Internals
- Changes priority of current thread to TDPRIT_CRIT, effectively avoiding preemption of the thread
- are per-cpu
Usage
- avoid anything else happening on that CPU due to the disabled preemption
- are no synchronization/locking between different CPUs!
- should be used if some code has to run uninterruptedly
Condvars
Internals
- XXX: currently not yet in the main repository
- uses spinlocks internally on the condvar
Usage
- can interlock sleep when given a lockmgr lock to avoid missing changes to it, or just regular tsleep
- used to wait for conditions to happen (threads doing this are waiters)
- can wakeup all waiters or just one, effectively notifying that a change has occured