PatchworkOS  da8a090
A non-POSIX operating system.
Loading...
Searching...
No Matches
Waiting subsystem

Wait queue implementation. More...

Collaboration diagram for Waiting subsystem:

Detailed Description

Wait queue implementation.

The waiting subsystem provides threads with the ability to suspend their execution until a certain condition is met and/or a timeout occurs.

The common usage pattern is to call WAIT_BLOCK() to check for a specified condition, when that condition is modified the subsystem utilizing the wait queue is expected to call wait_unblock() to wake up a specified number of waiting threads, causing them to re-evaluate the condition. If the condition is still not met the thread will go back to sleep, otherwise it will continue executing.

Note
Generally its preferred to use the WAIT_BLOCK* macros instead of directly calling the functions provided by this subsystem.

Data Structures

struct  wait_entry_t
 Represents a thread waiting on a wait queue. More...
 
struct  wait_queue_t
 The primitive that threads block on. More...
 
struct  wait_client_t
 Represents a thread in the waiting subsystem. More...
 
struct  wait_t
 Represents one instance of the waiting subsystem for a CPU. More...
 

Macros

#define WAIT_ALL   UINT64_MAX
 Used to indicate that the wait should unblock all waiting threads.
 
#define WAIT_BLOCK(queue, condition)
 Blocks until the condition is true, will test the condition on every wakeup.
 
#define WAIT_BLOCK_TIMEOUT(queue, condition, timeout)
 Blocks until the condition is true, condition will be tested on every wakeup. Reaching the timeout will always unblock.
 
#define WAIT_BLOCK_LOCK(queue, lock, condition)
 Blocks until the condition is true, condition will be tested on every wakeup. Will release the lock before blocking and acquire it again after waking up.
 
#define WAIT_BLOCK_LOCK_TIMEOUT(queue, lock, condition, timeout)
 Blocks until the condition is true, condition will be tested on every wakeup. Will release the lock before blocking and acquire it again after waking up. Reaching the timeout will always unblock.
 
#define WAIT_QUEUE_CREATE(name)   {.lock = LOCK_CREATE(), .entries = LIST_CREATE(name.entries)}
 Create a wait queue initializer.
 

Functions

void wait_queue_init (wait_queue_t *queue)
 Initialize wait queue.
 
void wait_queue_deinit (wait_queue_t *queue)
 Deinitialize wait queue.
 
void wait_client_init (wait_client_t *client)
 Initialize a threads wait client.
 
void wait_init (wait_t *wait)
 Initialize an instance of the waiting subsystem.
 
void wait_check_timeouts (interrupt_frame_t *frame, cpu_t *self)
 Check for timeouts and unblock threads as needed.
 
uint64_t wait_block_prepare (wait_queue_t **waitQueues, uint64_t amount, clock_t timeout)
 Prepare to block the currently running thread.
 
void wait_block_cancel (void)
 Cancels blocking of the currently running thread.
 
uint64_t wait_block_commit (void)
 Block the currently running thread.
 
bool wait_block_finalize (interrupt_frame_t *frame, cpu_t *self, thread_t *thread, clock_t uptime)
 Finalize blocking of a thread.
 
void wait_unblock_thread (thread_t *thread, errno_t err)
 Unblock a specific thread.
 
uint64_t wait_unblock (wait_queue_t *queue, uint64_t amount, errno_t err)
 Unblock threads waiting on a wait queue.
 

Macro Definition Documentation

◆ WAIT_ALL

#define WAIT_ALL   UINT64_MAX

Used to indicate that the wait should unblock all waiting threads.

Definition at line 40 of file wait.h.

◆ WAIT_BLOCK

#define WAIT_BLOCK (   queue,
  condition 
)
Value:
({ \
uint64_t result = 0; \
while (!(condition) && result == 0) \
{ \
wait_queue_t* temp = queue; \
if (wait_block_prepare(&temp, 1, CLOCKS_NEVER) == ERR) \
{ \
result = ERR; \
break; \
} \
result = wait_block_commit(); \
} \
result; \
})
#define CLOCKS_NEVER
Definition clock_t.h:16
uint64_t wait_block_prepare(wait_queue_t **waitQueues, uint64_t amount, clock_t timeout)
Prepare to block the currently running thread.
Definition wait.c:103
uint64_t wait_block_commit(void)
Block the currently running thread.
Definition wait.c:199
#define ERR
Integer error value.
Definition ERR.h:17
#define RFLAGS_INTERRUPT_ENABLE
Definition regs.h:32
static uint64_t rflags_read()
Definition regs.h:78
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
The primitive that threads block on.
Definition wait.h:182

Blocks until the condition is true, will test the condition on every wakeup.

Returns
On success, 0. On error, ERR and errno is set to:

Definition at line 48 of file wait.h.

◆ WAIT_BLOCK_TIMEOUT

#define WAIT_BLOCK_TIMEOUT (   queue,
  condition,
  timeout 
)
Value:
({ \
uint64_t result = 0; \
clock_t deadline = CLOCKS_DEADLINE(timeout, uptime); \
while (!(condition) && result == 0) \
{ \
if (deadline <= uptime) \
{ \
result = ERR; \
break; \
} \
clock_t remaining = CLOCKS_REMAINING(deadline, uptime); \
wait_queue_t* temp = queue; \
if (wait_block_prepare(&temp, 1, remaining) == ERR) \
{ \
result = ERR; \
break; \
} \
result = wait_block_commit(); \
} \
result; \
})
clock_t sys_time_uptime(void)
Time since boot.
Definition sys_time.c:99
#define ETIMEDOUT
Connection timed out.
Definition errno.h:577
#define errno
Error number variable.
Definition errno.h:27
clock_t uptime(void)
System call for retreving the time since boot.
Definition uptime.c:6
#define CLOCKS_REMAINING(deadline, uptime)
Safely calculate remaining time until deadline.
Definition clock_t.h:28
#define CLOCKS_DEADLINE(timeout, uptime)
Safely calculate deadline from timeout.
Definition clock_t.h:45
__UINT64_TYPE__ clock_t
A nanosecond time.
Definition clock_t.h:13

Blocks until the condition is true, condition will be tested on every wakeup. Reaching the timeout will always unblock.

Returns
On success, 0. On error, ERR and errno is set to:

Definition at line 72 of file wait.h.

◆ WAIT_BLOCK_LOCK

#define WAIT_BLOCK_LOCK (   queue,
  lock,
  condition 
)
Value:
({ \
uint64_t result = 0; \
while (!(condition) && result == 0) \
{ \
wait_queue_t* temp = queue; \
if (wait_block_prepare(&temp, 1, CLOCKS_NEVER) == ERR) \
{ \
result = ERR; \
break; \
} \
lock_release(lock); \
result = wait_block_commit(); \
lock_acquire(lock); \
} \
result; \
})
static lock_t lock
Definition io.c:13

Blocks until the condition is true, condition will be tested on every wakeup. Will release the lock before blocking and acquire it again after waking up.

Returns
On success, 0. On error, ERR and errno is set to:

Definition at line 106 of file wait.h.

◆ WAIT_BLOCK_LOCK_TIMEOUT

#define WAIT_BLOCK_LOCK_TIMEOUT (   queue,
  lock,
  condition,
  timeout 
)
Value:
({ \
uint64_t result = 0; \
clock_t deadline = CLOCKS_DEADLINE(timeout, uptime); \
while (!(condition) && result == ERR) \
{ \
if (deadline <= uptime) \
{ \
result = ERR; \
break; \
} \
clock_t remaining = CLOCKS_REMAINING(deadline, uptime); \
wait_queue_t* temp = queue; \
if (wait_block_prepare(&temp, 1, remaining) == ERR) \
{ \
result = ERR; \
break; \
} \
lock_release(lock); \
result = wait_block_commit(); \
lock_acquire(lock); \
} \
result; \
})

Blocks until the condition is true, condition will be tested on every wakeup. Will release the lock before blocking and acquire it again after waking up. Reaching the timeout will always unblock.

Returns
On success, 0. On error, ERR and errno is set to:

Definition at line 133 of file wait.h.

◆ WAIT_QUEUE_CREATE

#define WAIT_QUEUE_CREATE (   name)    {.lock = LOCK_CREATE(), .entries = LIST_CREATE(name.entries)}

Create a wait queue initializer.

Parameters
nameThe name of the wait queue variable.
Returns
The wait queue initializer.

Definition at line 219 of file wait.h.

Function Documentation

◆ wait_queue_init()

void wait_queue_init ( wait_queue_t queue)

Initialize wait queue.

Parameters
queueThe wait queue to initialize.

Definition at line 38 of file wait.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ wait_queue_deinit()

void wait_queue_deinit ( wait_queue_t queue)

Deinitialize wait queue.

Parameters
queueThe wait queue to deinitialize.

Definition at line 44 of file wait.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ wait_client_init()

void wait_client_init ( wait_client_t client)

Initialize a threads wait client.

Parameters
clientThe wait client to initialize.

Definition at line 54 of file wait.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ wait_init()

void wait_init ( wait_t wait)

Initialize an instance of the waiting subsystem.

Parameters
waitThe instance to initialize.

Definition at line 63 of file wait.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ wait_check_timeouts()

void wait_check_timeouts ( interrupt_frame_t frame,
cpu_t self 
)

Check for timeouts and unblock threads as needed.

Will be called by the interrupt_handler().

Parameters
frameThe interrupt frame.
selfThe current CPU.

Definition at line 69 of file wait.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ wait_block_prepare()

uint64_t wait_block_prepare ( wait_queue_t **  waitQueues,
uint64_t  amount,
clock_t  timeout 
)

Prepare to block the currently running thread.

Needed to handle race conditions when a thread is unblocked prematurely. The following sequence is used:

  • Call wait_block_prepare() to add the currently running thread to the provided wait queues and disable interrupts.
  • Check if the condition to block is still valid.
  • (The condition might change here, thus causing a race condition, leading to premature unblocking.)
  • If the condition was evaluated as not valid, call wait_block_cancel().
  • If the condition was evaluated as valid, call wait_block_commit() to block the thread. If the thread was unblocked prematurely this function will return immediately.

Will reenable interrupts on failure.

Parameters
waitQueuesArray of wait queues to add the thread to.
amountNumber of wait queues to add the thread to.
timeoutTimeout.
Returns
On success, 0. On failure, returns ERR and errno is set to:
  • EINVAL: Invalid arguments.
  • ENOMEM: Out of memory.

Definition at line 103 of file wait.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ wait_block_cancel()

void wait_block_cancel ( void  )

Cancels blocking of the currently running thread.

Should be called after wait_block_prepare() has been called if the condition to block is no longer valid.

Will reenable interrupts.

Definition at line 178 of file wait.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ wait_block_commit()

uint64_t wait_block_commit ( void  )

Block the currently running thread.

Should be called after wait_block_prepare(). If the thread was unblocked prematurely this function will return immediately.

Will reenable interrupts.

Returns
On success, 0. On failure, ERR and errno is set to:
  • ETIMEDOUT: The thread timed out.
  • EINTR: The thread was interrupted by a note.
  • Other error codes as set by the subsystem utilizing the wait queue.

Definition at line 199 of file wait.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ wait_block_finalize()

bool wait_block_finalize ( interrupt_frame_t frame,
cpu_t self,
thread_t thread,
clock_t  uptime 
)

Finalize blocking of a thread.

When wait_block_commit() is called the scheduler will be invoked, the scheduler will then call this function to finalize the blocking of the thread.

Its possible that during the gap between wait_block_commit() and this function being called the thread was prematurely unblocked, in that case this function will return false and the scheduler will resume the thread immediately.

Parameters
frameThe interrupt frame.
selfThe CPU the thread is being blocked on.
threadThe thread to block.
uptimeThe current uptime.
Returns
true if the thread was blocked, false if the thread was prematurely unblocked.

Definition at line 231 of file wait.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ wait_unblock_thread()

void wait_unblock_thread ( thread_t thread,
errno_t  err 
)

Unblock a specific thread.

Unblocks the provided thread, removing it from all wait queues it is waiting on.

The thread must be in the THREAD_UNBLOCKING state when this function is called.

Parameters
threadThe thread to unblock.
errThe errno value to set for the thread or EOK for no error.

Definition at line 284 of file wait.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ wait_unblock()

uint64_t wait_unblock ( wait_queue_t queue,
uint64_t  amount,
errno_t  err 
)

Unblock threads waiting on a wait queue.

Parameters
queueThe wait queue to unblock threads from.
amountThe number of threads to unblock or WAIT_ALL to unblock all threads.
errThe errno value to set for the unblocked threads or EOK for no error.
Returns
The number of threads that were unblocked.

Definition at line 296 of file wait.c.

Here is the call graph for this function:
Here is the caller graph for this function: