1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
#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;
}
}
|