[kernel] Re-design thread blocking

In preparation for the new mailbox IPC model, blocking threads needed an
overhaul. The `wait_on_*` and `wake_on_*` methods are gone, and the
`block()` and `wake()` calls on threads now pass a value between the
waker and the blocked thread.

As part of this change, the concept of signals on the base kobject class
was removed, along with the queue of blocked threads waiting on any
given object. Signals are now exclusively the domain of the event object
type, and the new wait_queue utility class helps manage waiting threads
when an object does actually need this functionality. In some cases (eg,
logger) an event object is used instead of the lower-level wait_queue.

Since this change has a lot of ramifications, this large commit includes
the following additional changes:

- The j6_object_wait, j6_object_wait_many, and j6_thread_pause syscalls
  have been removed.
- The j6_event_clear syscall has been removed - events are "cleared" by
  reading them now. A new j6_event_wait syscall has been added to read
  events.
- The generic close() method on kobject has been removed.
- The on_no_handles() method on kobject now deletes the object by
  default, and needs to be overridden by classes that should not be.
- The j6_system_bind_irq syscall now takes an event handle, as well as a
  signal that the IRQ should set on the event. IRQs will cause a waiting
  thread to be woken with the appropriate bit set.
- Threads waking due to timeout is simplified to just having a
  wake_timeout() accessor that returns a timestamp.
- The new wait_queue uses util::deque, which caused the disovery of two
  bugs in the deque implementation: empty deques could still have a
  single array allocated and thus return true for empty(), and new
  arrays getting allocated were not being zeroed first.
- Exposed a new erase() method on util::map that takes a node pointer
  instead of a key, skipping lookup.
This commit is contained in:
Justin C. Miller
2022-02-21 19:16:20 -08:00
parent f93d80b8d2
commit f7ae2e2220
40 changed files with 419 additions and 628 deletions

View File

@@ -3,18 +3,20 @@ object event : object {
capabilities [
signal
wait
]
method create [constructor]
# Assert signals on the event from the given bitset
# Signal events on this object
method signal [cap:signal] {
param signals uint64
param signals uint64 # A bitset of which events to signal
}
# De-assert signals on the event from the given bitset
method clear [cap:signal] {
param mask uint64
# Wait for signaled events on this object
method wait [cap:wait] {
param signals uint64 [out] # A bitset of which events were signaled
param timeout uint64 # Wait timeout in nanoseconds
}
}

View File

@@ -11,20 +11,4 @@ object object [virtual] {
method koid {
param koid uint64 [out]
}
# Block the current thread waiting for an object to assert
# one of a set of signals
method wait {
param mask uint64 # Bitmap of which signals to wait for
param signals uint64 [out] # Returns the state of the signals
}
# Block the current thread waiting for an one of multiple
# objects to assert one of a set of signals
method wait_many [static] {
param handles ref object [list] # The objects to wait on
param mask uint64 # Bitmap of which signals to wait for
param handle ref object [out] # Returns the object that signalled
param signals uint64 [out] # Returns the state of the signals
}
}

View File

@@ -21,8 +21,9 @@ object system : object {
# Ask the kernel to send this process messages whenever
# the given IRQ fires
method bind_irq [cap:bind_irq] {
param dest ref endpoint # Endpoint that will receive messages
param dest ref event # Event object that will receive messages
param irq uint # IRQ number to bind
param signal uint # Signal number on the event to bind to
}
# Create a VMA and map an area of physical memory into it,

View File

@@ -17,7 +17,6 @@ object thread : object {
param status int32
}
method pause [static]
method sleep [static] {
param until uint64
}