unix.rs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. extern crate libc;
  2. pub use self::libc::sched_yield;
  3. extern {
  4. /// Change the data segment. See `man sbrk`.
  5. pub fn sbrk(ptr: libc::intptr_t) -> *const libc::c_void;
  6. /// Write a buffer to a file descriptor.
  7. fn write(fd: libc::c_int, buff: *const libc::c_void, size: libc::size_t) -> libc::ssize_t;
  8. }
  9. /// Write to the log.
  10. ///
  11. /// This points to stderr, but could be changed arbitrarily.
  12. pub fn log(s: &str) -> libc::ssize_t {
  13. unsafe { write(2, s.as_ptr() as *const libc::c_void, s.len()) }
  14. }
  15. /// Thread destructors for Linux.
  16. #[cfg(target_os = "linux")]
  17. pub mod thread_destructor {
  18. use super::libc;
  19. extern {
  20. #[linkage = "extern_weak"]
  21. static __dso_handle: *mut u8;
  22. #[linkage = "extern_weak"]
  23. static __cxa_thread_atexit_impl: *const libc::c_void;
  24. }
  25. /// Does this platform support thread destructors?
  26. ///
  27. /// This will return true, if and only if `__cxa_thread_atexit_impl` is non-null.
  28. #[inline]
  29. pub fn is_supported() -> bool {
  30. unsafe { !__cxa_thread_atexit_impl.is_null() }
  31. }
  32. /// Register a thread destructor.
  33. ///
  34. /// # Safety
  35. ///
  36. /// This is unsafe due to accepting (and dereferencing) raw pointers, as well as running an
  37. /// arbitrary unsafe function.
  38. ///
  39. /// On older system without the `__cxa_thread_atexit_impl` symbol, this is unsafe to call, and will
  40. /// likely segfault.
  41. // TODO: Due to rust-lang/rust#18804, make sure this is not generic!
  42. pub unsafe fn register(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
  43. use core::mem;
  44. /// A thread destructor.
  45. type Dtor = unsafe extern fn(dtor: unsafe extern fn(*mut u8), arg: *mut u8, dso_handle: *mut u8) -> libc::c_int;
  46. mem::transmute::<*const libc::c_void, Dtor>(__cxa_thread_atexit_impl)(dtor, t, &__dso_handle as *const _ as *mut _);
  47. }
  48. }
  49. /// Thread destructors for Mac OS.
  50. #[cfg(target_os = "macos")]
  51. pub mod thread_destructor {
  52. use super::libc;
  53. /// Does this platform support thread destructors?
  54. ///
  55. /// This will always return true.
  56. #[inline]
  57. pub fn is_supported() -> bool { true }
  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. #[cfg(target_os = "macos")]
  65. pub unsafe fn register(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
  66. extern {
  67. fn _tlv_atexit(dtor: unsafe extern fn(*mut u8), arg: *mut u8);
  68. }
  69. _tlv_atexit(dtor, t);
  70. }
  71. }
  72. /// Debugging.
  73. pub mod debug {
  74. use super::libc;
  75. extern {
  76. /// Valgrind symbol to declare memory undefined.
  77. fn valgrind_make_mem_undefined(ptr: *const libc::c_void, size: libc::size_t);
  78. /// Valgrind symbol to declare memory freed.
  79. fn valgrind_freelike_block(ptr: *const libc::c_void, size: libc::size_t);
  80. }
  81. /// Mark this segment undefined to the debugger.
  82. pub fn mark_undefined(ptr: *const libc::c_void, size: libc::size_t) {
  83. unsafe { valgrind_make_mem_undefined(ptr, size) }
  84. }
  85. /// Mark this segment free to the debugger.
  86. pub fn mark_free(ptr: *const libc::c_void, size: libc::size_t) {
  87. unsafe { valgrind_freelike_block(ptr, size) }
  88. }
  89. }