mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 08:24:32 -08:00
[kernel] Add object_wait_many syscall
Add the object_wait_many syscall to allow programs to wait for signals on multiple objects at once. Also removed the object argument to thread::wait_on_signals, which does nothing with it. That information is saved in the thread being in the object's blocked threads list.
This commit is contained in:
@@ -52,7 +52,7 @@ thread_proc()
|
||||
int
|
||||
main(int argc, const char **argv)
|
||||
{
|
||||
j6_handle_t child = j6_handle_invalid;
|
||||
j6_handle_t children[2] = {j6_handle_invalid, j6_handle_invalid};
|
||||
j6_signal_t out = 0;
|
||||
|
||||
j6_system_log("main thread starting");
|
||||
@@ -76,7 +76,7 @@ main(int argc, const char **argv)
|
||||
|
||||
j6_system_log("main thread created endpoint");
|
||||
|
||||
result = j6_thread_create(reinterpret_cast<void*>(&thread_proc), &child);
|
||||
result = j6_thread_create(reinterpret_cast<void*>(&thread_proc), &children[1]);
|
||||
if (result != j6_status_ok)
|
||||
return result;
|
||||
|
||||
@@ -98,17 +98,26 @@ main(int argc, const char **argv)
|
||||
|
||||
j6_system_log(message);
|
||||
|
||||
j6_system_log("main thread waiting on child");
|
||||
result = j6_object_wait(child, -1ull, &out);
|
||||
j6_system_log("main thread creating a new process");
|
||||
result = j6_process_create(&children[0]);
|
||||
if (result != j6_status_ok)
|
||||
return result;
|
||||
|
||||
j6_system_log("main thread creating a new process");
|
||||
j6_handle_t child_proc = j6_handle_invalid;
|
||||
result = j6_process_create(&child_proc);
|
||||
j6_system_log("main thread waiting on children");
|
||||
|
||||
j6_handle_t outhandle;
|
||||
result = j6_object_wait_many(children, 2, -1ull, &outhandle, &out);
|
||||
if (result != j6_status_ok)
|
||||
return result;
|
||||
|
||||
if (outhandle == children[1]) {
|
||||
j6_system_log(" ok from child thread");
|
||||
} else if (outhandle == children[0]) {
|
||||
j6_system_log(" ok from child process");
|
||||
} else {
|
||||
j6_system_log(" ... got unknown handle");
|
||||
}
|
||||
|
||||
j6_system_log("main testing irqs");
|
||||
|
||||
|
||||
|
||||
@@ -6,8 +6,9 @@ SYSCALL(0x04, system_map_mmio, j6_handle_t, j6_handle_t *, uintptr_t, size_t,
|
||||
|
||||
SYSCALL(0x08, object_koid, j6_handle_t, j6_koid_t *)
|
||||
SYSCALL(0x09, object_wait, j6_handle_t, j6_signal_t, j6_signal_t *)
|
||||
SYSCALL(0x0a, object_signal, j6_handle_t, j6_signal_t)
|
||||
SYSCALL(0x0b, object_close, j6_handle_t)
|
||||
SYSCALL(0x0a, object_wait_many, j6_handle_t *, uint32_t, j6_signal_t, j6_handle_t *, j6_signal_t *)
|
||||
SYSCALL(0x0b, object_signal, j6_handle_t, j6_signal_t)
|
||||
SYSCALL(0x0c, object_close, j6_handle_t)
|
||||
|
||||
SYSCALL(0x10, process_create, j6_handle_t *)
|
||||
SYSCALL(0x11, process_start, j6_handle_t, uintptr_t, j6_handle_t *, size_t)
|
||||
|
||||
@@ -75,7 +75,7 @@ logger_task()
|
||||
if (!g_logger.has_log()) {
|
||||
sys.deassert_signal(j6_signal_system_has_log);
|
||||
sys.add_blocked_thread(&self);
|
||||
self.wait_on_signals(&sys, j6_signal_system_has_log);
|
||||
self.wait_on_signals(j6_signal_system_has_log);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,13 +50,11 @@ void
|
||||
kobject::notify_signal_observers()
|
||||
{
|
||||
size_t i = 0;
|
||||
bool readied = false;
|
||||
while (i < m_blocked_threads.count()) {
|
||||
thread *t = m_blocked_threads[i];
|
||||
|
||||
if (t->wake_on_signals(this, m_signals)) {
|
||||
m_blocked_threads.remove_swap_at(i);
|
||||
readied = true;
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ thread & thread::current() { return *current_cpu().thread; }
|
||||
inline void schedule_if_current(thread *t) { if (t == current_cpu().thread) scheduler::get().schedule(); }
|
||||
|
||||
void
|
||||
thread::wait_on_signals(kobject *obj, j6_signal_t signals)
|
||||
thread::wait_on_signals(j6_signal_t signals)
|
||||
{
|
||||
m_wait_type = wait_type::signal;
|
||||
m_wait_data = signals;
|
||||
|
||||
@@ -74,10 +74,9 @@ public:
|
||||
/// \arg p The new thread priority
|
||||
inline void set_priority(uint8_t p) { if (!constant()) m_tcb.priority = p; }
|
||||
|
||||
/// Block the thread, waiting on the given object's signals.
|
||||
/// \arg obj Object to wait on
|
||||
/// Block the thread, waiting an object's signals.
|
||||
/// \arg signals Mask of signals to wait for
|
||||
void wait_on_signals(kobject *obj, j6_signal_t signals);
|
||||
void wait_on_signals(j6_signal_t signals);
|
||||
|
||||
/// Block the thread, waiting for a given clock value
|
||||
/// \arg t Clock value to wait for
|
||||
@@ -114,6 +113,9 @@ public:
|
||||
/// 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; }
|
||||
|
||||
inline bool has_state(state s) const {
|
||||
return static_cast<uint8_t>(m_state) & static_cast<uint8_t>(s);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ object_wait(j6_handle_t handle, j6_signal_t mask, j6_signal_t *sigs)
|
||||
|
||||
thread &th = thread::current();
|
||||
obj->add_blocked_thread(&th);
|
||||
th.wait_on_signals(obj, mask);
|
||||
th.wait_on_signals(mask);
|
||||
|
||||
j6_status_t result = th.get_wait_result();
|
||||
if (result == j6_status_ok) {
|
||||
@@ -46,6 +46,55 @@ object_wait(j6_handle_t handle, j6_signal_t mask, j6_signal_t *sigs)
|
||||
return result;
|
||||
}
|
||||
|
||||
j6_status_t
|
||||
object_wait_many(j6_handle_t *handles, uint32_t count, j6_signal_t mask, j6_handle_t *handle, j6_signal_t *sigs)
|
||||
{
|
||||
kutil::vector<kobject*> objects {count};
|
||||
|
||||
for (unsigned i = 0; i < count; ++i) {
|
||||
j6_handle_t h = handles[i];
|
||||
if (h == j6_handle_invalid)
|
||||
continue;
|
||||
|
||||
kobject *obj = get_handle<kobject>(h);
|
||||
if (!obj)
|
||||
return j6_err_invalid_arg;
|
||||
|
||||
j6_signal_t current = obj->signals();
|
||||
if ((current & mask) != 0) {
|
||||
*sigs = current;
|
||||
*handle = h;
|
||||
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;
|
||||
|
||||
*handle = j6_handle_invalid;
|
||||
*sigs = th.get_wait_data();
|
||||
j6_koid_t koid = th.get_wait_object();
|
||||
for (unsigned i = 0; i < count; ++i) {
|
||||
if (koid == objects[i]->koid())
|
||||
*handle = handles[i];
|
||||
else
|
||||
objects[i]->remove_blocked_thread(&th);
|
||||
}
|
||||
|
||||
kassert(*handle != j6_handle_invalid,
|
||||
"Somehow woke on a handle that was not waited on");
|
||||
return j6_status_ok;
|
||||
}
|
||||
|
||||
j6_status_t
|
||||
object_signal(j6_handle_t handle, j6_signal_t signals)
|
||||
{
|
||||
|
||||
@@ -40,7 +40,7 @@ j6_status_t
|
||||
thread_pause()
|
||||
{
|
||||
thread &th = thread::current();
|
||||
th.wait_on_signals(&th, -1ull);
|
||||
th.wait_on_signals(-1ull);
|
||||
return j6_status_ok;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user