Introducing macros for defining SchemeId, Pid, ...

This commit is contained in:
David Teller 2016-11-13 13:59:58 +01:00
parent 86650e4579
commit 9f7c20bacf
3 changed files with 116 additions and 0 deletions

108
kernel/common/int_like.rs Normal file
View file

@ -0,0 +1,108 @@
//! Helpers used to define types that are backed by integers (typically `usize`),
//! without compromising safety.
//!
//! # Example
//!
//! ```
//! /// Define an opaque type `Pid` backed by a `usize`.
//! int_like!(Pid, usize);
//!
//! const ZERO: Pid = Pid::from(0);
//! ```
//!
//! # Example
//!
//! ```
//! /// Define opaque types `Pid` and `AtomicPid`, backed respectively by a `usize`
//! /// and a `AtomicUsize`.
//!
//! int_like!(Pid, AtomicPid, usize, AtomicUsize);
//!
//! const ZERO: Pid = Pid::from(0);
//! let ATOMIC_PID: AtomicPid = AtomicPid::default();
//! ```
#[macro_export]
macro_rules! int_like {
($new_type_name:ident, $backing_type: ident) => {
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
pub struct $new_type_name($backing_type);
impl $new_type_name {
pub const fn into(self) -> $backing_type {
self.0
}
pub const fn from(x: $backing_type) -> Self {
$new_type_name(x)
}
}
};
($new_type_name:ident, $new_atomic_type_name: ident, $backing_type:ident, $backing_atomic_type:ident) => {
int_like!($new_type_name, $backing_type);
/// A mutable holder for T that can safely be shared among threads.
/// Runtime equivalent to using `AtomicUsize`, just type-safer.
pub struct $new_atomic_type_name {
container: $backing_atomic_type,
}
impl $new_atomic_type_name {
pub const fn new(x: $new_type_name) -> Self {
$new_atomic_type_name {
container: $backing_atomic_type::new(x.into())
}
}
pub const fn default() -> Self {
Self::new($new_type_name::from(0))
}
pub fn load(&self, order: ::core::sync::atomic::Ordering) -> $new_type_name {
$new_type_name::from(self.container.load(order))
}
pub fn store(&self, val: $new_type_name, order: ::core::sync::atomic::Ordering) {
self.container.store(val.into(), order)
}
#[allow(dead_code)]
pub fn swap(&self, val: $new_type_name, order: ::core::sync::atomic::Ordering) -> $new_type_name {
$new_type_name::from(self.container.swap(val.into(), order))
}
#[allow(dead_code)]
pub fn compare_and_swap(&self, current: $new_type_name, new: $new_type_name, order: ::core::sync::atomic::Ordering) -> $new_type_name {
$new_type_name::from(self.container.compare_and_swap(current.into(), new.into(), order))
}
#[allow(dead_code)]
pub fn compare_exchange(&self, current: $new_type_name, new: $new_type_name, success: ::core::sync::atomic::Ordering, failure: ::core::sync::atomic::Ordering) -> ::core::result::Result<$new_type_name, $new_type_name> {
match self.container.compare_exchange(current.into(), new.into(), success, failure) {
Ok(result) => Ok($new_type_name::from(result)),
Err(result) => Err($new_type_name::from(result))
}
}
#[allow(dead_code)]
pub fn compare_exchange_weak(&self, current: $new_type_name, new: $new_type_name, success: ::core::sync::atomic::Ordering, failure: ::core::sync::atomic::Ordering) -> ::core::result::Result<$new_type_name, $new_type_name> {
match self.container.compare_exchange_weak(current.into(), new.into(), success, failure) {
Ok(result) => Ok($new_type_name::from(result)),
Err(result) => Err($new_type_name::from(result))
}
}
}
}
}
#[cfg(test)]
fn test() {
use core::mem::size_of;
use ::core::sync::atomic::AtomicUsize;
// Generate type `usize_like`.
int_like!(UsizeLike, usize);
const ZERO: UsizeLike = UsizeLike::from(0);
assert_eq!(size_of::<UsizeLike>(), size_of::<usize>());
// Generate types `usize_like` and `AtomicUsize`.
int_like!(UsizeLike2, AtomicUsizeLike, usize, AtomicUsize);
assert_eq!(size_of::<UsizeLike2>(), size_of::<usize>());
assert_eq!(size_of::<AtomicUsizeLike>(), size_of::<AtomicUsize>());
}

3
kernel/common/mod.rs Normal file
View file

@ -0,0 +1,3 @@
#[macro_use]
#[macro_export]
pub mod int_like;

View file

@ -47,6 +47,11 @@ use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
/// Context management
pub mod context;
#[macro_use]
/// Shared data structures
pub mod common;
/// ELF file parsing
#[cfg(all(not(test), target_arch = "x86_64"))]
pub mod elf;