feat(ipc): implement synchronous Rendezvous IPC and multi-thread cooperative scheduler
This commit is contained in:
+20
-15
@@ -2,29 +2,34 @@
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
|
||||
#define UART_SERVICE_ENDPOINT 2
|
||||
|
||||
extern "C" void _start() {
|
||||
puts("[INIT-SERVER] Userspace Root Init Server Started (Ring 3)!");
|
||||
|
||||
// 1. Instantiate RAII IPC Endpoint for Kernel Control
|
||||
ipc::Endpoint kernel_ctrl(CAP_SELF_TASK);
|
||||
// 1. Communicate with Kernel Control (Endpoint 1)
|
||||
ipc::Endpoint kernel_ctrl(CAP_KERNEL_CONTROL);
|
||||
puts("[INIT-SERVER] Sending Fast-Path IPC Ping to Microkernel (CAP 1)...");
|
||||
auto kping = kernel_ctrl.call(IPC_OP_PING, 777);
|
||||
if (kping.is_ok()) {
|
||||
puts("[INIT-SERVER] Received Pong from Microkernel!");
|
||||
}
|
||||
|
||||
puts("[INIT-SERVER] Sending Fast-Path IPC Ping to Microkernel...");
|
||||
auto ping_res = kernel_ctrl.call(IPC_OP_PING, 100);
|
||||
// 2. Communicate with UART Driver Service (Endpoint 2) via Rendezvous IPC
|
||||
ipc::Endpoint uart_service(UART_SERVICE_ENDPOINT);
|
||||
puts("[INIT-SERVER] Sending Synchronous Rendezvous IPC to UART Driver (Endpoint 2)...");
|
||||
|
||||
if (ping_res.is_ok()) {
|
||||
puts("[INIT-SERVER] Received IPC Ping Response from Microkernel!");
|
||||
// Pack 4 characters 'O', 'K', '!', '\n' into 32-bit arg0
|
||||
uint64_t msg_chars = 'O' | ('K' << 8) | ('!' << 16) | ('\n' << 24);
|
||||
auto uart_res = uart_service.call(IPC_OP_WRITE, msg_chars);
|
||||
|
||||
if (uart_res.is_ok()) {
|
||||
puts("[INIT-SERVER] Rendezvous IPC Call to UART Driver SUCCEEDED!");
|
||||
} else {
|
||||
puts("[INIT-SERVER] IPC Call Failed!");
|
||||
puts("[INIT-SERVER] Rendezvous IPC Call failed.");
|
||||
}
|
||||
|
||||
// 2. Register Server Endpoint
|
||||
puts("[INIT-SERVER] Registering Root Server Capability...");
|
||||
auto reg_res = kernel_ctrl.call(IPC_OP_REGISTER_SERVER, 0x1337BEEF);
|
||||
if (reg_res.is_ok()) {
|
||||
puts("[INIT-SERVER] Server Registered Successfully!");
|
||||
}
|
||||
|
||||
puts("[INIT-SERVER] Root Init Server ready. Entering event loop.");
|
||||
puts("[INIT-SERVER] Root Init Server running. Entering worker loop.");
|
||||
|
||||
while (true) {
|
||||
sys_yield();
|
||||
|
||||
@@ -1,17 +1,63 @@
|
||||
#include "uart.h"
|
||||
#include "stdio.h"
|
||||
#include "abi/syscalls.h"
|
||||
#include "abi/ipc.h"
|
||||
|
||||
#define UART_SERVICE_ENDPOINT 2
|
||||
|
||||
extern void _start(void) {
|
||||
uart_init(UART_COM1_PORT, 115200);
|
||||
uart_puts(UART_COM1_PORT, "[RING3-UART-DRIVER] 16550 UART COM1 initialized from userspace!\n");
|
||||
puts("[UART-DRIVER] 16550 UART Server started in Ring 3. Listening for IPC requests...");
|
||||
|
||||
uint64_t last_client = 0;
|
||||
uint64_t reply_val0 = 0;
|
||||
uint64_t reply_val1 = 0;
|
||||
|
||||
while (1) {
|
||||
if (uart_has_data(UART_COM1_PORT)) {
|
||||
char c = uart_getc(UART_COM1_PORT);
|
||||
// Echo back
|
||||
uart_putc(UART_COM1_PORT, c);
|
||||
uint64_t sender_tid = 0;
|
||||
uint64_t opcode = 0;
|
||||
uint64_t arg0 = 0;
|
||||
uint64_t arg1 = 0;
|
||||
|
||||
// Block and wait for next client IPC request, replying to last client if any
|
||||
sysret_t ret = sys_ipc_reply_recv_raw(
|
||||
UART_SERVICE_ENDPOINT,
|
||||
last_client,
|
||||
reply_val0,
|
||||
reply_val1,
|
||||
&sender_tid,
|
||||
&opcode,
|
||||
&arg0,
|
||||
&arg1
|
||||
);
|
||||
|
||||
if (ret == 0 && sender_tid != 0) {
|
||||
last_client = sender_tid;
|
||||
|
||||
if (opcode == IPC_OP_WRITE) {
|
||||
// Write received characters to UART hardware
|
||||
char c0 = (char)(arg0 & 0xFF);
|
||||
char c1 = (char)((arg0 >> 8) & 0xFF);
|
||||
char c2 = (char)((arg0 >> 16) & 0xFF);
|
||||
char c3 = (char)((arg0 >> 24) & 0xFF);
|
||||
|
||||
if (c0) uart_putc(UART_COM1_PORT, c0);
|
||||
if (c1) uart_putc(UART_COM1_PORT, c1);
|
||||
if (c2) uart_putc(UART_COM1_PORT, c2);
|
||||
if (c3) uart_putc(UART_COM1_PORT, c3);
|
||||
|
||||
reply_val0 = 0; // Success
|
||||
reply_val1 = 4; // Bytes written
|
||||
} else if (opcode == IPC_OP_PING) {
|
||||
reply_val0 = IPC_OP_PONG;
|
||||
reply_val1 = arg0 + 1;
|
||||
} else {
|
||||
reply_val0 = (uint64_t)-1;
|
||||
reply_val1 = 0;
|
||||
}
|
||||
} else {
|
||||
last_client = 0;
|
||||
sys_yield();
|
||||
}
|
||||
sys_yield();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user