diff --git a/definitions/objects/event.def b/definitions/objects/event.def index 02b1cc8..85e5f5c 100644 --- a/definitions/objects/event.def +++ b/definitions/objects/event.def @@ -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 } } diff --git a/definitions/objects/object.def b/definitions/objects/object.def index 923f3d9..7b8eb3c 100644 --- a/definitions/objects/object.def +++ b/definitions/objects/object.def @@ -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 - } } diff --git a/definitions/objects/system.def b/definitions/objects/system.def index 33f716b..88fb9e3 100644 --- a/definitions/objects/system.def +++ b/definitions/objects/system.def @@ -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, diff --git a/definitions/objects/thread.def b/definitions/objects/thread.def index 418fb25..4e30a60 100644 --- a/definitions/objects/thread.def +++ b/definitions/objects/thread.def @@ -17,7 +17,6 @@ object thread : object { param status int32 } - method pause [static] method sleep [static] { param until uint64 } diff --git a/src/kernel/device_manager.cpp b/src/kernel/device_manager.cpp index ae52711..a0a35da 100644 --- a/src/kernel/device_manager.cpp +++ b/src/kernel/device_manager.cpp @@ -12,10 +12,10 @@ #include "interrupts.h" #include "logger.h" #include "memory.h" -#include "objects/endpoint.h" +#include "objects/event.h" -static obj::endpoint * const ignore_endpoint = reinterpret_cast(-1ull); +static obj::event * const ignore_event = reinterpret_cast(-1ull); static const char expected_signature[] = "RSD PTR "; @@ -58,9 +58,9 @@ device_manager::device_manager() : m_irqs.ensure_capacity(32); m_irqs.set_size(16); for (int i = 0; i < 16; ++i) - m_irqs[i] = nullptr; + m_irqs[i] = {nullptr, 0}; - m_irqs[2] = ignore_endpoint; + m_irqs[2] = {ignore_event, 0}; } template static const T * @@ -381,32 +381,32 @@ device_manager::dispatch_irq(unsigned irq) if (irq >= m_irqs.count()) return false; - obj::endpoint *e = m_irqs[irq]; - if (!e || e == ignore_endpoint) - return e == ignore_endpoint; + irq_binding &binding = m_irqs[irq]; + if (!binding.target || binding.target == ignore_event) + return binding.target == ignore_event; - e->signal_irq(irq); + binding.target->signal(1 << binding.signal); return true; } bool -device_manager::bind_irq(unsigned irq, obj::endpoint *target) +device_manager::bind_irq(unsigned irq, obj::event *target, unsigned signal) { // TODO: grow if under max size if (irq >= m_irqs.count()) return false; - m_irqs[irq]= target; + m_irqs[irq] = {target, signal}; return true; } void -device_manager::unbind_irqs(obj::endpoint *target) +device_manager::unbind_irqs(obj::event *target) { const size_t count = m_irqs.count(); for (size_t i = 0; i < count; ++i) { - if (m_irqs[i] == target) - m_irqs[i] = nullptr; + if (m_irqs[i].target == target) + m_irqs[i] = {nullptr, 0}; } } diff --git a/src/kernel/device_manager.h b/src/kernel/device_manager.h index c6c6778..b960a52 100644 --- a/src/kernel/device_manager.h +++ b/src/kernel/device_manager.h @@ -12,7 +12,7 @@ struct acpi_table_header; class block_device; namespace obj { - class endpoint; + class event; } using irq_callback = void (*)(void *); @@ -45,12 +45,13 @@ public: /// Bind an IRQ to an endpoint /// \arg irq The IRQ number to bind /// \arg target The endpoint to recieve messages when the IRQ is signalled + /// \arg signal The event's signal number to bind to /// \returns True on success - bool bind_irq(unsigned irq, obj::endpoint *target); + bool bind_irq(unsigned irq, obj::event *target, unsigned signal); /// Remove IRQ bindings for an endpoint /// \arg target The endpoint to remove - void unbind_irqs(obj::endpoint *target); + void unbind_irqs(obj::event *target); /// Allocate an MSI IRQ for a device /// \arg name Name of the interrupt, for display to user @@ -164,7 +165,12 @@ private: util::vector m_pci; util::vector m_devices; - util::vector m_irqs; + struct irq_binding + { + obj::event *target = nullptr; + unsigned signal = 0; + }; + util::vector m_irqs; util::vector m_blockdevs; diff --git a/src/kernel/kernel.module b/src/kernel/kernel.module index d02f113..b6cb680 100644 --- a/src/kernel/kernel.module +++ b/src/kernel/kernel.module @@ -33,6 +33,7 @@ kernel = module("kernel", "msr.cpp", "objects/channel.cpp", "objects/endpoint.cpp", + "objects/event.cpp", "objects/kobject.cpp", "objects/thread.cpp", "objects/process.cpp", @@ -64,6 +65,7 @@ kernel = module("kernel", "task.s", "tss.cpp", "vm_space.cpp", + "wait_queue.cpp", ]) from glob import glob diff --git a/src/kernel/logger.cpp b/src/kernel/logger.cpp index 1b3d916..9c6bc70 100644 --- a/src/kernel/logger.cpp +++ b/src/kernel/logger.cpp @@ -7,6 +7,7 @@ #include "logger.h" #include "memory.h" #include "objects/system.h" +#include "objects/thread.h" #include "printf/printf.h" static uint8_t log_buffer[128 * 1024]; @@ -87,13 +88,14 @@ logger::output(level severity, logs area, const char *fmt, va_list args) memcpy(out, buffer, n); m_buffer.commit(n); - obj::system &sys = obj::system::get(); - sys.assert_signal(j6_signal_system_has_log); + m_event.signal(1); } size_t logger::get_entry(void *buffer, size_t size) { + m_event.wait(); + util::scoped_lock lock {m_lock}; void *out; diff --git a/src/kernel/logger.h b/src/kernel/logger.h index f7466f5..4f22c70 100644 --- a/src/kernel/logger.h +++ b/src/kernel/logger.h @@ -8,6 +8,8 @@ #include #include +#include "objects/event.h" + enum class logs : uint8_t { #define LOG(name, lvl) name, #include @@ -107,6 +109,8 @@ private: return m_levels[static_cast(area)]; } + obj::event m_event; + level m_levels[areas_count]; immediate_cb m_immediate; diff --git a/src/kernel/main.cpp b/src/kernel/main.cpp index 7755d1b..23a108f 100644 --- a/src/kernel/main.cpp +++ b/src/kernel/main.cpp @@ -3,7 +3,6 @@ #include #include -#include #include #include "assert.h" diff --git a/src/kernel/objects/channel.cpp b/src/kernel/objects/channel.cpp index 1cb2613..71b3bc4 100644 --- a/src/kernel/objects/channel.cpp +++ b/src/kernel/objects/channel.cpp @@ -15,7 +15,7 @@ channel::channel() : m_len(0), m_data(g_kernel_buffers.get_section()), m_buffer(reinterpret_cast(m_data), buffer_bytes), - kobject(kobject::type::channel, j6_signal_channel_can_send) + kobject(kobject::type::channel) { } @@ -41,10 +41,10 @@ channel::enqueue(const util::buffer &data) m_buffer.commit(len); if (len) - assert_signal(j6_signal_channel_can_recv); + m_can_recv = true; if (m_buffer.free_space() == 0) - deassert_signal(j6_signal_channel_can_send); + m_can_send = false; return len; } @@ -64,10 +64,10 @@ channel::dequeue(util::buffer buffer) m_buffer.consume(len); if (len) - assert_signal(j6_signal_channel_can_send); + m_can_send = true; if (m_buffer.size() == 0) - deassert_signal(j6_signal_channel_can_recv); + m_can_recv = false; return len; } @@ -76,16 +76,8 @@ void channel::close() { util::scoped_lock lock {m_close_lock}; - - kobject::close(); g_kernel_buffers.return_section(m_data); -} - -void -channel::on_no_handles() -{ - kobject::on_no_handles(); - delete this; + m_closed = true; } } // namespace obj diff --git a/src/kernel/objects/channel.h b/src/kernel/objects/channel.h index 09d70a2..8d286f7 100644 --- a/src/kernel/objects/channel.h +++ b/src/kernel/objects/channel.h @@ -3,7 +3,6 @@ /// Definition of channel objects and related functions #include -#include #include #include #include @@ -26,10 +25,10 @@ public: static constexpr kobject::type type = kobject::type::channel; /// Check if the channel has space for a message to be sent - inline bool can_send() const { return check_signal(j6_signal_channel_can_send); } + inline bool can_send() const { return m_can_send; } /// Check if the channel has a message wiating already - inline bool can_receive() const { return check_signal(j6_signal_channel_can_recv); } + inline bool can_receive() const { return m_can_recv; } /// Put a message into the channel /// \arg data Buffer of data to write @@ -43,14 +42,17 @@ public: /// Mark this channel as closed, all future calls to enqueue or /// dequeue messages will fail with j6_status_closed. - virtual void close() override; + void close(); -protected: - virtual void on_no_handles() override; + /// Check if this channel has been closed. + inline bool closed() const { return m_closed; } private: size_t m_len; uintptr_t m_data; + bool m_closed; + bool m_can_send; + bool m_can_recv; util::bip_buffer m_buffer; util::spinlock m_close_lock; }; diff --git a/src/kernel/objects/event.cpp b/src/kernel/objects/event.cpp new file mode 100644 index 0000000..6a975b9 --- /dev/null +++ b/src/kernel/objects/event.cpp @@ -0,0 +1,48 @@ +#include "objects/event.h" +#include "objects/thread.h" + +namespace obj { + +event::event() : + kobject {type::event}, + m_signals {0} +{} + +event::~event() {} + +void +event::signal(uint64_t s) +{ + uint64_t after = __atomic_or_fetch(&m_signals, s, __ATOMIC_SEQ_CST); + if (after) wake_observer(); +} + +uint64_t +event::wait() +{ + // If events are pending, grab those and return immediately + uint64_t value = read(); + if (value) + return value; + + // Wait for event::signal() to wake us with a value + thread ¤t = thread::current(); + m_queue.add_thread(¤t); + return current.block(); +} + +void +event::wake_observer() +{ + util::scoped_lock lock {m_queue.get_lock()}; + thread *t = m_queue.get_next_unlocked(); + if (!t) return; + + uint64_t value = read(); + if (value) { + m_queue.pop_next_unlocked(); + t->wake(value); + } +} + +} // namespace obj diff --git a/src/kernel/objects/event.h b/src/kernel/objects/event.h index 584e3cc..26becad 100644 --- a/src/kernel/objects/event.h +++ b/src/kernel/objects/event.h @@ -2,21 +2,48 @@ /// \file event.h /// Definition of event kobject types +#include +#include + #include "objects/kobject.h" +#include "wait_queue.h" namespace obj { +class thread; + class event : public kobject { public: /// Capabilities on a newly constructed event handle - constexpr static j6_cap_t creation_caps = 0; - - event() : - kobject(type::event) {} - + constexpr static j6_cap_t creation_caps = j6_cap_event_all; static constexpr kobject::type type = kobject::type::event; + + event(); + ~event(); + + /// Signal the given event(s). + /// \arg s The events to signal, as a bitset + void signal(uint64_t s); + + /// Wait for events to be signalled. If events have already + /// been signaled since the last call to wait, return them + /// immediately. + /// \returns The events which have been signalled, as a bitset + uint64_t wait(); + +private: + /// Read and consume the current signaled events + inline uint64_t read() { + return __atomic_exchange_n(&m_signals, 0, __ATOMIC_SEQ_CST); + } + + /// Wake an observer to handle an incoming event + void wake_observer(); + + uint64_t m_signals; + wait_queue m_queue; }; } // namespace obj diff --git a/src/kernel/objects/kobject.cpp b/src/kernel/objects/kobject.cpp index fe7970a..8b2adb5 100644 --- a/src/kernel/objects/kobject.cpp +++ b/src/kernel/objects/kobject.cpp @@ -1,5 +1,4 @@ #include -#include #include #include "assert.h" @@ -10,17 +9,12 @@ namespace obj { static j6_koid_t next_koids [static_cast(kobject::type::max)] = { 0 }; -kobject::kobject(type t, j6_signal_t signals) : +kobject::kobject(type t) : m_koid(koid_generate(t)), - m_signals(signals), m_handle_count(0) {} -kobject::~kobject() -{ - for (auto *t : m_blocked_threads) - t->wake_on_result(this, j6_status_destroyed); -} +kobject::~kobject() {} j6_koid_t kobject::koid_generate(type t) @@ -37,81 +31,10 @@ kobject::koid_type(j6_koid_t koid) return static_cast((koid >> 48) & 0xffffull); } -j6_signal_t -kobject::assert_signal(j6_signal_t s) -{ - j6_signal_t old = - __atomic_fetch_or(&m_signals, s, __ATOMIC_SEQ_CST); - notify_signal_observers(); - return old; -} - -j6_signal_t -kobject::deassert_signal(j6_signal_t s) -{ - return __atomic_fetch_and(&m_signals, ~s, __ATOMIC_SEQ_CST); -} - -void -kobject::compact_blocked_threads() -{ - // Clean up what we can of the list - while (!m_blocked_threads.empty() && !m_blocked_threads.first()) - m_blocked_threads.pop_front(); - while (!m_blocked_threads.empty() && !m_blocked_threads.last()) - m_blocked_threads.pop_back(); -} - -void -kobject::notify_signal_observers() -{ - for (auto &entry : m_blocked_threads) { - if (entry == nullptr) continue; - if (entry->wake_on_signals(this, m_signals)) - entry = nullptr; - } - compact_blocked_threads(); -} - -void -kobject::notify_object_observers(size_t count) -{ - if (!count) return; - - for (auto &entry : m_blocked_threads) { - if (entry == nullptr) continue; - if (entry->wake_on_object(this)) { - entry = nullptr; - if (--count) break; - } - } - compact_blocked_threads(); -} - -void -kobject::remove_blocked_thread(thread *t) -{ - // Can't really remove from a deque, so just - // null out removed entries. - for (auto &entry : m_blocked_threads) { - if (entry == t) { - entry = nullptr; - break; - } - } - compact_blocked_threads(); -} - -void -kobject::close() -{ - assert_signal(j6_signal_closed); -} - void kobject::on_no_handles() { - assert_signal(j6_signal_no_handles); + delete this; } } // namespace obj diff --git a/src/kernel/objects/kobject.h b/src/kernel/objects/kobject.h index b719619..58fa239 100644 --- a/src/kernel/objects/kobject.h +++ b/src/kernel/objects/kobject.h @@ -3,9 +3,7 @@ /// Definition of base type for user-interactable kernel objects #include -#include #include -#include namespace obj { @@ -25,7 +23,7 @@ public: max }; - kobject(type t, j6_signal_t signals = 0ull); + kobject(type t); virtual ~kobject(); /// Generate a new koid for a given type @@ -44,23 +42,6 @@ public: /// Get this object's koid inline j6_koid_t koid() const { return m_koid; } - /// Set the given signals active on this object - /// \arg s The set of signals to assert - /// \returns The previous state of the signals - j6_signal_t assert_signal(j6_signal_t s); - - /// Clear the given signals on this object - /// \arg s The set of signals to deassert - /// \returns The previous state of the signals - j6_signal_t deassert_signal(j6_signal_t s); - - /// Check if the given signals are set on this object - /// \arg s The set of signals to check - inline bool check_signal(j6_signal_t s) const { return (m_signals & s) == s; } - - /// Get the current object signal state - inline j6_signal_t signals() const { return m_signals; } - /// Increment the handle refcount inline void handle_retain() { ++m_handle_count; } @@ -69,45 +50,21 @@ public: if (--m_handle_count == 0) on_no_handles(); } - /// Add the given thread to the list of threads waiting on this object. - inline void add_blocked_thread(thread *t) { m_blocked_threads.push_back(t); } - - /// Remove the given thread from the list of threads waiting on this object. - void remove_blocked_thread(thread *t); - - /// Perform any cleanup actions necessary to mark this object closed - virtual void close(); - - /// Check if this object has been closed - inline bool closed() const { return check_signal(j6_signal_closed); } - protected: - /// Interface for subclasses to handle when all handles are closed. Subclasses - /// should either call the base version, or assert j6_signal_no_handles. + /// Interface for subclasses to handle when all handles are closed. + /// Default implementation deletes the object. virtual void on_no_handles(); + /// Get the current number of handles to this object + inline uint16_t handle_count() const { return m_handle_count; } + private: kobject() = delete; kobject(const kobject &other) = delete; kobject(const kobject &&other) = delete; - /// Notifiy observers of this object - /// \arg result The result to pass to the observers - void notify_signal_observers(); - - /// Compact the blocked threads deque - void compact_blocked_threads(); - j6_koid_t m_koid; - j6_signal_t m_signals; uint16_t m_handle_count; - -protected: - /// Notify threads waiting on this object - /// \arg count Number of observers to wake, or -1ull for all - void notify_object_observers(size_t count = -1ull); - - util::deque m_blocked_threads; }; } // namespace obj diff --git a/src/kernel/objects/process.cpp b/src/kernel/objects/process.cpp index 3f55842..31aa45a 100644 --- a/src/kernel/objects/process.cpp +++ b/src/kernel/objects/process.cpp @@ -53,7 +53,6 @@ process::exit(int32_t code) // TODO: make this thread-safe m_state = state::exited; m_return_code = code; - close(); for (auto *thread : m_threads) { thread->exit(code); diff --git a/src/kernel/objects/process.h b/src/kernel/objects/process.h index 89ad87e..2bae4da 100644 --- a/src/kernel/objects/process.h +++ b/src/kernel/objects/process.h @@ -103,6 +103,11 @@ public: /// \returns The kernel process object static process * create_kernel_process(page_table *pml4); +protected: + /// Don't delete a process on no handles, the scheduler takes + /// care of that. + virtual void on_no_handles() override {} + private: // This constructor is called by create_kernel_process process(page_table *kpml4); diff --git a/src/kernel/objects/thread.cpp b/src/kernel/objects/thread.cpp index d65acd3..7cf7161 100644 --- a/src/kernel/objects/thread.cpp +++ b/src/kernel/objects/thread.cpp @@ -1,4 +1,3 @@ -#include #include #include "cpu.h" @@ -15,15 +14,12 @@ extern obj::vm_area_guarded &g_kernel_stacks; namespace obj { -static constexpr j6_signal_t thread_default_signals = 0; - thread::thread(process &parent, uint8_t pri, uintptr_t rsp0) : - kobject(kobject::type::thread, thread_default_signals), - m_parent(parent), - m_state(state::none), - m_wait_type(wait_type::none), - m_wait_data(0), - m_wait_obj(0) + kobject {kobject::type::thread}, + m_parent {parent}, + m_state {state::none}, + m_wake_value {0}, + m_wake_timeout {0} { parent.space().initialize_tcb(m_tcb); m_tcb.priority = pri; @@ -45,129 +41,20 @@ thread::~thread() thread & thread::current() { return *current_cpu().thread; } -j6_status_t -thread::wait_on_signals(j6_signal_t signals) -{ - util::scoped_lock lock {m_wait_lock}; - - m_wait_type = wait_type::signal; - m_wait_data = signals; - - lock.release(); - block(); - - return m_wait_result; -} - -j6_status_t -thread::wait_on_time(uint64_t t) -{ - util::scoped_lock lock {m_wait_lock}; - - m_wait_type = wait_type::time; - m_wait_time = t; - - lock.release(); - block(); - - return m_wait_result; -} - -j6_status_t -thread::wait_on_object(void *o, uint64_t t) -{ - util::scoped_lock lock {m_wait_lock}; - - m_wait_type = wait_type::object; - m_wait_data = reinterpret_cast(o); - - if (t) { - m_wait_type |= wait_type::time; - m_wait_time = t; - } - - lock.release(); - block(); - return m_wait_result; -} - -bool -thread::wake_on_signals(kobject *obj, j6_signal_t signals) -{ - util::scoped_lock lock {m_wait_lock}; - - if (!(m_wait_type & wait_type::signal) || - (signals & m_wait_data) == 0) - return false; - - m_wait_type = wait_type::none; - m_wait_result = j6_status_ok; - m_wait_data = signals; - m_wait_obj = obj->koid(); - set_state(state::ready); - return true; -} - -bool -thread::wake_on_time(uint64_t now) -{ - util::scoped_lock lock {m_wait_lock}; - - if (!(m_wait_type & wait_type::time) || - now < m_wait_time) - return false; - - if (!(m_wait_type & ~wait_type::none)) - m_wait_result = j6_status_ok; - else - m_wait_result = j6_err_timed_out; - - m_wait_type = wait_type::none; - m_wait_data = now; - m_wait_obj = 0; - set_state(state::ready); - return true; -} - -bool -thread::wake_on_object(void *o, uint64_t id) -{ - util::scoped_lock lock {m_wait_lock}; - - if (!(m_wait_type & wait_type::object) || - reinterpret_cast(o) != m_wait_data) - return false; - - m_wait_type = wait_type::none; - m_wait_result = j6_status_ok; - m_wait_obj = id; - set_state(state::ready); - return true; -} - -void -thread::wake_on_result(kobject *obj, j6_status_t result) -{ - util::scoped_lock lock {m_wait_lock}; - - m_wait_type = wait_type::none; - m_wait_result = result; - m_wait_data = 0; - m_wait_obj = obj->koid(); - set_state(state::ready); -} - -void +uint64_t thread::block() { clear_state(state::ready); if (current_cpu().thread == this) scheduler::get().schedule(); + return m_wake_value; } void -thread::wake() +thread::wake(uint64_t value) { + m_wake_value = value; + m_wake_timeout = 0; set_state(state::ready); } @@ -175,8 +62,8 @@ void thread::exit(int32_t code) { m_return_code = code; + m_wake_timeout = 0; set_state(state::exited); - close(); block(); } diff --git a/src/kernel/objects/thread.h b/src/kernel/objects/thread.h index c0c3578..98b22df 100644 --- a/src/kernel/objects/thread.h +++ b/src/kernel/objects/thread.h @@ -29,14 +29,14 @@ struct TCB obj::thread* thread; uint8_t priority; + // note: 3 bytes padding - // TODO: move state into TCB? - uintptr_t kernel_stack; - uint32_t time_left; uint64_t last_ran; + + uintptr_t kernel_stack; }; using tcb_list = util::linked_list; @@ -90,6 +90,10 @@ public: /// \returns True if the thread has constant priority. inline bool constant() const { return has_state(state::constant); } + /// Get the `exited` state of the thread. + /// \returns True if the thread has exited. + inline bool exited() const { return has_state(state::exited); } + /// Get the thread priority. inline uint8_t priority() const { return m_tcb.priority; } @@ -97,58 +101,21 @@ public: /// \arg p The new thread priority inline void set_priority(uint8_t p) { if (!constant()) m_tcb.priority = p; } - /// Block the thread, waiting an object's signals. - /// \arg signals Mask of signals to wait for - /// \returns j6_status_ok on success - j6_status_t wait_on_signals(j6_signal_t signals); + /// Block this thread, waiting for a value + /// \returns The value passed to wake() + uint64_t block(); - /// Block the thread, waiting for a given clock value - /// \arg t Clock value to wait for - /// \returns j6_status_ok on success - j6_status_t wait_on_time(uint64_t t); + /// Wake this thread, giving it a value + /// \arg value The value that block() should return + void wake(uint64_t value = 0); - /// Block the thread, waiting on the given object - /// \arg o The object that should wake this thread - /// \arg t The timeout clock value to wait for - /// \returns j6_status_ok on success - j6_status_t wait_on_object(void *o, uint64_t t = 0); + /// Set a timeout to unblock this thread + /// \arg time The clock time at which to wake. 0 for no timeout. + inline void set_wake_timeout(uint64_t time) { m_wake_timeout = time; } - /// Wake the thread if it is waiting on signals. - /// \arg obj Object that changed signals - /// \arg signals Signal state of the object - /// \returns True if this action unblocked the thread - bool wake_on_signals(kobject *obj, j6_signal_t signals); - - /// Wake the thread if it is waiting on the clock. - /// \arg now Current clock value - /// \returns True if this action unblocked the thread - bool wake_on_time(uint64_t now); - - /// Wake the thread if it is waiting on the given object. - /// \arg o Object trying to wake the thread - /// \arg id Id of the object trying to wake the thread - /// \returns True if this action unblocked the thread - bool wake_on_object(void *o, uint64_t id = 0); - - /// Wake the thread with a given result code. - /// \arg obj Object that changed signals - /// \arg result Result code to return to the thread - void wake_on_result(kobject *obj, j6_status_t result); - - /// Get the result status code from the last blocking operation - j6_status_t get_wait_result() const { return m_wait_result; } - - /// Get the current blocking opreation's wait data - uint64_t get_wait_data() const { return m_wait_data; } - - /// Get the current blocking operation's wait ojbect (as a handle) - j6_koid_t get_wait_object() const { return m_wait_obj; } - - /// Primitive thread blocking, instead of using wait framework - void block(); - - /// Primitive thread unblocking, instead of using wait framework - void wake(); + /// Get the timeout at which to unblock this thread + /// \returns The clock time at which to wake. 0 for no timeout. + inline uint64_t wake_timeout() const { return m_wake_timeout; } inline bool has_state(state s) const { return static_cast(m_state) & static_cast(s); @@ -189,6 +156,11 @@ public: /// \arg rsp The existing stack for the idle thread static thread * create_idle_thread(process &kernel, uint8_t pri, uintptr_t rsp); +protected: + /// Don't delete a thread on no handles, the scheduler takes + /// care of that. + virtual void on_no_handles() override {} + private: thread() = delete; thread(const thread &other) = delete; @@ -210,16 +182,13 @@ private: thread *m_creator; state m_state; - wait_type m_wait_type; - // There should be 1 byte of padding here + + // There should be 3 bytes of padding here int32_t m_return_code; - uint64_t m_wait_data; - uint64_t m_wait_time; - j6_status_t m_wait_result; - uint64_t m_wait_obj; - util::spinlock m_wait_lock; + uint64_t m_wake_value; + uint64_t m_wake_timeout; j6_handle_t m_self_handle; }; diff --git a/src/kernel/objects/vm_area.cpp b/src/kernel/objects/vm_area.cpp index dfe48ec..85318fd 100644 --- a/src/kernel/objects/vm_area.cpp +++ b/src/kernel/objects/vm_area.cpp @@ -35,15 +35,13 @@ void vm_area::remove_from(vm_space *space) { m_spaces.remove_swap(space); - if (!m_spaces.count() && - check_signal(j6_signal_no_handles)) + if (!m_spaces.count() && !handle_count()) delete this; } void vm_area::on_no_handles() { - kobject::on_no_handles(); if (!m_spaces.count()) delete this; } diff --git a/src/kernel/objects/vm_area.h b/src/kernel/objects/vm_area.h index 585d746..12f4ee7 100644 --- a/src/kernel/objects/vm_area.h +++ b/src/kernel/objects/vm_area.h @@ -6,7 +6,6 @@ #include #include -#include #include #include @@ -76,7 +75,10 @@ public: virtual bool get_page(uintptr_t offset, uintptr_t &phys) = 0; protected: + /// A VMA is not deleted until both no handles remain AND it's not + /// mapped by any VM space. virtual void on_no_handles() override; + bool can_resize(size_t size); size_t m_size; diff --git a/src/kernel/scheduler.cpp b/src/kernel/scheduler.cpp index b7f1101..ea80db5 100644 --- a/src/kernel/scheduler.cpp +++ b/src/kernel/scheduler.cpp @@ -126,13 +126,15 @@ scheduler::prune(run_queue &queue, uint64_t now) thread *th = tcb->thread; uint8_t priority = tcb->priority; + uint64_t timeout = th->wake_timeout(); + if (timeout && timeout <= now) + th->wake(); + bool ready = th->has_state(thread::state::ready); bool exited = th->has_state(thread::state::exited); bool constant = th->has_state(thread::state::constant); bool current = tcb == queue.current; - ready |= th->wake_on_time(now); - auto *remove = tcb; tcb = tcb->next(); if (!exited && !ready) diff --git a/src/kernel/syscalls/event.cpp b/src/kernel/syscalls/event.cpp index 9a386b7..5a3b4d1 100644 --- a/src/kernel/syscalls/event.cpp +++ b/src/kernel/syscalls/event.cpp @@ -1,7 +1,8 @@ #include -#include +#include "clock.h" #include "objects/event.h" +#include "objects/thread.h" #include "syscalls/helpers.h" using namespace obj; @@ -18,17 +19,21 @@ event_create(j6_handle_t *self) j6_status_t event_signal(event *self, j6_signal_t signals) { - if (signals & j6_signal_global_mask) - return j6_err_invalid_arg; - - self->assert_signal(signals); + self->signal(signals); return j6_status_ok; } j6_status_t -event_clear(event *self, j6_signal_t mask) +event_wait(event *self, j6_signal_t *signals, uint64_t timeout) { - self->deassert_signal(~mask); + thread& t = thread::current(); + + if (timeout) { + timeout += clock::get().value(); + t.set_wake_timeout(timeout); + } + + *signals = self->wait(); return j6_status_ok; } diff --git a/src/kernel/syscalls/object.cpp b/src/kernel/syscalls/object.cpp index d4179ea..f838497 100644 --- a/src/kernel/syscalls/object.cpp +++ b/src/kernel/syscalls/object.cpp @@ -1,5 +1,4 @@ #include -#include #include #include @@ -19,81 +18,4 @@ object_koid(kobject *self, j6_koid_t *koid) return j6_status_ok; } -j6_status_t -object_wait(kobject *self, j6_signal_t mask, j6_signal_t *sigs) -{ - j6_signal_t current = self->signals(); - if ((current & mask) != 0) { - *sigs = current; - return j6_status_ok; - } - - thread &th = thread::current(); - self->add_blocked_thread(&th); - th.wait_on_signals(mask); - - j6_status_t result = th.get_wait_result(); - if (result == j6_status_ok) { - *sigs = th.get_wait_data(); - } - return result; -} - -j6_status_t -object_wait_many(j6_handle_t * handles, size_t handles_count, uint64_t mask, j6_handle_t * woken, uint64_t * signals) -{ - util::vector objects {uint32_t(handles_count)}; - - for (unsigned i = 0; i < handles_count; ++i) { - j6_handle_t hid = handles[i]; - if (hid == j6_handle_invalid) - continue; - - handle *h = get_handle(hid); - if (!h || !h->object) - return j6_err_invalid_arg; - kobject *obj = h->object; - - j6_signal_t current = obj->signals(); - if ((current & mask) != 0) { - *signals = current; - *woken = hid; - return j6_status_ok; - } - - objects.append(obj); - } - - thread &th = thread::current(); - for (auto *obj : objects) - obj->add_blocked_thread(&th); - - th.wait_on_signals(mask); - - j6_status_t result = th.get_wait_result(); - if (result != j6_status_ok) - return result; - - *woken = j6_handle_invalid; - *signals = th.get_wait_data(); - j6_koid_t koid = th.get_wait_object(); - for (unsigned i = 0; i < handles_count; ++i) { - if (koid == objects[i]->koid()) - *woken = handles[i]; - else - objects[i]->remove_blocked_thread(&th); - } - - kassert(*woken != j6_handle_invalid, - "Somehow woke on a handle that was not waited on"); - return j6_status_ok; -} - -j6_status_t -object_close(kobject *self) -{ - self->close(); - return j6_status_ok; -} - } // namespace syscalls diff --git a/src/kernel/syscalls/system.cpp b/src/kernel/syscalls/system.cpp index 47a7060..2e9d0fa 100644 --- a/src/kernel/syscalls/system.cpp +++ b/src/kernel/syscalls/system.cpp @@ -6,7 +6,7 @@ #include "frame_allocator.h" #include "logger.h" #include "memory.h" -#include "objects/endpoint.h" +#include "objects/event.h" #include "objects/thread.h" #include "objects/system.h" #include "objects/vm_area.h" @@ -49,16 +49,13 @@ system_get_log(system *self, void *buffer, size_t *buffer_len) { size_t orig_size = *buffer_len; *buffer_len = g_logger.get_entry(buffer, *buffer_len); - if (!g_logger.has_log()) - self->deassert_signal(j6_signal_system_has_log); - return (*buffer_len > orig_size) ? j6_err_insufficient : j6_status_ok; } j6_status_t -system_bind_irq(system *self, endpoint *endp, unsigned irq) +system_bind_irq(system *self, event *dest, unsigned irq, unsigned signal) { - if (device_manager::get().bind_irq(irq, endp)) + if (device_manager::get().bind_irq(irq, dest, signal)) return j6_status_ok; return j6_err_invalid_arg; diff --git a/src/kernel/syscalls/thread.cpp b/src/kernel/syscalls/thread.cpp index 4debc09..0d3c01e 100644 --- a/src/kernel/syscalls/thread.cpp +++ b/src/kernel/syscalls/thread.cpp @@ -46,21 +46,14 @@ thread_kill(thread *self) return j6_status_ok; } -j6_status_t -thread_pause() -{ - thread &th = thread::current(); - th.wait_on_signals(-1ull); - return j6_status_ok; -} - j6_status_t thread_sleep(uint64_t til) { thread &th = thread::current(); log::debug(logs::task, "Thread %llx sleeping until %llu", th.koid(), til); - th.wait_on_time(til); + th.set_wake_timeout(til); + th.block(); return j6_status_ok; } diff --git a/src/kernel/wait_queue.cpp b/src/kernel/wait_queue.cpp new file mode 100644 index 0000000..9920830 --- /dev/null +++ b/src/kernel/wait_queue.cpp @@ -0,0 +1,50 @@ +#include "objects/thread.h" +#include "wait_queue.h" + +wait_queue::~wait_queue() +{ + util::scoped_lock lock {m_lock}; + for (auto *t : m_threads) { + if (!t->exited()) t->wake(); + t->handle_release(); + } +} + +void +wait_queue::add_thread(obj::thread *t) +{ + util::scoped_lock lock {m_lock}; + t->handle_retain(); + m_threads.push_back(t); +} + +void +wait_queue::pop_exited() +{ + while (!m_threads.empty()) { + obj::thread *t = m_threads.first(); + if (!t->exited()) + break; + + m_threads.pop_front(); + t->handle_release(); + } +} + +obj::thread * +wait_queue::get_next_unlocked() +{ + pop_exited(); + if (m_threads.empty()) + return nullptr; + return m_threads.first(); +} + +obj::thread * +wait_queue::pop_next_unlocked() +{ + pop_exited(); + if (m_threads.empty()) + return nullptr; + return m_threads.pop_front(); +} diff --git a/src/kernel/wait_queue.h b/src/kernel/wait_queue.h new file mode 100644 index 0000000..a440f83 --- /dev/null +++ b/src/kernel/wait_queue.h @@ -0,0 +1,48 @@ +#pragma once +/// \file wait_queue.h +/// Class and related defintions for keeping a queue of waiting threads + +#include +#include + +namespace obj { + class thread; +} + +class wait_queue +{ +public: + /// Wake all threads when destructing + ~wait_queue(); + + /// Add the given thread to the queue. Locks the + /// queue lock. + void add_thread(obj::thread *t); + + /// Pops the next waiting thread off the queue. + /// Locks the queue lock. + inline obj::thread * pop_next() { + util::scoped_lock lock {m_lock}; + return pop_next_unlocked(); + } + + /// Get the next waiting thread. Does not lock the + /// queue lock. + obj::thread * get_next_unlocked(); + + /// Pop the next thread off the queue. Does not + /// lock the queue lock. + obj::thread * pop_next_unlocked(); + + /// Get the spinlock to lock this queue + util::spinlock & get_lock() { return m_lock; } + +private: + /// Get rid of any exited threads that are next + /// in the queue. Caller must hold the queue lock. + void pop_exited(); + + util::spinlock m_lock; + util::deque m_threads; +}; + diff --git a/src/libraries/j6/init.cpp b/src/libraries/j6/init.cpp index cc24b19..65e671e 100644 --- a/src/libraries/j6/init.cpp +++ b/src/libraries/j6/init.cpp @@ -9,43 +9,38 @@ #include #include -j6_handle_t __handle_sys; j6_handle_t __handle_self; namespace { - constexpr size_t __static_arr_size = 4; - j6_handle_t __handle_array[__static_arr_size]; - - static j6_status_t - load_handles() - { - size_t count = __static_arr_size; - j6_handle_t *handles = __handle_array; - j6_status_t s = j6_handle_list(handles, &count); - - if (s != j6_err_insufficient && s != j6_status_ok) - return s; - - if (count > __static_arr_size) - count = __static_arr_size; - - for (size_t i = 0; i < count; ++i) { - uint8_t type = (handles[i] >> 56); - if (type == j6_object_type_system && __handle_sys == j6_handle_invalid) - __handle_sys = handles[i]; - else if (type == j6_object_type_process && __handle_self == j6_handle_invalid) - __handle_self = handles[i]; - } - - return s; - } + constexpr size_t static_arr_size = 8; + j6_handle_t handle_array[static_arr_size]; } // namespace +j6_handle_t +j6_find_first_handle(j6_object_type obj_type) +{ + size_t count = static_arr_size; + j6_handle_t *handles = handle_array; + j6_status_t s = j6_handle_list(handles, &count); + + if (s != j6_err_insufficient && s != j6_status_ok) + return j6_handle_invalid; + + if (count > static_arr_size) + count = static_arr_size; + + for (size_t i = 0; i < count; ++i) { + uint8_t type = (handles[i] >> 56); + if (type == obj_type) return handles[i]; + } + + return j6_handle_invalid; +} + extern "C" void __init_libj6(uint64_t *rsp) { - __handle_sys = __handle_self = j6_handle_invalid; - load_handles(); + __handle_self = j6_find_first_handle(j6_object_type_process); } #endif // __j6kernel diff --git a/src/libraries/j6/j6.module b/src/libraries/j6/j6.module index 78e5c88..68e209d 100644 --- a/src/libraries/j6/j6.module +++ b/src/libraries/j6/j6.module @@ -12,7 +12,6 @@ j6 = module("j6", "j6/errors.h", "j6/flags.h", "j6/init.h", - "j6/signals.h", "j6/syscalls.h.cog", "j6/sysconf.h.cog", "j6/types.h", diff --git a/src/libraries/j6/j6/init.h b/src/libraries/j6/j6/init.h index c65827c..0fdec8f 100644 --- a/src/libraries/j6/j6/init.h +++ b/src/libraries/j6/j6/init.h @@ -1,37 +1,16 @@ #pragma once /// \file init.h -/// Types used in process and thread initialization +/// Process initialization utility functions -#include #include -enum j6_init_type { // `value` is a: - j6_init_handle_self, // Handle to the system - j6_init_handle_other, // Handle to this process - j6_init_desc_framebuffer // Pointer to a j6_init_framebuffer descriptor -}; +#ifdef __cplusplus +extern "C" { +#endif -struct j6_typed_handle { - enum j6_object_type type; - j6_handle_t handle; -}; +/// Find the first handle of the given type held by this process +j6_handle_t j6_find_first_handle(j6_object_type obj_type); -struct j6_init_value { - enum j6_init_type type; - union { - struct j6_typed_handle handle; - void *data; - }; -}; - -/// Structure defining a framebuffer. -/// `flags` has the following bits: -/// 0-3: Pixel layout. 0000: rgb8, 0001: bgr8 -struct j6_init_framebuffer { - uintptr_t addr; - size_t size; - uint32_t vertical; - uint32_t horizontal; - uint32_t scanline; - uint32_t flags; -}; +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/libraries/j6/j6/signals.h b/src/libraries/j6/j6/signals.h deleted file mode 100644 index 83c9711..0000000 --- a/src/libraries/j6/j6/signals.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once -/// \file signals.h -/// Collection of constants for the j6_signal_t type - -// Signals 56-63 are common to all types -#define j6_signal_no_handles (1ull << 56) -#define j6_signal_closed (1ull << 57) -#define j6_signal_global_mask 0xff00000000000000 - -// Signals 0-55 are defined per object type - -// System signals -#define j6_signal_system_has_log (1ull << 0) - -// Channel signals -#define j6_signal_channel_can_send (1ull << 0) -#define j6_signal_channel_can_recv (1ull << 1) - -// Endpoint signals -#define j6_signal_endpoint_can_send (1ull << 0) -#define j6_signal_endpoint_can_recv (1ull << 1) - diff --git a/src/libraries/util/util/deque.h b/src/libraries/util/util/deque.h index 599e789..b4ad093 100644 --- a/src/libraries/util/util/deque.h +++ b/src/libraries/util/util/deque.h @@ -3,6 +3,7 @@ /// A generic templatized linked list. #include +#include #include namespace util { @@ -42,7 +43,9 @@ public: inline void push_front(const T& item) { if (!m_first) { // need a new block at the start - m_list.push_front(new node_type); + node_type *n = new node_type; + memset(n, 0, sizeof(node_type)); + m_list.push_front(n); m_first = N; } m_list.front()->items[--m_first] = item; @@ -50,7 +53,9 @@ public: inline void push_back(const T& item) { if (m_next == N) { // need a new block at the end - m_list.push_back(new node_type); + node_type *n = new node_type; + memset(n, 0, sizeof(node_type)); + m_list.push_back(n); m_next = 0; } m_list.back()->items[m_next++] = item; @@ -80,7 +85,10 @@ public: return value; } - inline bool empty() const { return m_list.empty(); } + inline bool empty() const { + return m_list.empty() || + m_list.length() == 1 && m_first == m_next; + } inline T& first() { assert(!empty() && "Calling first() on an empty deque"); diff --git a/src/libraries/util/util/map.h b/src/libraries/util/util/map.h index 8d49914..ca09ca0 100644 --- a/src/libraries/util/util/map.h +++ b/src/libraries/util/util/map.h @@ -119,7 +119,22 @@ public: { node *n = lookup(k); if (!n) return false; + erase(n); + return true; + } + inline size_t count() const { return m_count; } + inline size_t capacity() const { return m_capacity; } + inline size_t threshold() const { return (m_capacity * max_load) / 100; } + +protected: + inline size_t mod(uint64_t i) const { return i & (m_capacity - 1); } + inline size_t offset(uint64_t h, size_t i) const { + return mod(i + m_capacity - mod(h)); + } + + void erase(node *n) + { n->~node(); --m_count; @@ -132,18 +147,6 @@ public: m.~node(); i = mod(++i); } - - return true; - } - - inline size_t count() const { return m_count; } - inline size_t capacity() const { return m_capacity; } - inline size_t threshold() const { return (m_capacity * max_load) / 100; } - -protected: - inline size_t mod(uint64_t i) const { return i & (m_capacity - 1); } - inline size_t offset(uint64_t h, size_t i) const { - return mod(i + m_capacity - mod(h)); } void set_capacity(size_t capacity) { @@ -263,7 +266,8 @@ public: V * find(const K &k) { node *n = this->lookup(k); - return n ? &n->val : nullptr; + V *val = n ? &n->val : nullptr; + return val; } const V * find(const K &k) const { @@ -285,6 +289,12 @@ public: map(size_t capacity = 0) : base(capacity) {} + V * find(const K &k) { + node *n = this->lookup(k); + V *val = n ? n->val : nullptr; + return val; + } + V * find(const K &k) const { const node *n = this->lookup(k); return n ? n->val : nullptr; diff --git a/src/user/drv.uart/main.cpp b/src/user/drv.uart/main.cpp index 3ef1b23..782431c 100644 --- a/src/user/drv.uart/main.cpp +++ b/src/user/drv.uart/main.cpp @@ -5,7 +5,7 @@ #include #include -#include +#include #include #include #include @@ -19,7 +19,7 @@ extern "C" { } extern j6_handle_t __handle_self; -extern j6_handle_t __handle_sys; +j6_handle_t g_handle_sys = j6_handle_invalid; struct entry { @@ -76,13 +76,13 @@ log_pump_proc() void *message_buffer = nullptr; char stringbuf[300]; - j6_status_t result = j6_system_request_iopl(__handle_sys, 3); + j6_status_t result = j6_system_request_iopl(g_handle_sys, 3); if (result != j6_status_ok) return; while (true) { size_t size = buffer_size; - j6_status_t s = j6_system_get_log(__handle_sys, message_buffer, &size); + j6_status_t s = j6_system_get_log(g_handle_sys, message_buffer, &size); if (s == j6_err_insufficient) { free(message_buffer); @@ -94,12 +94,6 @@ log_pump_proc() continue; } - if (size == 0) { - j6_signal_t sigs = 0; - j6_object_wait(__handle_sys, j6_signal_system_has_log, &sigs); - continue; - } - const entry *e = reinterpret_cast(message_buffer); const char *area_name = area_names[e->area]; @@ -118,22 +112,26 @@ main(int argc, const char **argv) { j6_log("uart driver starting"); - j6_handle_t endp = j6_handle_invalid; + j6_handle_t event = j6_handle_invalid; j6_status_t result = j6_status_ok; - result = j6_system_request_iopl(__handle_sys, 3); + g_handle_sys = j6_find_first_handle(j6_object_type_system); + if (g_handle_sys == j6_handle_invalid) + return 1; + + result = j6_system_request_iopl(g_handle_sys, 3); if (result != j6_status_ok) return result; - result = j6_endpoint_create(&endp); + result = j6_event_create(&event); if (result != j6_status_ok) return result; - result = j6_system_bind_irq(__handle_sys, endp, 3); + result = j6_system_bind_irq(g_handle_sys, event, 3, 0); if (result != j6_status_ok) return result; - result = j6_system_bind_irq(__handle_sys, endp, 4); + result = j6_system_bind_irq(g_handle_sys, event, 4, 1); if (result != j6_status_ok) return result; @@ -159,8 +157,8 @@ main(int argc, const char **argv) size_t len = 0; while (true) { - uint64_t tag = 0; - result = j6_endpoint_receive(endp, &tag, nullptr, &len, 10000); + uint64_t signals = 0; + result = j6_event_wait(event, &signals, 1000); if (result == j6_err_timed_out) { com1.handle_interrupt(); com2.handle_interrupt(); @@ -172,22 +170,10 @@ main(int argc, const char **argv) continue; } - if (!j6_tag_is_irq(tag)) { - j6_log("uart driver got non-irq waiting for irq"); - continue; - } - - unsigned irq = j6_tag_to_irq(tag); - switch (irq) { - case 3: - com2.handle_interrupt(); - break; - case 4: - com1.handle_interrupt(); - break; - default: - j6_log("uart driver got unknown irq waiting for irq"); - } + if (signals & (1<<0)) + com2.handle_interrupt(); + if (signals & (1<<1)) + com1.handle_interrupt(); } j6_log("uart driver somehow got to the end of main"); diff --git a/src/user/drv.uefi_fb/main.cpp b/src/user/drv.uefi_fb/main.cpp index d66bc8c..803153f 100644 --- a/src/user/drv.uefi_fb/main.cpp +++ b/src/user/drv.uefi_fb/main.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include diff --git a/src/user/srv.init/loader.cpp b/src/user/srv.init/loader.cpp index fe544ba..ff48820 100644 --- a/src/user/srv.init/loader.cpp +++ b/src/user/srv.init/loader.cpp @@ -13,7 +13,6 @@ using bootproto::module_flags; using bootproto::module_program; extern j6_handle_t __handle_self; -extern j6_handle_t __handle_sys; constexpr uintptr_t load_addr = 0xf8000000; constexpr size_t stack_size = 0x10000; @@ -28,7 +27,7 @@ load_program(const module_program &prog, j6_handle_t sys, char *err_msg) } j6_handle_t elf_vma = j6_handle_invalid; - j6_status_t res = j6_system_map_phys(__handle_sys, &elf_vma, prog.base_address, prog.size, 0); + j6_status_t res = j6_system_map_phys(sys, &elf_vma, prog.base_address, prog.size, 0); if (res != j6_status_ok) { sprintf(err_msg, " ** error loading program '%s': creating physical vma: %lx", prog.filename, res); return false; diff --git a/src/user/srv.init/main.cpp b/src/user/srv.init/main.cpp index 616ae53..dd53591 100644 --- a/src/user/srv.init/main.cpp +++ b/src/user/srv.init/main.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -21,21 +22,34 @@ extern "C" { uintptr_t _arg_modules_phys; // This gets filled in in _start extern j6_handle_t __handle_self; -extern j6_handle_t __handle_sys; int main(int argc, const char **argv) { + j6_status_t s; + + j6_handle_t sys = j6_handle_invalid; + j6_handle_t sys_child = j6_handle_invalid; + j6_log("srv.init starting"); - modules mods = modules::load_modules(_arg_modules_phys, __handle_sys, __handle_self); + sys = j6_find_first_handle(j6_object_type_system); + if (sys == j6_handle_invalid) + return 1; - j6_handle_t drv_sys_handle = j6_handle_invalid; - j6_status_t s = j6_handle_clone(__handle_sys, &drv_sys_handle, - j6_cap_system_bind_irq | j6_cap_system_map_phys | j6_cap_system_change_iopl); + s = j6_handle_clone(sys, &sys_child, + j6_cap_system_bind_irq | + j6_cap_system_get_log | + j6_cap_system_map_phys | + j6_cap_system_change_iopl); if (s != j6_status_ok) return s; + if (s != j6_status_ok) + return s; + + modules mods = modules::load_modules(_arg_modules_phys, sys, __handle_self); + for (auto &mod : mods.of_type(module_type::program)) { auto &prog = static_cast(mod); @@ -43,7 +57,7 @@ main(int argc, const char **argv) sprintf(message, " loading program module '%s' at %lx", prog.filename, prog.base_address); j6_log(message); - if (!load_program(prog, __handle_sys, message)) { + if (!load_program(prog, sys_child, message)) { j6_log(message); return 1; } diff --git a/src/user/testapp/main.cpp b/src/user/testapp/main.cpp index 65a05c4..ce701bc 100644 --- a/src/user/testapp/main.cpp +++ b/src/user/testapp/main.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include "io.h"