[docs] tweak a few errors in the blocking primitives doc
This commit is contained in:
@@ -8,22 +8,21 @@ The LK kernel provides a comprehensive set of synchronization primitives for coo
|
|||||||
|
|
||||||
### Wait Queues Foundation
|
### Wait Queues Foundation
|
||||||
|
|
||||||
All blocking primitives in LK are built upon wait queues (`wait_queue_t`), which provide the fundamental blocking and wakeup mechanisms:
|
Most blocking primitives in LK are built upon wait queues (`wait_queue_t`) (with the exception of spinlocks), which provide the fundamental blocking and wakeup mechanisms:
|
||||||
|
|
||||||
- **Thread blocking**: Threads can be placed on wait queues and blocked until signaled
|
- **Thread blocking**: Threads can be placed on wait queues and blocked until signaled
|
||||||
- **Timeout support**: All wait operations support optional timeouts
|
- **Timeout support**: All wait operations support optional timeouts
|
||||||
- **Wake semantics**: Support for waking one thread or all threads
|
- **Wake semantics**: Support for waking one thread or all threads
|
||||||
- **Priority preservation**: Threads maintain their priority when blocked and resumed
|
- **Priority preservation**: Threads maintain their priority when blocked and resumed
|
||||||
|
|
||||||
### Locking Requirements
|
Most code in the system will not use a wait queue directly, it acts as the building block for other primitives.
|
||||||
|
|
||||||
All synchronization primitives require the global thread lock (`thread_lock`) to be held when manipulating their internal state. This ensures atomic operations and prevents race conditions during state transitions.
|
|
||||||
|
|
||||||
## Synchronization Primitives
|
## Synchronization Primitives
|
||||||
|
|
||||||
### 1. Mutexes
|
### 1. Mutexes
|
||||||
|
|
||||||
Mutexes provide exclusive access to shared resources with ownership semantics.
|
Mutexes provide exclusive access to shared resources with ownership semantics.
|
||||||
|
See [`mutex.h`](../kernel/include/kernel/mutex.h) implementation details.
|
||||||
|
|
||||||
#### Structure
|
#### Structure
|
||||||
|
|
||||||
@@ -46,17 +45,18 @@ typedef struct mutex {
|
|||||||
#### API
|
#### API
|
||||||
|
|
||||||
```c
|
```c
|
||||||
void mutex_init(mutex_t *m);
|
void mutex_init(mutex_t *m); // Initialze a mutex to the default state.
|
||||||
void mutex_destroy(mutex_t *m);
|
void mutex_destroy(mutex_t *m);
|
||||||
status_t mutex_acquire(mutex_t *m); // Infinite timeout
|
|
||||||
status_t mutex_acquire_timeout(mutex_t *m, lk_time_t timeout);
|
status_t mutex_acquire_timeout(mutex_t *m, lk_time_t timeout);
|
||||||
status_t mutex_release(mutex_t *m);
|
status_t mutex_acquire(mutex_t *m); // Same as above but with infinite timeout.
|
||||||
bool is_mutex_held(const mutex_t *m); // Check ownership
|
status_t mutex_release(mutex_t *m); // Release the mutex, must be the holding thread.
|
||||||
|
bool is_mutex_held(const mutex_t *m); // Is the mutex held by the current thread?
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Usage Example
|
#### Usage Example
|
||||||
|
|
||||||
```c
|
```c
|
||||||
|
// Static initialization of the mutex. Equivalent to mutex_init().
|
||||||
mutex_t resource_lock = MUTEX_INITIAL_VALUE(resource_lock);
|
mutex_t resource_lock = MUTEX_INITIAL_VALUE(resource_lock);
|
||||||
|
|
||||||
void protected_function(void) {
|
void protected_function(void) {
|
||||||
@@ -90,6 +90,7 @@ public:
|
|||||||
### 2. Semaphores
|
### 2. Semaphores
|
||||||
|
|
||||||
Semaphores control access to a finite number of resources using a counter mechanism.
|
Semaphores control access to a finite number of resources using a counter mechanism.
|
||||||
|
See [`semaphore.h`](../kernel/include/kernel/semaphore.h) implementation details.
|
||||||
|
|
||||||
#### Structure
|
#### Structure
|
||||||
|
|
||||||
@@ -146,6 +147,7 @@ void use_resource(void) {
|
|||||||
### 3. Events
|
### 3. Events
|
||||||
|
|
||||||
Events provide signaling mechanisms for thread coordination and notification.
|
Events provide signaling mechanisms for thread coordination and notification.
|
||||||
|
See [`event.h`](../kernel/include/kernel/event.h) implementation details.
|
||||||
|
|
||||||
#### Structure
|
#### Structure
|
||||||
|
|
||||||
@@ -227,6 +229,7 @@ void clear_ready(void) {
|
|||||||
### 4. Ports
|
### 4. Ports
|
||||||
|
|
||||||
Ports provide message-passing communication channels between threads with buffering.
|
Ports provide message-passing communication channels between threads with buffering.
|
||||||
|
See [`port.h`](../kernel/include/kernel/port.h) implementation details.
|
||||||
|
|
||||||
#### Structure
|
#### Structure
|
||||||
|
|
||||||
@@ -318,6 +321,7 @@ void consumer_thread(void *arg) {
|
|||||||
### 5. Spinlocks
|
### 5. Spinlocks
|
||||||
|
|
||||||
Spinlocks provide lightweight mutual exclusion for short critical sections.
|
Spinlocks provide lightweight mutual exclusion for short critical sections.
|
||||||
|
See [`spinlock.h`](../kernel/include/kernel/spinlock.h) implementation details.
|
||||||
|
|
||||||
#### Structure
|
#### Structure
|
||||||
|
|
||||||
@@ -345,7 +349,8 @@ int spin_trylock(spin_lock_t *lock); // Non-blocking attempt
|
|||||||
void spin_unlock(spin_lock_t *lock);
|
void spin_unlock(spin_lock_t *lock);
|
||||||
bool spin_lock_held(spin_lock_t *lock);
|
bool spin_lock_held(spin_lock_t *lock);
|
||||||
|
|
||||||
// IRQ-safe variants
|
// Wrapper functions that disable and restore interrupts, saving interrupt state
|
||||||
|
// into 'state'.
|
||||||
void spin_lock_irqsave(spin_lock_t *lock, spin_lock_saved_state_t *state);
|
void spin_lock_irqsave(spin_lock_t *lock, spin_lock_saved_state_t *state);
|
||||||
void spin_unlock_irqrestore(spin_lock_t *lock, spin_lock_saved_state_t state);
|
void spin_unlock_irqrestore(spin_lock_t *lock, spin_lock_saved_state_t state);
|
||||||
```
|
```
|
||||||
@@ -399,6 +404,7 @@ public:
|
|||||||
### Wait Queues
|
### Wait Queues
|
||||||
|
|
||||||
The foundation primitive underlying all blocking synchronization:
|
The foundation primitive underlying all blocking synchronization:
|
||||||
|
See [`wait.h`](../kernel/include/kernel/wait.h) implementation details.
|
||||||
|
|
||||||
#### API
|
#### API
|
||||||
|
|
||||||
@@ -419,11 +425,7 @@ status_t thread_unblock_from_wait_queue(thread_t *t, status_t error);
|
|||||||
|
|
||||||
### Priority Inheritance
|
### Priority Inheritance
|
||||||
|
|
||||||
While not explicitly implemented, the LK synchronization primitives provide implicit priority inheritance through the wait queue mechanism:
|
The wait queues provide no mechanism to handle priority inversion at this time. All threads are woken in FIFO order.
|
||||||
|
|
||||||
- **FIFO ordering**: Threads are generally woken in the order they were blocked
|
|
||||||
- **Priority-based scheduling**: High-priority threads are scheduled immediately when unblocked
|
|
||||||
- **Head insertion**: Newly unblocked threads are inserted at the head of their priority run queue
|
|
||||||
|
|
||||||
### Error Handling
|
### Error Handling
|
||||||
|
|
||||||
@@ -453,12 +455,12 @@ Debug builds include assertions that will panic on:
|
|||||||
When threads are unblocked, the scheduler automatically handles CPU wakeup:
|
When threads are unblocked, the scheduler automatically handles CPU wakeup:
|
||||||
|
|
||||||
- **Pinned threads**: Wake the specific CPU where the thread is pinned
|
- **Pinned threads**: Wake the specific CPU where the thread is pinned
|
||||||
- **Unpinned threads**: Wake all CPUs except the local one
|
- **Unpinned threads**: Find a CPU to run the thread on and wake it up
|
||||||
- **Load balancing**: Distribution across available CPUs
|
- **Load balancing**: Distribution across available CPUs
|
||||||
|
|
||||||
#### Memory Ordering
|
#### Memory Ordering
|
||||||
|
|
||||||
- **Architecture barriers**: Spinlocks include appropriate memory barriers
|
- **Architecture barriers**: All primitives include appropriate memory barriers
|
||||||
- **Cache coherency**: Hardware ensures cache coherence for shared data
|
- **Cache coherency**: Hardware ensures cache coherence for shared data
|
||||||
- **Atomic operations**: Underlying atomic primitives ensure consistency
|
- **Atomic operations**: Underlying atomic primitives ensure consistency
|
||||||
|
|
||||||
@@ -468,7 +470,7 @@ When threads are unblocked, the scheduler automatically handles CPU wakeup:
|
|||||||
|
|
||||||
1. **Mutexes**: For exclusive access to shared resources with ownership
|
1. **Mutexes**: For exclusive access to shared resources with ownership
|
||||||
2. **Semaphores**: For counting resources or limiting concurrency
|
2. **Semaphores**: For counting resources or limiting concurrency
|
||||||
3. **Events**: For signaling and notification between threads
|
3. **Events**: For signaling and notification between threads and from IRQ context
|
||||||
4. **Ports**: For message passing and producer-consumer patterns
|
4. **Ports**: For message passing and producer-consumer patterns
|
||||||
5. **Spinlocks**: For very short critical sections or interrupt contexts
|
5. **Spinlocks**: For very short critical sections or interrupt contexts
|
||||||
|
|
||||||
@@ -605,5 +607,3 @@ All blocking primitives (except spinlocks) require:
|
|||||||
- **Dynamic allocation**: Runtime initialization for dynamically allocated primitives
|
- **Dynamic allocation**: Runtime initialization for dynamically allocated primitives
|
||||||
- **Cleanup requirements**: Proper destruction prevents resource leaks
|
- **Cleanup requirements**: Proper destruction prevents resource leaks
|
||||||
- **Magic number validation**: Debug builds validate primitive integrity
|
- **Magic number validation**: Debug builds validate primitive integrity
|
||||||
|
|
||||||
This comprehensive set of blocking primitives provides the foundation for safe, efficient multi-threaded programming in the LK kernel, supporting everything from simple mutual exclusion to complex communication patterns.
|
|
||||||
|
|||||||
Reference in New Issue
Block a user