-
Notifications
You must be signed in to change notification settings - Fork 14
/
catch_ball.rs
134 lines (117 loc) · 3.4 KB
/
catch_ball.rs
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#![no_main]
#![no_std]
#![feature(asm)]
#[macro_use]
extern crate misc;
extern crate osmium_syscall;
use core::slice;
use misc::syscall;
use osmium_syscall::errors::SyscallError;
use osmium_syscall::perm;
fn blocking_receive() -> Result<syscall::Message, SyscallError> {
//println!("blocking_receive");
match syscall::sys_receive() {
Err(SyscallError::QueueIsEmpty) => {
syscall::sys_yield();
blocking_receive()
}
Err(e) => Err(e),
Ok(msg) => Ok(msg),
}
}
fn receive_from_id(id: u32) -> Result<u32, SyscallError> {
match blocking_receive() {
Ok(ref msg) if msg.id == id => Ok(msg.data),
Ok(ref msg) => receive_from_id(id),
Err(e) => Err(e),
}
}
fn blocking_send(id: u32, data: u32) -> Result<(), SyscallError> {
match syscall::sys_send(id, data) {
Err(SyscallError::QueueIsFull) => {
syscall::sys_yield();
blocking_send(id, data)
}
Err(e) => Err(e),
Ok(()) => Ok(()),
}
}
const SIZE: usize = 8;
fn parent(child_id: u32) -> Result<(), SyscallError> {
let my_id = syscall::sys_get_proc_id();
syscall::sys_send(child_id, my_id)?;
let mut data = [1; SIZE];
for i in 0..5 {
for x in &data {
blocking_send(child_id, *x)?;
}
for i in 0..SIZE {
let v = receive_from_id(child_id)?;
data[i] = (i as u32 + 1) * v;
}
}
for i in 0..SIZE {
println!("{}: {}", i, data[i]);
}
println!("let's start sharing page");
// first, create memory region.
let addr = syscall::sys_alloc(None, 4096 * 2, perm::Perm::READ | perm::Perm::WRITE)?;
println!("addr: {}", addr);
// second, memory map between the parent and its child
syscall::sys_mmap(
my_id,
addr,
child_id,
addr,
perm::Perm::READ | perm::Perm::WRITE,
)?;
// then, notify the address where they use
syscall::sys_send(child_id, addr)?;
// start communicating.
let data = unsafe { slice::from_raw_parts_mut(addr as *mut u32, 4096 * 2 / 4) };
data[0] = 100;
//data[1024] = 100;
// notify the timing
syscall::sys_send(child_id, addr)?;
let _ = receive_from_id(child_id)?;
Ok(())
}
fn child() -> Result<(), SyscallError> {
let id = syscall::sys_receive()?.data;
// should check id is my parent
let mut data = [1; SIZE];
for _ in 0..5 {
for i in 0..SIZE {
let v = receive_from_id(id)?;
data[i] = v + 1;
}
for x in &data {
blocking_send(id, *x)?;
}
}
let addr = receive_from_id(id)?;
println!("child addr: {}", addr);
let data = unsafe { slice::from_raw_parts_mut(addr as *mut u32, 4096 / 4) };
// wait for update
let _ = receive_from_id(id)?;
println!("data[0] = {}", data[0]);
syscall::sys_send(id, addr)?;
Ok(())
}
#[no_mangle]
pub extern "C" fn _start() -> ! {
match syscall::sys_fork() {
syscall::ForkResult::Parent(id) => match parent(id) {
Ok(()) => (),
Err(e) => println!("parent error: {}", e),
},
syscall::ForkResult::Fail => {
syscall::sys_exit(-1);
}
syscall::ForkResult::Child => match child() {
Err(SyscallError::NotFound) | Ok(()) => (),
Err(e) => println!("child error: {}", e),
},
}
syscall::sys_exit(0)
}