Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • martin/relibc
  • ashton/relibc
  • vincent/relibc
  • boomshroom/relibc
  • gmacd/relibc
  • mati865/relibc
  • nicoan/relibc
  • lmiskiew/relibc
  • devnexen/relibc
  • jamesgraves/relibc
  • oddcoder/relibc
  • andar1an/relibc
  • bitstr0m/relibc
  • gugz0r/relibc
  • matijaskala/relibc
  • redox-os/relibc
  • 4lDO2/relibc
  • arthurpaulino/relibc
  • Majoneza/relibc
  • enygmator/relibc
  • njskalski/relibc
  • JustAnotherDev/relibc
  • doriancodes/relibc
  • adamantinum/relibc
  • wiredtv/relibc
  • stratact/relibc
  • Ramla-I/relibc
  • bpisch/relibc
  • henritel/relibc
  • smckay/relibc
  • xTibor/relibc
  • devajithvs/relibc
  • t-nil/relibc
  • zen3ger/relibc
  • DataTriny/relibc
  • SteveLauC/relibc
  • dlrobertson/relibc
  • TheDarkula/relibc
  • josh/relibc
  • willnode/relibc
  • GrayJack/relibc
  • raffaeleragni/relibc
  • redoxeon/relibc
  • darley/relibc
  • ayf/relibc
  • heghe/relibc
  • Ivan/relibc
  • hasheddan/relibc
  • dahc/relibc
  • auwardoctor/relibc
  • kodicraft/relibc
  • jasonhansel/relibc
  • kel/relibc
  • microcolonel/relibc
  • sahitpj/relibc
  • plimkilde/relibc
  • BjornTheProgrammer/relibc
  • defra/relibc
  • jD91mZM2/relibc
  • Schyrsivochter/relibc
  • ebalalic/relibc
  • adchacon/relibc
  • aaronjanse/relibc
  • josh_williams/relibc
  • andypython/relibc
  • 8tab/relibc
  • AgostonSzepessy/relibc
  • athei/relibc
  • carrot93/relibc
  • bamontan/relibc
  • zhaozhao/relibc
  • JCake/relibc
  • KGrewal1/relibc
  • feliwir/relibc
  • emturner/relibc
  • LuigiPiucco/relibc
  • RA_GM1/relibc
  • bfrascher/relibc
  • kcired/relibc
  • jamespcfrancis/relibc
  • omar-mohamed-khallaf/relibc
  • neallred/relibc
  • rw_van/relibc
  • Skallwar/relibc
  • matt-vdv/relibc
  • SoyaOhnishi/relibc
  • ArniDagur/relibc
  • tlam/relibc
  • glongo/relibc
  • kamirr/relibc
  • abdullah/relibc
  • saeedtabrizi/relibc
  • sajattack/relibc
  • seanpk/relibc
  • MaikuZ/relibc
  • jamadazi/relibc
  • coolreader18/relibc
  • wt/relibc
  • lebensterben/relibc
  • starsheriff/relibc
  • uuuvn/relibc
  • vadorovsky/relibc
  • ids1024/relibc
  • freewilll/relibc
  • LLeny/relibc
  • batonius/relibc
  • alfredoyang/relibc
  • TornaxO7/relibc
  • bjorn3/relibc
  • Arcterus/relibc
  • Tommoa/relibc
  • samuela/relibc
  • mindriot101/relibc
  • lygstate/relibc
114 results
Show changes
Commits on Source (2)
......@@ -235,15 +235,32 @@ impl Pal for Sys {
e(unsafe { syscall!(FTRUNCATE, fildes, length) }) as c_int
}
fn futex(
addr: *mut c_int,
op: c_int,
val: c_int,
val2: usize,
) -> Result<c_long, crate::pthread::Errno> {
e_raw(unsafe { syscall!(FUTEX, addr, op, val, val2, 0, 0) })
.map(|r| r as c_long)
.map_err(|e| crate::pthread::Errno(e as c_int))
#[inline]
unsafe fn futex_wait(
addr: *mut u32,
val: u32,
deadline: *const timespec,
) -> Result<(), crate::pthread::Errno> {
e_raw(unsafe {
syscall!(
FUTEX, addr, // uaddr
9, // futex_op: FUTEX_WAIT_BITSET
val, // val
deadline, // timeout: deadline
0, // uaddr2/val2: 0/NULL
0xffffffff // val3: FUTEX_BITSET_MATCH_ANY
)
})
.map_err(|e| crate::pthread::Errno(e as c_int))
.map(|_| ())
}
#[inline]
unsafe fn futex_wake(addr: *mut u32, num: u32) -> Result<c_int, crate::pthread::Errno> {
e_raw(unsafe {
syscall!(FUTEX, addr, 1 /* FUTEX_WAKE */, num)
})
.map_err(|e| crate::pthread::Errno(e as c_int))
.map(|n| n as c_int)
}
fn futimens(fd: c_int, times: *const timespec) -> c_int {
......
......@@ -10,6 +10,7 @@ use crate::{
sys_utsname::utsname,
time::timespec,
},
pthread,
};
pub use self::epoll::PalEpoll;
......@@ -78,12 +79,12 @@ pub trait Pal {
fn ftruncate(fildes: c_int, length: off_t) -> c_int;
fn futex(
addr: *mut c_int,
op: c_int,
val: c_int,
val2: usize,
) -> Result<c_long, crate::pthread::Errno>;
unsafe fn futex_wait(
addr: *mut u32,
val: u32,
deadline: *const timespec,
) -> Result<(), pthread::Errno>;
unsafe fn futex_wake(addr: *mut u32, num: u32) -> Result<c_int, pthread::Errno>;
fn futimens(fd: c_int, times: *const timespec) -> c_int;
......
......@@ -24,6 +24,7 @@ use crate::{
unistd::{F_OK, R_OK, W_OK, X_OK},
},
io::{self, prelude::*, BufReader},
pthread,
};
pub use redox_exec::FdGuard;
......@@ -300,25 +301,35 @@ impl Pal for Sys {
e(syscall::ftruncate(fd as usize, len as usize)) as c_int
}
// FIXME: unsound
fn futex(
addr: *mut c_int,
op: c_int,
val: c_int,
val2: usize,
) -> Result<c_long, crate::pthread::Errno> {
match unsafe {
syscall::futex(
addr as *mut i32,
op as usize,
val as i32,
val2,
ptr::null_mut(),
)
} {
Ok(success) => Ok(success as c_long),
Err(err) => Err(crate::pthread::Errno(err.errno)),
}
#[inline]
unsafe fn futex_wait(
addr: *mut u32,
val: u32,
deadline: *const timespec,
) -> CoreResult<(), pthread::Errno> {
syscall::syscall5(
syscall::SYS_FUTEX,
addr as usize,
syscall::FUTEX_WAIT,
val as usize,
deadline as usize,
0,
)
.map_err(|s| pthread::Errno(s.errno))
.map(|_| ())
}
#[inline]
unsafe fn futex_wake(addr: *mut u32, num: u32) -> Result<c_int, pthread::Errno> {
syscall::syscall5(
syscall::SYS_FUTEX,
addr as usize,
syscall::FUTEX_WAKE,
num as usize,
0,
0,
)
.map_err(|s| pthread::Errno(s.errno))
.map(|n| n as c_int)
}
// FIXME: unsound
......@@ -1106,7 +1117,7 @@ impl Pal for Sys {
fn verify() -> bool {
// GETPID on Redox is 20, which is WRITEV on Linux
e(unsafe { syscall::syscall5(syscall::number::SYS_GETPID, !0, !0, !0, !0, !0) }) != !0
(unsafe { syscall::syscall5(syscall::number::SYS_GETPID, !0, !0, !0, !0, !0) }).is_ok()
}
fn exit_thread() -> ! {
......
......@@ -74,7 +74,7 @@ impl Cond {
unlock: impl FnOnce() -> Result<()>,
lock: impl FnOnce() -> Result<()>,
lock_with_timeout: impl FnOnce(&timespec) -> Result<()>,
timeout: Option<&timespec>,
deadline: Option<&timespec>,
) -> Result<(), Errno> {
// TODO: Error checking for certain types (i.e. robust and errorcheck) of mutexes, e.g. if the
// mutex is not locked.
......@@ -83,14 +83,10 @@ impl Cond {
unlock();
match timeout {
Some(timeout) => {
crate::sync::futex_wait(
&self.cur,
current,
timespec::subtract(*timeout, crate::sync::rttime()).as_ref(),
);
lock_with_timeout(timeout);
match deadline {
Some(deadline) => {
crate::sync::futex_wait(&self.cur, current, Some(&deadline));
lock_with_timeout(deadline);
}
None => {
crate::sync::futex_wait(&self.cur, current, None);
......
......@@ -16,8 +16,12 @@ pub use self::{
};
use crate::{
header::time::timespec,
header::{
errno::{EAGAIN, ETIMEDOUT},
time::timespec,
},
platform::{types::*, Pal, Sys},
pthread::Errno,
};
use core::{
mem::MaybeUninit,
......@@ -36,7 +40,7 @@ pub enum AttemptStatus {
}
pub trait FutexTy {
fn conv(self) -> i32;
fn conv(self) -> u32;
}
pub trait FutexAtomicTy {
type Ty: FutexTy;
......@@ -44,13 +48,13 @@ pub trait FutexAtomicTy {
fn ptr(&self) -> *mut Self::Ty;
}
impl FutexTy for u32 {
fn conv(self) -> i32 {
self as i32
fn conv(self) -> u32 {
self
}
}
impl FutexTy for i32 {
fn conv(self) -> i32 {
self
fn conv(self) -> u32 {
self as u32
}
}
impl FutexAtomicTy for AtomicU32 {
......@@ -91,20 +95,26 @@ impl FutexAtomicTy for AtomicI32 {
pub unsafe fn futex_wake_ptr(ptr: *mut impl FutexTy, n: i32) -> usize {
// TODO: unwrap_unchecked?
Sys::futex(ptr.cast(), FUTEX_WAKE, n, 0).unwrap() as usize
Sys::futex_wake(ptr.cast(), n as u32).unwrap() as usize
}
pub unsafe fn futex_wait_ptr<T: FutexTy>(
ptr: *mut T,
value: T,
timeout_opt: Option<&timespec>,
) -> bool {
// TODO: unwrap_unchecked?
Sys::futex(
deadline_opt: Option<&timespec>,
) -> FutexWaitResult {
match Sys::futex_wait(
ptr.cast(),
FUTEX_WAIT,
value.conv(),
timeout_opt.map_or(0, |t| t as *const _ as usize),
) == Ok(0)
deadline_opt.map_or(core::ptr::null(), |t| t as *const _),
) {
Ok(()) => FutexWaitResult::Waited,
Err(Errno(EAGAIN)) => FutexWaitResult::Stale,
Err(Errno(ETIMEDOUT)) if deadline_opt.is_some() => FutexWaitResult::TimedOut,
Err(other) => {
eprintln!("futex failed: {}", other.0);
FutexWaitResult::Waited
}
}
}
pub fn futex_wake(atomic: &impl FutexAtomicTy, n: i32) -> usize {
unsafe { futex_wake_ptr(atomic.ptr(), n) }
......@@ -112,9 +122,16 @@ pub fn futex_wake(atomic: &impl FutexAtomicTy, n: i32) -> usize {
pub fn futex_wait<T: FutexAtomicTy>(
atomic: &T,
value: T::Ty,
timeout_opt: Option<&timespec>,
) -> bool {
unsafe { futex_wait_ptr(atomic.ptr(), value, timeout_opt) }
deadline_opt: Option<&timespec>,
) -> FutexWaitResult {
unsafe { futex_wait_ptr(atomic.ptr(), value, deadline_opt) }
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum FutexWaitResult {
Waited, // possibly spurious
Stale, // outdated value
TimedOut,
}
pub fn rttime() -> timespec {
......@@ -187,7 +204,7 @@ impl AtomicLock {
pub fn wait_if(&self, value: c_int, timeout_opt: Option<&timespec>) {
self.wait_if_raw(value, timeout_opt);
}
pub fn wait_if_raw(&self, value: c_int, timeout_opt: Option<&timespec>) -> bool {
pub fn wait_if_raw(&self, value: c_int, timeout_opt: Option<&timespec>) -> FutexWaitResult {
futex_wait(&self.atomic, value, timeout_opt)
}
......
......@@ -10,6 +10,8 @@ use crate::{
use crate::platform::{types::*, Pal, Sys};
use super::FutexWaitResult;
pub struct RlctMutex {
// Actual locking word.
inner: AtomicUint,
......@@ -123,7 +125,11 @@ impl RlctMutex {
// If the mutex is not robust, simply futex_wait until unblocked.
//crate::sync::futex_wait(&self.inner, inner | WAITING_BIT, None);
crate::sync::futex_wait(&self.inner, thread, None);
if crate::sync::futex_wait(&self.inner, thread, deadline)
== FutexWaitResult::TimedOut
{
return Err(Errno(ETIMEDOUT));
}
}
}
}
......
......@@ -21,7 +21,7 @@ impl Rwlock {
state: AtomicU32::new(0),
}
}
pub fn acquire_write_lock(&self, _timeout: Option<&timespec>) {
pub fn acquire_write_lock(&self, deadline: Option<&timespec>) {
let mut waiting_wr = self.state.load(Ordering::Relaxed) & WAITING_WR;
loop {
......@@ -45,16 +45,15 @@ impl Rwlock {
};
waiting_wr = expected & WAITING_WR;
// TODO: timeout
let _ = crate::sync::futex_wait(&self.state, expected, None);
let _ = crate::sync::futex_wait(&self.state, expected, deadline);
}
}
}
}
pub fn acquire_read_lock(&self, _timeout: Option<&timespec>) {
pub fn acquire_read_lock(&self, deadline: Option<&timespec>) {
// TODO: timeout
while let Err(old) = self.try_acquire_read_lock() {
crate::sync::futex_wait(&self.state, old, None);
crate::sync::futex_wait(&self.state, old, deadline);
}
}
pub fn try_acquire_read_lock(&self) -> Result<(), u32> {
......
......@@ -186,6 +186,7 @@ NAMES=\
pthread/rwlock_trylock \
pthread/rwlock_randtest \
pthread/mutex_recursive \
pthread/timeout \
grp/getgrouplist \
grp/getgrgid_r \
grp/getgrnam_r \
......
#include "../test_helpers.h"
#include "common.h"
#include <errno.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
struct arg {
int status;
bool completed;
pthread_barrier_t barrier;
pthread_mutex_t mutex;
};
void *routine(void *arg_raw) {
struct arg *arg = (struct arg *)arg_raw;
int barrier_status = pthread_barrier_wait(&arg->barrier);
if (barrier_status != 0 && barrier_status != PTHREAD_BARRIER_SERIAL_THREAD) {
arg->status = barrier_status;
fputs("failed to wait for barrier\n", stderr);
return NULL;
}
puts("thread waited");
struct timespec abstime;
if ((arg->status = clock_gettime(CLOCK_MONOTONIC, &abstime)) != 0) {
fputs("failed to get current time\n", stderr);
return NULL;
}
abstime.tv_sec += 1;
if ((arg->status = pthread_mutex_timedlock(&arg->mutex, &abstime)) != ETIMEDOUT) {
fputs("failed to fail at locking mutex\n", stderr);
return NULL;
}
arg->status = 0;
return NULL;
}
int main(void) {
int status;
struct arg arg;
arg.completed = false;
status = pthread_barrier_init(&arg.barrier, NULL, 2);
ERROR_IF2(pthread_barrier_init, status, != 0);
status = pthread_mutex_init(&arg.mutex, NULL);
ERROR_IF2(pthread_mutex_init, status, != 0);
status = pthread_mutex_trylock(&arg.mutex);
ERROR_IF2(pthread_mutex_trylock, status, != 0);
pthread_t thread;
status = pthread_create(&thread, NULL, routine, &arg);
ERROR_IF2(pthread_create, status, != 0);
status = pthread_barrier_wait(&arg.barrier);
if (status != PTHREAD_BARRIER_SERIAL_THREAD) {
ERROR_IF2(pthread_barrier_wait, status, != 0);
}
puts("main waited");
status = pthread_join(thread, NULL);
ERROR_IF2(pthread_join, status, != 0);
status = pthread_mutex_unlock(&arg.mutex);
ERROR_IF2(pthread_mutex_unlock, status, != 0);
if (arg.status != 0) {
fprintf(stderr, "thread failed: %s\n", strerror(arg.status));
return EXIT_FAILURE;
}
status = pthread_mutex_destroy(&arg.mutex);
ERROR_IF2(pthread_mutex_destroy, status, != 0);
status = pthread_barrier_destroy(&arg.barrier);
ERROR_IF2(pthread_barrier_destroy, status, != 0);
return EXIT_SUCCESS;
}
......@@ -46,6 +46,15 @@
} \
} while(0)
#define ERROR_IF2(func, status, condition) \
do { \
if (status condition) { \
fprintf(stderr, "%s:%s:%d: '%s' failed: %s (%d)\n", \
__FILE__, __func__, __LINE__, #func, strerror(status), status); \
_exit(EXIT_FAILURE); \
} \
} while(0)
// Throws errors on API return values not defined by the standards.
//
// Do not pass functions as the status or condition arguments, they might be
......