1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
use alloc::boxed::Box;
use crate::errno::*;
use crate::synch::semaphore::Semaphore;
/// Create a new, unnamed semaphore.
///
/// This function can be used to get the raw memory location of a semaphore.
///
/// Stores the raw memory location of the new semaphore in parameter `sem`.
/// Returns `0` on success, `-EINVAL` if `sem` is null.
extern "C" fn __sys_sem_init(sem: *mut *mut Semaphore, value: u32) -> i32 {
if sem.is_null() {
return -EINVAL;
}
// Create a new boxed semaphore and return a pointer to the raw memory.
let boxed_semaphore = Box::new(Semaphore::new(value as isize));
unsafe {
*sem = Box::into_raw(boxed_semaphore);
}
0
}
#[no_mangle]
pub extern "C" fn sys_sem_init(sem: *mut *mut Semaphore, value: u32) -> i32 {
kernel_function!(__sys_sem_init(sem, value))
}
/// Destroy and deallocate a semaphore.
///
/// This function can be used to manually deallocate a semaphore via a reference.
///
/// Returns `0` on success, `-EINVAL` if `sem` is null.
extern "C" fn __sys_sem_destroy(sem: *mut Semaphore) -> i32 {
if sem.is_null() {
return -EINVAL;
}
// Consume the pointer to the raw memory into a Box again
// and drop the Box to free the associated memory.
unsafe {
drop(Box::from_raw(sem));
}
0
}
#[no_mangle]
pub extern "C" fn sys_sem_destroy(sem: *mut Semaphore) -> i32 {
kernel_function!(__sys_sem_destroy(sem))
}
/// Release a semaphore.
///
/// This function can be used to allow the next blocked waiter to access this semaphore.
/// It will notify the next waiter that `sem` is available.
/// The semaphore is not deallocated after being released.
///
/// Returns `0` on success, or `-EINVAL` if `sem` is null.
extern "C" fn __sys_sem_post(sem: *const Semaphore) -> i32 {
if sem.is_null() {
return -EINVAL;
}
// Get a reference to the given semaphore and release it.
let semaphore = unsafe { &*sem };
semaphore.release();
0
}
#[no_mangle]
pub extern "C" fn sys_sem_post(sem: *const Semaphore) -> i32 {
kernel_function!(__sys_sem_post(sem))
}
/// Try to acquire a lock on a semaphore.
///
/// This function does not block if the acquire fails.
/// If the acquire fails (i.e. the semaphore's count is already 0), the function returns immediately.
///
/// Returns `0` on lock acquire, `-EINVAL` if `sem` is null, or `-ECANCELED` if the decrement fails.
extern "C" fn __sys_sem_trywait(sem: *const Semaphore) -> i32 {
if sem.is_null() {
return -EINVAL;
}
// Get a reference to the given semaphore and acquire it in a non-blocking fashion.
let semaphore = unsafe { &*sem };
if semaphore.try_acquire() {
0
} else {
-ECANCELED
}
}
#[no_mangle]
pub extern "C" fn sys_sem_trywait(sem: *const Semaphore) -> i32 {
kernel_function!(__sys_sem_trywait(sem))
}
/// Try to acquire a lock on a semaphore, blocking for a given amount of milliseconds.
///
/// Blocks until semaphore is acquired or until wake-up time has elapsed.
///
/// Returns `0` on lock acquire, `-EINVAL` if sem is null, or `-ETIME` on timeout.
extern "C" fn __sys_sem_timedwait(sem: *const Semaphore, ms: u32) -> i32 {
if sem.is_null() {
return -EINVAL;
}
let delay = if ms > 0 { Some(u64::from(ms)) } else { None };
// Get a reference to the given semaphore and wait until we have acquired it or the wakeup time has elapsed.
let semaphore = unsafe { &*sem };
if semaphore.acquire(delay) {
0
} else {
-ETIME
}
}
#[no_mangle]
pub extern "C" fn sys_sem_timedwait(sem: *const Semaphore, ms: u32) -> i32 {
kernel_function!(__sys_sem_timedwait(sem, ms))
}
extern "C" fn __sys_sem_cancelablewait(sem: *const Semaphore, ms: u32) -> i32 {
sys_sem_timedwait(sem, ms)
}
#[no_mangle]
pub extern "C" fn sys_sem_cancelablewait(sem: *const Semaphore, ms: u32) -> i32 {
kernel_function!(__sys_sem_cancelablewait(sem, ms))
}