Rollup merge of #77722 - fusion-engineering-forks:safe-unsupported-locks, r=Mark-Simulacrum

Remove unsafety from sys/unsupported and add deny(unsafe_op_in_unsafe_fn).

Replacing `UnsafeCell`s by a `Cell`s simplifies things and makes the mutex and rwlock implementations safe. Other than that, only unsafety in strlen() contained unsafe code.

@rustbot modify labels: +F-unsafe-block-in-unsafe-fn +C-cleanup
This commit is contained in:
Yuki Okushi 2020-10-14 06:02:21 +09:00 committed by GitHub
commit cc5a1aad4e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 34 additions and 37 deletions

View file

@ -39,10 +39,13 @@ pub fn hashmap_random_keys() -> (u64, u64) {
pub enum Void {}
pub unsafe fn strlen(mut s: *const c_char) -> usize {
let mut n = 0;
while *s != 0 {
n += 1;
s = s.offset(1);
// SAFETY: The caller must guarantee `s` points to a valid 0-terminated string.
unsafe {
let mut n = 0;
while *s != 0 {
n += 1;
s = s.offset(1);
}
n
}
return n;
}

View file

@ -1,3 +1,5 @@
#![deny(unsafe_op_in_unsafe_fn)]
pub mod alloc;
pub mod args;
pub mod cmath;

View file

@ -1,7 +1,8 @@
use crate::cell::UnsafeCell;
use crate::cell::Cell;
pub struct Mutex {
locked: UnsafeCell<bool>,
// This platform has no threads, so we can use a Cell here.
locked: Cell<bool>,
}
pub type MovableMutex = Mutex;
@ -11,7 +12,7 @@ unsafe impl Sync for Mutex {} // no threads on this platform
impl Mutex {
pub const fn new() -> Mutex {
Mutex { locked: UnsafeCell::new(false) }
Mutex { locked: Cell::new(false) }
}
#[inline]
@ -19,25 +20,17 @@ pub unsafe fn init(&mut self) {}
#[inline]
pub unsafe fn lock(&self) {
let locked = self.locked.get();
assert!(!*locked, "cannot recursively acquire mutex");
*locked = true;
assert_eq!(self.locked.replace(true), false, "cannot recursively acquire mutex");
}
#[inline]
pub unsafe fn unlock(&self) {
*self.locked.get() = false;
self.locked.set(false);
}
#[inline]
pub unsafe fn try_lock(&self) -> bool {
let locked = self.locked.get();
if *locked {
false
} else {
*locked = true;
true
}
self.locked.replace(true) == false
}
#[inline]

View file

@ -1,7 +1,8 @@
use crate::cell::UnsafeCell;
use crate::cell::Cell;
pub struct RWLock {
mode: UnsafeCell<isize>,
// This platform has no threads, so we can use a Cell here.
mode: Cell<isize>,
}
unsafe impl Send for RWLock {}
@ -9,14 +10,14 @@ unsafe impl Sync for RWLock {} // no threads on this platform
impl RWLock {
pub const fn new() -> RWLock {
RWLock { mode: UnsafeCell::new(0) }
RWLock { mode: Cell::new(0) }
}
#[inline]
pub unsafe fn read(&self) {
let mode = self.mode.get();
if *mode >= 0 {
*mode += 1;
let m = self.mode.get();
if m >= 0 {
self.mode.set(m + 1);
} else {
rtabort!("rwlock locked for writing");
}
@ -24,9 +25,9 @@ pub unsafe fn read(&self) {
#[inline]
pub unsafe fn try_read(&self) -> bool {
let mode = self.mode.get();
if *mode >= 0 {
*mode += 1;
let m = self.mode.get();
if m >= 0 {
self.mode.set(m + 1);
true
} else {
false
@ -35,19 +36,15 @@ pub unsafe fn try_read(&self) -> bool {
#[inline]
pub unsafe fn write(&self) {
let mode = self.mode.get();
if *mode == 0 {
*mode = -1;
} else {
if self.mode.replace(-1) != 0 {
rtabort!("rwlock locked for reading")
}
}
#[inline]
pub unsafe fn try_write(&self) -> bool {
let mode = self.mode.get();
if *mode == 0 {
*mode = -1;
if self.mode.get() == 0 {
self.mode.set(-1);
true
} else {
false
@ -56,12 +53,12 @@ pub unsafe fn try_write(&self) -> bool {
#[inline]
pub unsafe fn read_unlock(&self) {
*self.mode.get() -= 1;
self.mode.set(self.mode.get() - 1);
}
#[inline]
pub unsafe fn write_unlock(&self) {
*self.mode.get() += 1;
assert_eq!(self.mode.replace(0), -1);
}
#[inline]

View file

@ -53,6 +53,7 @@
pub mod time;
#[path = "../unsupported/common.rs"]
#[deny(unsafe_op_in_unsafe_fn)]
#[allow(unused)]
mod common;
pub use common::*;

View file

@ -66,5 +66,6 @@
}
#[path = "../unsupported/common.rs"]
#[deny(unsafe_op_in_unsafe_fn)]
mod common;
pub use common::*;