@@ -20,24 +20,69 @@ use crate::ptr;
20
20
///
21
21
/// # Example
22
22
///
23
- /// ```no_run
24
- /// use std::alloc::{GlobalAlloc, Layout, alloc};
23
+ /// ```
24
+ /// use std::alloc::{GlobalAlloc, Layout};
25
+ /// use std::cell::UnsafeCell;
25
26
/// use std::ptr::null_mut;
27
+ /// use std::sync::atomic::{
28
+ /// AtomicUsize,
29
+ /// Ordering::{Acquire, SeqCst},
30
+ /// };
26
31
///
27
- /// struct MyAllocator;
28
- ///
29
- /// unsafe impl GlobalAlloc for MyAllocator {
30
- /// unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { null_mut() }
31
- /// unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
32
+ /// const ARENA_SIZE: usize = 128 * 1024;
33
+ /// const MAX_SUPPORTED_ALIGN: usize = 4096;
34
+ /// #[repr(C, align(4096))] // 4096 == MAX_SUPPORTED_ALIGN
35
+ /// struct SimpleAllocator {
36
+ /// arena: UnsafeCell<[u8; ARENA_SIZE]>,
37
+ /// remaining: AtomicUsize, // we allocate from the top, counting down
32
38
/// }
33
39
///
34
40
/// #[global_allocator]
35
- /// static A: MyAllocator = MyAllocator;
41
+ /// static ALLOCATOR: SimpleAllocator = SimpleAllocator {
42
+ /// arena: UnsafeCell::new([0x55; ARENA_SIZE]),
43
+ /// remaining: AtomicUsize::new(ARENA_SIZE),
44
+ /// };
36
45
///
37
- /// fn main() {
38
- /// unsafe {
39
- /// assert!(alloc(Layout::new::<u32>()).is_null())
46
+ /// unsafe impl Sync for SimpleAllocator {}
47
+ ///
48
+ /// unsafe impl GlobalAlloc for SimpleAllocator {
49
+ /// unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
50
+ /// let size = layout.size();
51
+ /// let align = layout.align();
52
+ ///
53
+ /// // `Layout` contract forbids making a `Layout` with align=0, or align not power of 2.
54
+ /// // So we can safely use a mask to ensure alignment without worrying about UB.
55
+ /// let align_mask_to_round_down = !(align - 1);
56
+ ///
57
+ /// if align > MAX_SUPPORTED_ALIGN {
58
+ /// return null_mut();
59
+ /// }
60
+ ///
61
+ /// let mut allocated = 0;
62
+ /// if self
63
+ /// .remaining
64
+ /// .fetch_update(SeqCst, SeqCst, |mut remaining| {
65
+ /// if size > remaining {
66
+ /// return None;
67
+ /// }
68
+ /// remaining -= size;
69
+ /// remaining &= align_mask_to_round_down;
70
+ /// allocated = remaining;
71
+ /// Some(remaining)
72
+ /// })
73
+ /// .is_err()
74
+ /// {
75
+ /// return null_mut();
76
+ /// };
77
+ /// (self.arena.get() as *mut u8).add(allocated)
40
78
/// }
79
+ /// unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
80
+ /// }
81
+ ///
82
+ /// fn main() {
83
+ /// let _s = format!("allocating a string!");
84
+ /// let currently = ALLOCATOR.remaining.load(Acquire);
85
+ /// println!("allocated so far: {}", ARENA_SIZE - currently);
41
86
/// }
42
87
/// ```
43
88
///
0 commit comments