First pass at message syscalls

This commit is contained in:
Justin C. Miller
2019-02-07 18:19:22 -08:00
parent 8e85ae5318
commit aca442ee87
5 changed files with 141 additions and 8 deletions

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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>;

View File

@@ -92,6 +92,31 @@ syscall_dispatch(uintptr_t return_rsp, cpu_state &regs)
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);

View File

@@ -12,6 +12,8 @@ enum class syscall : uint64_t
pause,
sleep,
getpid,
send,
receive,
last_syscall
};