Skip to content

Commit

Permalink
Use std::os::fd
Browse files Browse the repository at this point in the history
  • Loading branch information
AldaronLau committed Jan 22, 2023
1 parent 0b8745d commit a30710d
Showing 6 changed files with 58 additions and 66 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -4,6 +4,9 @@ All notable changes to `smelling_salts` will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://github.com/AldaronLau/semver).

## [0.11.0] - Unreleased


## [0.10.0] - 2023-01-18
### Changed
- Updated `whisk` to 0.10
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright © 2020-2022 The Smelling Salts Contributors.
# Copyright © 2020-2023 The Smelling Salts Contributors.
#
# Licensed under any of:
# - Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
59 changes: 25 additions & 34 deletions examples/pipe.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use std::{
convert::TryInto,
mem::{self, MaybeUninit},
os::{raw, unix::io::RawFd},
os::{
fd::{AsRawFd, FromRawFd, OwnedFd, RawFd},
raw,
},
};

use async_main::async_main;
@@ -17,26 +20,28 @@ extern "C" {
fn pipe2(pipefd: *mut [RawFd; 2], flags: raw::c_int) -> RawFd;
fn write(fd: RawFd, buf: *const raw::c_void, count: usize) -> isize;
fn read(fd: RawFd, buf: *mut raw::c_void, count: usize) -> isize;
fn close(fd: RawFd) -> raw::c_int;
}

/// A `PipeReceiver` device future.
pub struct PipeReceiver(Option<Device>);
pub struct PipeReceiver(Device);

impl Notifier for PipeReceiver {
type Event = u32;

fn poll_next(mut self: Pin<&mut Self>, task: &mut Task<'_>) -> Poll<u32> {
let device = self.0.as_mut().unwrap();
let device = &mut self.0;

if Pin::new(&mut *device).poll_next(task).is_pending() {
return Pending;
}

unsafe {
let mut x = MaybeUninit::<u32>::uninit();
if read(device.fd(), x.as_mut_ptr().cast(), mem::size_of::<u32>())
== mem::size_of::<u32>().try_into().unwrap()
if read(
device.fd().as_raw_fd(),
x.as_mut_ptr().cast(),
mem::size_of::<u32>(),
) == mem::size_of::<u32>().try_into().unwrap()
{
Ready(x.assume_init())
} else {
@@ -46,54 +51,40 @@ impl Notifier for PipeReceiver {
}
}

impl Drop for PipeReceiver {
fn drop(&mut self) {
// Remove from watchlist
let device = self.0.take().unwrap();
let fd = device.fd();
drop(device);
// Close file descriptor
let ret = unsafe { close(fd) };
assert_eq!(0, ret);
}
}

/// A `PipeSender` device.
pub struct PipeSender(RawFd);
pub struct PipeSender(OwnedFd);

impl PipeSender {
/// Send a 32-bit value over the pipe.
pub fn send(&self, value: u32) {
let data = [value];
let len: usize = unsafe {
write(self.0, data.as_ptr().cast(), mem::size_of::<u32>())
.try_into()
.unwrap()
write(
self.0.as_raw_fd(),
data.as_ptr().cast(),
mem::size_of::<u32>(),
)
.try_into()
.unwrap()
};
assert_eq!(len, mem::size_of::<u32>());
}
}

impl Drop for PipeSender {
fn drop(&mut self) {
unsafe {
let ret = close(self.0);
assert_eq!(0, ret);
}
}
}

/// Create a new `Pipe`.
pub fn pipe() -> (PipeReceiver, PipeSender) {
let [fd, sender] = unsafe {
let (fd, sender) = unsafe {
// Create pipe for communication
let mut pipe = mem::MaybeUninit::<[raw::c_int; 2]>::uninit();
let ret = pipe2(pipe.as_mut_ptr(), O_CLOEXEC | O_NONBLOCK | O_DIRECT);
assert!(ret >= 0);
pipe.assume_init()
let [fd, sender] = pipe.assume_init();
assert_ne!(fd, -1);
assert_ne!(sender, -1);
(OwnedFd::from_raw_fd(fd), OwnedFd::from_raw_fd(sender))
};

let device = Some(Device::builder().input().watch(fd));
let device = Device::builder().input().watch(fd);

(PipeReceiver(device), PipeSender(sender))
}
33 changes: 14 additions & 19 deletions examples/sleep.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use std::{
convert::TryInto,
mem::{self, MaybeUninit},
os::{raw, unix::io::RawFd},
os::{
fd::{AsRawFd, FromRawFd, OwnedFd, RawFd},
raw,
},
ptr,
time::Duration,
};
@@ -31,23 +34,10 @@ extern "C" {
old_value: *mut ITimerSpec,
) -> raw::c_int;
fn read(fd: RawFd, buf: *mut u64, count: usize) -> isize;
fn close(fd: RawFd) -> raw::c_int;
}

/// A `Timer` device future.
pub struct Timer(Option<Device>);

impl Drop for Timer {
fn drop(&mut self) {
// Remove from watchlist
let device = self.0.take().unwrap();
let fd = device.fd();
drop(device);
// Close file descriptor
let ret = unsafe { close(fd) };
assert_eq!(0, ret);
}
}
pub struct Timer(Device);

impl Timer {
/// Create a new `Timer`.
@@ -62,24 +52,29 @@ impl Timer {
};
let _ret = unsafe { timerfd_settime(fd, 0, &its, ptr::null_mut()) };
assert_eq!(0, _ret);
Self(Some(Device::builder().input().watch(fd)))
assert_ne!(fd, -1);
let fd = unsafe { OwnedFd::from_raw_fd(fd) };
Self(Device::builder().input().watch(fd))
}
}

impl Notifier for Timer {
type Event = usize;

fn poll_next(mut self: Pin<&mut Self>, task: &mut Task<'_>) -> Poll<usize> {
let device = self.0.as_mut().unwrap();
let device = &mut self.0;

if Pin::new(&mut *device).poll_next(task).is_pending() {
return Pending;
}

unsafe {
let mut x = MaybeUninit::<u64>::uninit();
if read(device.fd(), x.as_mut_ptr(), mem::size_of::<u64>())
== mem::size_of::<u64>().try_into().unwrap()
if read(
device.fd().as_raw_fd(),
x.as_mut_ptr(),
mem::size_of::<u64>(),
) == mem::size_of::<u64>().try_into().unwrap()
{
let count = x.assume_init().try_into().unwrap();
if count == 0 {
25 changes: 14 additions & 11 deletions src/epoll.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2020-2022 The Smelling Salts Contributors.
// Copyright © 2020-2023 The Smelling Salts Contributors.
//
// Licensed under any of:
// - Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
@@ -15,17 +15,15 @@
use std::{
mem::{self, MaybeUninit},
os::{
fd::{AsFd, AsRawFd, BorrowedFd, OwnedFd, RawFd},
raw::{c_int, c_void},
unix::io::RawFd,
},
sync::{Arc, Once},
};

use pasts::prelude::*;
use whisk::{Channel, Queue};

type Poll<T = ()> = pasts::prelude::Poll<T>;

const EPOLLIN: u32 = 0x0001;
const EPOLLOUT: u32 = 0x0004;
const EPOLLET: u32 = 1 << 31;
@@ -36,7 +34,7 @@ const EPOLLET: u32 = 1 << 31;
#[derive(Debug)]
pub struct Device {
channel: Channel,
fd: RawFd,
owned_fd: OwnedFd,
}

impl Device {
@@ -46,8 +44,8 @@ impl Device {
}

/// Get the file descriptor for this device
pub fn fd(&self) -> RawFd {
self.fd
pub fn fd(&self) -> BorrowedFd<'_> {
self.owned_fd.as_fd()
}
}

@@ -63,7 +61,9 @@ impl Drop for Device {
fn drop(&mut self) {
let epoll_fd = state().epoll_fd;
let mut _ev = MaybeUninit::<EpollEvent>::zeroed();
let ret = unsafe { epoll_ctl(epoll_fd, 2, self.fd, _ev.as_mut_ptr()) };
let ret = unsafe {
epoll_ctl(epoll_fd, 2, self.fd().as_raw_fd(), _ev.as_mut_ptr())
};
assert_eq!(ret, 0);
}
}
@@ -93,18 +93,21 @@ impl DeviceBuilder {
}

/// Finish building the [`Device`]
pub fn watch(self, fd: RawFd) -> Device {
pub fn watch(self, fd: impl Into<OwnedFd>) -> Device {
let owned_fd = fd.into();
let state = state();
let channel = Channel::new();
let queue: Arc<Queue> = channel.clone().into();
let ptr: *mut _ = unsafe { mem::transmute(queue) };
let data = EpollData { ptr };
let events = self.events;
let mut event = EpollEvent { events, data };
let ret = unsafe { epoll_ctl(state.epoll_fd, 1, fd, &mut event) };
let ret = unsafe {
epoll_ctl(state.epoll_fd, 1, owned_fd.as_raw_fd(), &mut event)
};
assert_eq!(ret, 0);

Device { channel, fd }
Device { channel, owned_fd }
}
}

2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2020-2022 The Smelling Salts Contributors.
// Copyright © 2020-2023 The Smelling Salts Contributors.
//
// Licensed under any of:
// - Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)

0 comments on commit a30710d

Please sign in to comment.