Skip to content

Commit f50f305

Browse files
committed
send/recv socket syscalls
1 parent fecc6c0 commit f50f305

File tree

7 files changed

+125
-118
lines changed

7 files changed

+125
-118
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ pc-keyboard = { git = "https://github.com/rust-embedded-community/pc-keyboard",
2929
paste = "1.0" # macro ident concat
3030
bit_field = "0.10"
3131
bytemuck = { version = "1.13", features = ["derive"] }
32-
lock_api = "0.4"
32+
lock_api = { version = "0.4", features = ["arc_lock"] }
3333
ringbuf = { version = "0.3", default-features = false, features = ["alloc"] }
3434
# rpds = { version = "1.1", default-features = false }
3535
# image = "0.24"

crates/kernel/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ x86_64.workspace = true
1919
time.workspace = true
2020
futures-util.workspace = true
2121
crossbeam.workspace = true
22+
lock_api.workspace = true
2223

2324
hyperion-arch.path = "../arch"
2425
hyperion-backtrace.path = "../backtrace"

crates/kernel/src/syscall.rs

Lines changed: 89 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use hyperion_vfs::{
3131
path::Path,
3232
tree::{FileRef, Node},
3333
};
34+
use lock_api::ArcMutexGuard;
3435
use time::Duration;
3536
use x86_64::{structures::paging::PageTableFlags, VirtAddr};
3637

@@ -242,39 +243,6 @@ pub fn pfree(args: &mut SyscallRegs) -> Result<usize> {
242243
return Ok(0);
243244
}
244245

245-
/// send data to an input channel of a process
246-
///
247-
/// # arguments
248-
/// - `syscall_id` : 11
249-
/// - `arg0` : target PID
250-
/// - `arg1` : data ptr
251-
/// - `arg2` : data len (bytes)
252-
pub fn send(args: &mut SyscallRegs) -> Result<usize> {
253-
let target_pid = args.arg0;
254-
let data = read_untrusted_bytes(args.arg1, args.arg2)?;
255-
256-
let pid = hyperion_scheduler::task::Pid::new(target_pid as usize);
257-
258-
if hyperion_scheduler::send(pid, data).is_err() {
259-
return Err(Error::NO_SUCH_PROCESS);
260-
}
261-
262-
return Ok(0);
263-
}
264-
265-
/// recv data from this process input channel
266-
///
267-
/// returns the number of bytes read
268-
///
269-
/// # arguments
270-
/// - `syscall_id` : 12
271-
/// - `arg0` : data ptr
272-
/// - `arg1` : data len (bytes)
273-
pub fn recv(args: &mut SyscallRegs) -> Result<usize> {
274-
let buf = read_untrusted_bytes_mut(args.arg0, args.arg1)?;
275-
return Ok(hyperion_scheduler::recv(buf));
276-
}
277-
278246
/// rename the current process
279247
///
280248
/// # arguments
@@ -503,24 +471,16 @@ fn _bind(socket: SocketDesc, addr: &str) -> Result<()> {
503471
return Err(Error::NOT_FOUND);
504472
};
505473

506-
let this = process();
507-
let ext = process_ext_with(&this);
474+
let socket = get_socket(socket)?;
508475

509-
let sockets = ext.sockets.lock();
510-
let socket_file = sockets
511-
.get(socket.0)
512-
.and_then(|s| s.as_ref())
513-
.ok_or(Error::BAD_FILE_DESCRIPTOR)?
514-
.socket_ref
515-
.clone();
516-
drop(sockets);
517-
518-
let dir = VFS_ROOT
476+
VFS_ROOT
477+
// find the directory node
519478
.find_dir(dir, false)
520-
.map_err(map_vfs_err_to_syscall_err)?;
521-
522-
dir.lock()
523-
.create_node(sock_file, Node::File(socket_file))
479+
.map_err(map_vfs_err_to_syscall_err)?
480+
// lock the directory
481+
.lock_arc()
482+
// create the socket file in that directory
483+
.create_node(sock_file, Node::File(socket))
524484
.map_err(map_vfs_err_to_syscall_err)?;
525485

526486
return Ok(());
@@ -535,17 +495,9 @@ fn listen(args: &mut SyscallRegs) -> Result<usize> {
535495
}
536496

537497
fn _listen(socket: SocketDesc) -> Result<()> {
538-
let this = process();
539-
let ext = process_ext_with(&this);
540-
541-
ext.sockets
542-
.lock()
543-
.get(socket.0)
544-
.and_then(|s| s.as_ref())
545-
.ok_or(Error::BAD_FILE_DESCRIPTOR)?
546-
.socket_ref
547-
.lock()
548-
.conn = Some(Arc::new(Channel::new()));
498+
get_socket_locked(socket)?
499+
.conn
500+
.get_or_insert_with(|| Arc::new(Channel::new()));
549501

550502
Ok(())
551503
}
@@ -560,19 +512,7 @@ fn accept(args: &mut SyscallRegs) -> Result<usize> {
560512
}
561513

562514
fn _accept(socket: SocketDesc) -> Result<SocketDesc> {
563-
let this = process();
564-
let ext = process_ext_with(&this);
565-
566-
let sockets = ext.sockets.lock();
567-
let socket = sockets
568-
.get(socket.0)
569-
.and_then(|s| s.as_ref())
570-
.ok_or(Error::BAD_FILE_DESCRIPTOR)?
571-
.socket_ref
572-
.clone();
573-
drop(sockets);
574-
575-
let mut socket = socket.lock();
515+
let mut socket = get_socket_locked(socket)?;
576516

577517
let domain = socket.domain;
578518
let ty = socket.ty;
@@ -609,22 +549,13 @@ fn connect(args: &mut SyscallRegs) -> Result<usize> {
609549
}
610550

611551
fn _connect(socket: SocketDesc, addr: &str) -> Result<()> {
612-
let this = process();
613-
let ext = process_ext_with(&this);
614-
615-
let sockets = ext.sockets.lock();
616-
let client = sockets
617-
.get(socket.0)
618-
.and_then(|s| s.as_ref())
619-
.ok_or(Error::BAD_FILE_DESCRIPTOR)?
620-
.socket_ref
621-
.clone();
622-
drop(sockets);
552+
// get the client socket early to test for errors, but lock it late
553+
let client = get_socket(socket)?;
623554

624555
let server = VFS_ROOT
625556
.find_file(addr, false, false)
626-
.map_err(map_vfs_err_to_syscall_err)?;
627-
let server = server.lock();
557+
.map_err(map_vfs_err_to_syscall_err)?
558+
.lock_arc();
628559

629560
// TODO: inode
630561
let conn = server
@@ -642,13 +573,62 @@ fn _connect(socket: SocketDesc, addr: &str) -> Result<()> {
642573
drop(server);
643574

644575
let pipe = Arc::new(Pipe::new());
645-
conn.send(pipe.clone());
646-
647-
client.lock().pipe = Some(pipe);
576+
client.lock().pipe = Some(pipe.clone());
577+
conn.send(pipe);
648578

649579
Ok(())
650580
}
651581

582+
/// send data to a socket
583+
///
584+
/// [`hyperion_syscall::send`]
585+
pub fn send(args: &mut SyscallRegs) -> Result<usize> {
586+
let socket = SocketDesc(args.arg0 as _);
587+
let data = read_untrusted_bytes(args.arg1, args.arg2)?;
588+
let flags = args.arg3 as _;
589+
590+
_send(socket, data, flags).map(|_| 0)
591+
}
592+
593+
fn _send(socket: SocketDesc, data: &[u8], _flags: usize) -> Result<()> {
594+
let socket = get_socket_locked(socket)?;
595+
596+
let Some(pipe) = socket.pipe.as_ref().cloned() else {
597+
return Err(Error::BAD_FILE_DESCRIPTOR);
598+
};
599+
600+
drop(socket);
601+
602+
pipe.send_slice(data);
603+
604+
return Ok(());
605+
}
606+
607+
/// recv data from a socket
608+
///
609+
/// [`hyperion_syscall::recv`]
610+
pub fn recv(args: &mut SyscallRegs) -> Result<usize> {
611+
let socket = SocketDesc(args.arg0 as _);
612+
let buf = read_untrusted_bytes_mut(args.arg1, args.arg2)?;
613+
let flags = args.arg3 as _;
614+
615+
_recv(socket, buf, flags)
616+
}
617+
618+
fn _recv(socket: SocketDesc, buf: &mut [u8], _flags: usize) -> Result<usize> {
619+
let socket = get_socket_locked(socket)?;
620+
621+
let Some(pipe) = socket.pipe.as_ref().cloned() else {
622+
return Err(Error::BAD_FILE_DESCRIPTOR);
623+
};
624+
625+
drop(socket);
626+
627+
let bytes = pipe.recv_slice(buf);
628+
629+
return Ok(bytes);
630+
}
631+
652632
//
653633

654634
struct ProcessExtra {
@@ -711,6 +691,26 @@ impl ProcessExt for ProcessExtra {
711691

712692
//
713693

694+
fn get_socket_locked(socket: SocketDesc) -> Result<ArcMutexGuard<Futex, SocketFile>> {
695+
get_socket(socket).map(|v| v.lock_arc())
696+
}
697+
698+
fn get_socket(socket: SocketDesc) -> Result<Arc<Mutex<SocketFile>>> {
699+
let this = process();
700+
let ext = process_ext_with(&this);
701+
702+
let socket = ext
703+
.sockets
704+
.lock()
705+
.get(socket.0)
706+
.and_then(|s| s.as_ref())
707+
.ok_or(Error::BAD_FILE_DESCRIPTOR)?
708+
.socket_ref
709+
.clone();
710+
711+
Ok(socket)
712+
}
713+
714714
fn process_ext_with(proc: &Process) -> &ProcessExtra {
715715
proc.ext
716716
.call_once(|| {

crates/sample-elf/src/io.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use alloc::{format, string::String, vec::Vec};
1+
use alloc::{string::String, vec::Vec};
22
use core::slice::memchr;
33

44
//
@@ -11,7 +11,9 @@ pub struct SimpleIpcInputChannel;
1111

1212
impl Read for SimpleIpcInputChannel {
1313
fn recv(&mut self, buf: &mut [u8]) -> Result<usize, String> {
14-
hyperion_syscall::recv(buf).map_err(|err| format!("failed to recv: {err}"))
14+
_ = buf;
15+
todo!()
16+
// hyperion_syscall::recv(buf).map_err(|err| format!("failed to recv: {err}"))
1517
}
1618
}
1719

crates/sample-elf/src/main.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@ pub fn main(_args: CliArgs) {
4040

4141
bind(server, "/dev/server.sock").unwrap();
4242

43-
let _conn = accept(server).unwrap();
43+
let conn = accept(server).unwrap();
4444

4545
println!("connected");
4646

47-
// TODO: send(conn, b"Hello").unwrap();
47+
send(conn, b"Hello", 0).unwrap();
4848
});
4949

5050
// wait for the server to be up
@@ -56,10 +56,11 @@ pub fn main(_args: CliArgs) {
5656

5757
println!("connected");
5858

59-
// TODO:
60-
// let mut buf = [0u8; 64];
61-
// let len = recv(client, &mut buf).unwrap();
62-
// assert_eq!(&buf[..len], b"Hello");
59+
let mut buf = [0u8; 64];
60+
let len = recv(client, &mut buf, 0).unwrap();
61+
assert_eq!(&buf[..len], b"Hello");
62+
63+
println!("got `{:?}`", core::str::from_utf8(&buf[..len]));
6364

6465
/* match args.iter().next().expect("arg0 to be present") {
6566
// busybox style single binary 'coreutils'

crates/syscall/src/lib.rs

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,16 @@ pub mod id {
3030
pub const RECV: usize = 12;
3131
pub const RENAME: usize = 13;
3232

33-
pub const OPEN: usize = 1000;
34-
pub const CLOSE: usize = 1100;
35-
pub const READ: usize = 1200;
36-
pub const WRITE: usize = 1300;
33+
pub const OPEN: usize = 14;
34+
pub const CLOSE: usize = 15;
35+
pub const READ: usize = 16;
36+
pub const WRITE: usize = 17;
3737

38-
pub const SOCKET: usize = 2000;
39-
pub const BIND: usize = 2100;
40-
pub const LISTEN: usize = 2200;
41-
pub const ACCEPT: usize = 2300;
42-
pub const CONNECT: usize = 2400;
38+
pub const SOCKET: usize = 18;
39+
pub const BIND: usize = 19;
40+
pub const LISTEN: usize = 20;
41+
pub const ACCEPT: usize = 21;
42+
pub const CONNECT: usize = 22;
4343
}
4444

4545
//
@@ -168,17 +168,6 @@ pub fn pfree(ptr: NonNull<u8>, pages: usize) -> Result<()> {
168168
unsafe { syscall_2(id::PFREE, ptr.as_ptr() as usize, pages) }.map(|_| {})
169169
}
170170

171-
/// send data to a PID based single naïve IPC channel
172-
#[inline(always)]
173-
pub fn send(target: usize, data: &[u8]) -> Result<()> {
174-
unsafe { syscall_3(id::SEND, target, data.as_ptr() as usize, data.len()) }.map(|_| {})
175-
}
176-
177-
/// read data from a PID based single naïve IPC channel
178-
pub fn recv(buf: &mut [u8]) -> Result<usize> {
179-
unsafe { syscall_2(id::RECV, buf.as_mut_ptr() as usize, buf.len()) }
180-
}
181-
182171
/// rename the current process
183172
#[inline(always)]
184173
pub fn rename(new_name: &str) -> Result<()> {
@@ -247,3 +236,16 @@ pub fn accept(socket: SocketDesc) -> Result<SocketDesc> {
247236
pub fn connect(socket: SocketDesc, addr: &str) -> Result<()> {
248237
unsafe { syscall_3(id::CONNECT, socket.0, addr.as_ptr() as _, addr.len()) }.map(|_| {})
249238
}
239+
240+
/// send data to a socket
241+
#[inline(always)]
242+
pub fn send(socket: SocketDesc, data: &[u8], flags: usize) -> Result<()> {
243+
let (data, data_len) = (data.as_ptr() as usize, data.len());
244+
unsafe { syscall_4(id::SEND, socket.0, data, data_len, flags) }.map(|_| {})
245+
}
246+
247+
/// read data from a socket
248+
pub fn recv(socket: SocketDesc, buf: &mut [u8], flags: usize) -> Result<usize> {
249+
let (buf, buf_len) = (buf.as_ptr() as usize, buf.len());
250+
unsafe { syscall_4(id::RECV, socket.0, buf, buf_len, flags) }
251+
}

0 commit comments

Comments
 (0)