sys.rs 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. //! System primitives.
  2. extern crate ralloc_shim as shim;
  3. use prelude::*;
  4. use core::mem;
  5. /// The BRK mutex.
  6. ///
  7. /// This is used for avoiding data races in multiple allocator.
  8. static BRK_MUTEX: Mutex<()> = Mutex::new(());
  9. /// Increment data segment of this process by some, _n_, return a pointer to the new data segment
  10. /// start.
  11. ///
  12. /// This uses the system call BRK as backend.
  13. ///
  14. /// # Safety
  15. ///
  16. /// This is safe unless you have negative or overflowing `n`.
  17. #[inline]
  18. pub unsafe fn sbrk(n: isize) -> Result<*mut u8, ()> {
  19. // Lock the BRK mutex.
  20. #[cfg(not(feature = "unsafe_no_brk_lock"))]
  21. let _guard = BRK_MUTEX.lock();
  22. let brk = shim::sbrk(n);
  23. if brk as usize == !0 {
  24. Err(())
  25. } else {
  26. Ok(brk as *mut u8)
  27. }
  28. }
  29. /// Cooperatively gives up a timeslice to the OS scheduler.
  30. pub fn yield_now() {
  31. assert_eq!(unsafe { shim::sched_yield() }, 0);
  32. }
  33. /// Register a thread destructor.
  34. ///
  35. /// This will add a thread destructor to _the current thread_, which will be executed when the
  36. /// thread exits.
  37. ///
  38. /// The argument to the destructor is a pointer to the so-called "load", which is the data
  39. /// shipped with the destructor.
  40. // TODO I haven't figured out a safe general solution yet. Libstd relies on devirtualization,
  41. // which, when missed, can make it quite expensive.
  42. pub fn register_thread_destructor<T>(load: *mut T, dtor: extern fn(*mut T)) -> Result<(), ()> {
  43. // Check if thread dtors are supported.
  44. if shim::thread_destructor::is_supported() {
  45. unsafe {
  46. // This is safe due to sharing memory layout.
  47. shim::thread_destructor::register(load as *mut u8, mem::transmute(dtor));
  48. }
  49. Ok(())
  50. } else {
  51. Err(())
  52. }
  53. }
  54. /// Write text to the log.
  55. ///
  56. /// The log target is defined by the `shim` crate.
  57. // TODO find a better way to silence the warning than this attribute
  58. #[allow(dead_code)]
  59. pub fn log(s: &str) -> Result<(), ()> {
  60. if shim::log(s) == -1 { Err(()) } else { Ok(()) }
  61. }
  62. #[cfg(test)]
  63. mod test {
  64. use super::*;
  65. #[test]
  66. fn test_oom() {
  67. unsafe {
  68. assert!(sbrk(9999999999999).is_err());
  69. }
  70. }
  71. }