#include "api/error.h" #include "api/obj.h" #include "api/syscall.h" #include "jove.h" #include "lib/printf.h" #include "proc/process.h" #include "proc/scheduler.h" #include "syscall.h" #include "errno.h" int s_syscall_pcb_yield(jove_owned_obj_t *pcb_obj, size_t bytes_left, void *payload_data) { size_t bytes_needed = sizeof(pid_t); CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for payload"); pid_t subject_pid = *((pid_t*)payload_data); return scheduler_yield(subject_pid); } int s_syscall_pcb_send(jove_owned_obj_t *pcb_obj, lockstack_t *lockstack, jove_owned_obj_t *objdir_obj, size_t bytes_left, void *payload_data) { size_t bytes_needed = sizeof(struct syscall_pcb_send); CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for payload"); struct syscall_pcb_send *payload = payload_data; bytes_needed += payload->send_path_length; CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for subject path"); jove_perm_obj_t subject_objdir = link_try_traverse_objdir( objdir_obj, lockstack, payload->send_path_length - 1, payload->send_path); if(errno) { klogf("Unable to get subject %P objdir : %s\n", payload->send_path, payload->send_path_length, errstr(errno)); return -errno; } CHECK_OBJPERM(subject_objdir, SYSCALL_PERM_PCB_SEND_OBJDIR, "Subject objdir does not permit send"); jove_owned_obj_t *subject = objdir_trygetlocal(subject_objdir.obj, payload->send_path[payload->send_path_length-1]); if(subject == 0) { klogf("Unable to get subject %P object : %s\n", payload->send_path, payload->send_path_length, errstr(errno)); return -errno; } return pcb_send(obj_deref(pcb_obj), payload->send_target, subject, payload->send_timeout); } int s_syscall_pcb_recv(jove_owned_obj_t *pcb_obj, lockstack_t *lockstack, jove_owned_obj_t *objdir_obj, size_t bytes_left, void *payload_data) { size_t bytes_needed = sizeof(struct syscall_pcb_recv); CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for payload"); struct syscall_pcb_recv *payload = payload_data; bytes_needed += payload->recv_path_length * sizeof(objpath_part_t); CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for destination path"); jove_perm_obj_t destination = link_try_traverse_objdir( objdir_obj, lockstack, payload->recv_path_length, payload->recv_path); if(errno) { klogf("Unable to get destination %P : %s\n", payload->recv_path, payload->recv_path_length, errstr(errno)); return -errno; } CHECK_OBJPERM(destination, SYSCALL_PERM_PCB_RECV_DST, "Destination object does not permit recv."); return pcb_recv(obj_deref(pcb_obj), payload->recv_target, destination.obj, payload->recv_timeout); } int _syscall_handle_pcb(syscall_context_t *ctx) { switch(ctx->header->callid) { case SYSCALL_PCB_YIELD: if(ctx->target.permissions & SYSCALL_PERM_PCB_YIELD) return s_syscall_pcb_yield(ctx->target.obj, ctx->bytes_left, ctx->payload); return -EPERM; case SYSCALL_PCB_SEND: if(ctx->target.permissions & SYSCALL_PERM_PCB_SEND) return s_syscall_pcb_send( ctx->target.obj, &ctx->lockstack, ctx->objdir, ctx->bytes_left, ctx->payload); return -EPERM; case SYSCALL_PCB_RECV: if(ctx->target.permissions & SYSCALL_PERM_PCB_RECV) return s_syscall_pcb_recv( ctx->target.obj, &ctx->lockstack, ctx->objdir, ctx->bytes_left, ctx->payload); return -EPERM; default: return -EBADCALL; } }