lib.rs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. //! Symbols and externs that `ralloc` depends on.
  2. //!
  3. //! This crate provides implementation/import of these in Linux, BSD, and Mac OS.
  4. //!
  5. //! # Important
  6. //!
  7. //! You CANNOT use libc library calls, due to no guarantees being made about allocations of the
  8. //! functions in the POSIX specification. Therefore, we use the system calls directly.
  9. #![feature(linkage, core_intrinsics)]
  10. #![no_std]
  11. #![warn(missing_docs)]
  12. #[macro_use]
  13. extern crate syscall;
  14. use core::intrinsics;
  15. /// Voluntarily give a time slice to the scheduler.
  16. pub fn sched_yield() -> usize {
  17. unsafe { syscall!(SCHED_YIELD) }
  18. }
  19. /// The default OOM handler.
  20. #[cold]
  21. pub fn default_oom_handler() -> ! {
  22. // Log some message.
  23. log("\x1b[31;1mThe application ran out of memory. Aborting.\n");
  24. unsafe {
  25. intrinsics::abort();
  26. }
  27. }
  28. /// Change the data segment. See `man brk`.
  29. ///
  30. /// # Note
  31. ///
  32. /// This is the `brk` **syscall**, not the library function.
  33. pub unsafe fn brk(ptr: *const u8) -> *const u8 {
  34. syscall!(BRK, ptr) as *const u8
  35. }
  36. /// Write to the log.
  37. ///
  38. /// This points to stderr, but could be changed arbitrarily.
  39. pub fn log(s: &str) -> usize {
  40. unsafe { syscall!(WRITE, 2, s.as_ptr(), s.len()) }
  41. }
  42. /// Thread destructors for Linux.
  43. #[cfg(target_os = "linux")]
  44. pub mod thread_destructor {
  45. extern {
  46. #[linkage = "extern_weak"]
  47. static __dso_handle: *mut u8;
  48. #[linkage = "extern_weak"]
  49. static __cxa_thread_atexit_impl: *const u8;
  50. }
  51. /// Does this platform support thread destructors?
  52. ///
  53. /// This will return true, if and only if `__cxa_thread_atexit_impl` is non-null.
  54. #[inline]
  55. pub fn is_supported() -> bool {
  56. !__cxa_thread_atexit_impl.is_null()
  57. }
  58. /// Register a thread destructor.
  59. ///
  60. /// # Safety
  61. ///
  62. /// This is unsafe due to accepting (and dereferencing) raw pointers, as well as running an
  63. /// arbitrary unsafe function.
  64. ///
  65. /// On older system without the `__cxa_thread_atexit_impl` symbol, this is unsafe to call, and will
  66. /// likely segfault.
  67. // TODO: Due to rust-lang/rust#18804, make sure this is not generic!
  68. pub unsafe fn register(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
  69. use core::mem;
  70. /// A thread destructor.
  71. type Dtor = unsafe extern fn(dtor: unsafe extern fn(*mut u8), arg: *mut u8, dso_handle: *mut u8) -> i32;
  72. mem::transmute::<*const u8, Dtor>(__cxa_thread_atexit_impl)(dtor, t, &__dso_handle as *const _ as *mut _);
  73. }
  74. }
  75. /// Thread destructors for Mac OS.
  76. #[cfg(target_os = "macos")]
  77. pub mod thread_destructor {
  78. /// Does this platform support thread destructors?
  79. ///
  80. /// This will always return true.
  81. #[inline]
  82. pub fn is_supported() -> bool { true }
  83. /// Register a thread destructor.
  84. ///
  85. /// # Safety
  86. ///
  87. /// This is unsafe due to accepting (and dereferencing) raw pointers, as well as running an
  88. /// arbitrary unsafe function.
  89. #[cfg(target_os = "macos")]
  90. pub unsafe fn register(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
  91. extern {
  92. fn _tlv_atexit(dtor: unsafe extern fn(*mut u8), arg: *mut u8);
  93. }
  94. _tlv_atexit(dtor, t);
  95. }
  96. }
  97. /// Debugging.
  98. pub mod debug {
  99. extern {
  100. /// Valgrind symbol to declare memory undefined.
  101. fn valgrind_make_mem_undefined(ptr: *const u8, size: usize);
  102. /// Valgrind symbol to declare memory freed.
  103. fn valgrind_freelike_block(ptr: *const u8, size: usize);
  104. }
  105. /// Mark this segment undefined to the debugger.
  106. pub fn mark_undefined(ptr: *const u8, size: usize) {
  107. unsafe { valgrind_make_mem_undefined(ptr, size) }
  108. }
  109. /// Mark this segment free to the debugger.
  110. pub fn mark_free(ptr: *const u8, size: usize) {
  111. unsafe { valgrind_freelike_block(ptr, size) }
  112. }
  113. }