First pass at message syscalls
This commit is contained in:
@@ -9,6 +9,11 @@ _start:
|
||||
mov rax, 1 ; DEBUG syscall
|
||||
int 0xee
|
||||
|
||||
cmp r12, 1
|
||||
je .dosend
|
||||
jne .doreceive
|
||||
|
||||
.preloop:
|
||||
mov r11, 0 ; counter
|
||||
mov rbx, 20 ; sleep timeout
|
||||
|
||||
@@ -31,3 +36,15 @@ _start:
|
||||
|
||||
mov r11, 0
|
||||
jmp .loop
|
||||
|
||||
.dosend:
|
||||
mov rax, 6 ; SEND syscall
|
||||
mov rdi, 2 ; target is pid 2
|
||||
int 0xee
|
||||
jmp .preloop
|
||||
|
||||
.doreceive:
|
||||
mov rax, 7 ; RECEIVE syscall
|
||||
mov rdi, 1 ; source is pid 2
|
||||
int 0xee
|
||||
jmp .preloop
|
||||
|
||||
@@ -1,28 +1,65 @@
|
||||
#include "process.h"
|
||||
#include "scheduler.h"
|
||||
|
||||
|
||||
void
|
||||
bool
|
||||
process::wait_on_signal(uint64_t sigmask)
|
||||
{
|
||||
waiting = process_wait::signal;
|
||||
waiting_info = sigmask;
|
||||
flags -= process_flags::ready;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
process::wait_on_child(uint32_t pid)
|
||||
{
|
||||
waiting = process_wait::child;
|
||||
waiting_info = pid;
|
||||
flags -= process_flags::ready;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
process::wait_on_time(uint64_t time)
|
||||
{
|
||||
waiting = process_wait::time;
|
||||
waiting_info = time;
|
||||
flags -= process_flags::ready;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
process::wait_on_send(uint32_t target_id)
|
||||
{
|
||||
scheduler &s = scheduler::get();
|
||||
process *target = s.get_process_by_id(target_id);
|
||||
if (!target) return false;
|
||||
|
||||
if (!target->wake_on_receive(this)) {
|
||||
waiting = process_wait::send;
|
||||
waiting_info = target_id;
|
||||
flags -= process_flags::ready;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
process::wait_on_receive(uint32_t source_id)
|
||||
{
|
||||
scheduler &s = scheduler::get();
|
||||
process *source = s.get_process_by_id(source_id);
|
||||
if (!source) return false;
|
||||
|
||||
if (!source->wake_on_send(this)) {
|
||||
waiting = process_wait::receive;
|
||||
waiting_info = source_id;
|
||||
flags -= process_flags::ready;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -49,7 +86,6 @@ process::wake_on_child(process *child)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
process::wake_on_time(uint64_t now)
|
||||
{
|
||||
@@ -62,3 +98,28 @@ process::wake_on_time(uint64_t now)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
process::wake_on_send(process *target)
|
||||
{
|
||||
if (waiting != process_wait::send ||
|
||||
waiting_info != target->pid)
|
||||
return false;
|
||||
|
||||
waiting = process_wait::none;
|
||||
flags += process_flags::ready;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
process::wake_on_receive(process *source)
|
||||
{
|
||||
if (waiting != process_wait::receive ||
|
||||
waiting_info != source->pid)
|
||||
return false;
|
||||
|
||||
waiting = process_wait::none;
|
||||
flags += process_flags::ready;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,9 @@ enum class process_wait : uint8_t
|
||||
none,
|
||||
signal,
|
||||
child,
|
||||
time
|
||||
time,
|
||||
send,
|
||||
receive
|
||||
};
|
||||
|
||||
/// A process
|
||||
@@ -52,15 +54,30 @@ struct process
|
||||
|
||||
/// Unready this process until it gets a signal
|
||||
/// \arg sigmask A bitfield of signals to wake on
|
||||
void wait_on_signal(uint64_t sigmask);
|
||||
/// \returns Whether the process should be rescheduled
|
||||
bool wait_on_signal(uint64_t sigmask);
|
||||
|
||||
/// Unready this process until a child exits
|
||||
/// \arg pid PID of the child to wait for, or 0 for any
|
||||
void wait_on_child(uint32_t pid);
|
||||
/// \returns Whether the process should be rescheduled
|
||||
bool wait_on_child(uint32_t pid);
|
||||
|
||||
/// Unready this process until after the given time
|
||||
/// \arg time The time after which to wake
|
||||
void wait_on_time(uint64_t time);
|
||||
/// \returns Whether the process should be rescheduled
|
||||
bool wait_on_time(uint64_t time);
|
||||
|
||||
/// Try to send to the target process, becoming unready if it
|
||||
/// is not waiting on receive.
|
||||
/// \arg target_id The process to send to
|
||||
/// \returns Whether the process should be rescheduled
|
||||
bool wait_on_send(uint32_t target_id);
|
||||
|
||||
/// Try to receive from one or more processes, becoming unready
|
||||
/// if none of them are waiting on a send to this process.
|
||||
/// \arg source_id The process to receive from
|
||||
/// \returns Whether the process should be rescheduled
|
||||
bool wait_on_receive(uint32_t source_id);
|
||||
|
||||
/// If this process is waiting on the given signal, wake it
|
||||
/// \argument signal The signal sent to the process
|
||||
@@ -76,6 +93,17 @@ struct process
|
||||
/// \argument now The current time
|
||||
/// \returns True if this wake was handled
|
||||
bool wake_on_time(uint64_t now);
|
||||
|
||||
/// If this process is waiting to send to this target, wake it
|
||||
/// \argument target The target process
|
||||
/// \returns True if this wake was handled
|
||||
bool wake_on_send(process *target);
|
||||
|
||||
/// If this process is waiting to receieve from this source, wake it
|
||||
/// \argument source The process that is sending
|
||||
/// \returns True if this wake was handled
|
||||
bool wake_on_receive(process *source);
|
||||
|
||||
};
|
||||
|
||||
using process_list = kutil::linked_list<process>;
|
||||
|
||||
@@ -92,6 +92,31 @@ syscall_dispatch(uintptr_t return_rsp, cpu_state ®s)
|
||||
regs.rax = p->pid;
|
||||
break;
|
||||
|
||||
case syscall::send:
|
||||
{
|
||||
uint32_t target = regs.rdi;
|
||||
|
||||
cons->set_color(11);
|
||||
cons->printf("\nProcess %u: Received SEND syscall, target %u\n", p->pid, target);
|
||||
cons->set_color();
|
||||
|
||||
if (p->wait_on_send(target))
|
||||
return_rsp = s.schedule(return_rsp);
|
||||
}
|
||||
break;
|
||||
|
||||
case syscall::receive:
|
||||
{
|
||||
uint32_t source = regs.rdi;
|
||||
|
||||
cons->set_color(11);
|
||||
cons->printf("\nProcess %u: Received RECEIVE syscall, source %u\n", p->pid, source);
|
||||
cons->set_color();
|
||||
|
||||
if (p->wait_on_receive(source))
|
||||
return_rsp = s.schedule(return_rsp);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
cons->set_color(9);
|
||||
|
||||
@@ -12,6 +12,8 @@ enum class syscall : uint64_t
|
||||
pause,
|
||||
sleep,
|
||||
getpid,
|
||||
send,
|
||||
receive,
|
||||
|
||||
last_syscall
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user