rs_mem/
lib.rs

1//
2// Copyright 2020-Present (c) Raja Lehtihet & Wael El Oraiby
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6//
7// 1. Redistributions of source code must retain the above copyright notice,
8// this list of conditions and the following disclaimer.
9//
10// 2. Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
12// and/or other materials provided with the distribution.
13//
14// 3. Neither the name of the copyright holder nor the names of its contributors
15// may be used to endorse or promote products derived from this software without
16// specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28// POSSIBILITY OF SUCH DAMAGE.
29//
30#![no_std]
31#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
32#[allow(improper_ctypes)]
33
34use core::alloc::*;
35use core::*;
36use core::sync::atomic::*;
37
38mod os;
39use os::*;
40
41pub unsafe fn realloc_fallback(
42    alloc: &System,
43    ptr: *mut u8,
44    old_layout: Layout,
45    new_size: usize,
46) -> *mut u8 {
47    // Docs for GlobalAlloc::realloc require this to be valid:
48    let new_layout = Layout::from_size_align_unchecked(new_size, old_layout.align());
49
50    let new_ptr = GlobalAlloc::alloc(alloc, new_layout);
51    if !new_ptr.is_null() {
52        let size = cmp::min(old_layout.size(), new_size);
53        ptr::copy_nonoverlapping(ptr, new_ptr, size);
54        GlobalAlloc::dealloc(alloc, ptr, old_layout);
55    }
56    new_ptr
57}
58
59pub const sysalloc : System = System;
60
61pub unsafe fn alloc<T>() -> *mut T {
62     sysalloc.alloc(Layout::new::<T>()) as *mut rs_ctypes::c_void as *mut T
63}
64
65pub unsafe fn free<T>(t: *mut T) {
66    sysalloc.dealloc(t as *mut u8, Layout::new::<T>());
67}
68
69// TODO: change this to const generics when they become stable and return a slice
70pub unsafe fn alloc_array<T>(res_count: usize) -> *mut T {
71    let l = Layout::array::<T>(res_count);
72    match l {
73        Ok(layout) => sysalloc.alloc(layout) as *mut T,
74        _ => panic!("unable to create layout")
75    }
76}
77
78pub unsafe fn alloc_array_zeroed<T>(res_count: usize) -> *mut T {
79    let l = Layout::array::<T>(res_count);
80    match l {
81        Ok(layout) => sysalloc.alloc_zeroed(layout) as *mut T,
82        _ => panic!("unable to create layout")
83    }
84}
85
86// TODO: change this to slice once const generics stable
87pub unsafe fn free_array<T>(ptr: *mut T, count: usize, res_count: usize) {
88    if count > res_count {
89        panic!("count exceeded reserved count")
90    }
91
92    let arr      = core::slice::from_raw_parts_mut(ptr, count); // this will keep a pointer (will not free it)
93    for i in 0..count {
94        ::core::ptr::drop_in_place(&arr[i] as *const T as *mut T);
95    }
96    let l = Layout::array::<T>(count);
97    match l {
98        Ok(layout) => sysalloc.dealloc(ptr as *mut u8, layout),
99        _ => panic!("unable to create layout")
100    }
101}
102
103// TODO: change this to slice once const generics stable
104pub unsafe fn free_array_ptr<T>(ptr: *mut T, count: usize) {
105    let l = Layout::array::<T>(count);
106    match l {
107        Ok(layout) => sysalloc.dealloc(ptr as *mut u8, layout),
108        _ => panic!("unable to create layout")
109    }
110}
111
112
113////////////////////////////////////////////////////////////////////////////////
114/// TODO: remove these when the alloc handler stabilize in alloc
115////////////////////////////////////////////////////////////////////////////////
116#[repr(C)]
117pub struct Unique<T: ?Sized> {
118    ptr         : *mut T,
119    _marker     : ::core::marker::PhantomData<T>,
120}
121
122impl<T: ?Sized> Unique<T> {
123    pub fn new(ptr: *mut T) -> Self { Self { ptr : ptr, _marker: ::core::marker::PhantomData } }
124    pub fn get_mut_ptr(&mut self) -> *mut T { self.ptr }
125    pub fn get_ptr(&self) -> *const T { self.ptr }
126}
127
128#[repr(C)]
129pub struct Box<T: ?Sized>{
130    uptr: Unique<T>
131}
132
133impl<T: ?Sized> Drop for Box<T> {
134    fn drop(&mut self) {
135        unsafe {
136            ::core::ptr::drop_in_place(self.uptr.get_mut_ptr());
137            let addr = self.uptr.get_mut_ptr() as *mut u8;  // TODO: this is a hack to pass thin to fat type conversion error
138            free(addr);
139        }
140    }
141}
142
143impl<T: Sized> Box<T> {
144    #[inline(always)]
145    pub fn new(x: T) -> Self {
146        unsafe {
147            let addr = alloc::<T>();
148            ptr::write(addr, x);
149            Self { uptr: Unique::new(addr) }
150        }
151    }
152
153    pub fn unbox(self) -> T {
154        unsafe {
155            let ptr = self.uptr.ptr;
156            let v = Self::into_raw(self).read();
157            free(ptr);
158            v
159        }
160    }
161
162    pub fn get_unique(&mut self) -> &mut Unique<T> {
163        &mut self.uptr
164    }
165}
166
167
168impl<T: ?Sized> Box<T> {
169    pub fn as_ref(&self) -> &T { unsafe { &(*self.uptr.get_ptr()) } }
170    pub fn as_mut(&mut self) -> &T { unsafe { &mut (*self.uptr.get_mut_ptr()) } }
171    pub fn into_raw(this: Self) -> *mut T {
172        let m = ::core::mem::ManuallyDrop::new(this);
173        m.uptr.ptr
174    }
175
176    pub fn from_raw(raw: *mut T) -> Self {
177        Self { uptr: Unique::new(raw) }
178    }
179}
180
181
182#[repr(C)]
183struct ArcCell<T: ?Sized> {
184    count: AtomicIsize,
185    data: T,
186}
187
188impl<T: ?Sized> ArcCell<T> {
189    pub fn count(&self) -> isize {
190        self.count.load(Ordering::Relaxed)
191    }
192
193    pub fn inc(&mut self) {
194        self.count.fetch_add(1, Ordering::SeqCst);
195    }
196
197    pub fn dec(&mut self) -> isize { self.count.fetch_sub(1, Ordering::SeqCst) }
198}
199
200pub struct Arc<T: ?Sized>(*mut ArcCell<T>);
201
202impl<T: ?Sized> Arc<T> {
203    pub fn as_ptr(this: &Arc<T>) -> *const T {
204        unsafe { &(*this.0).data as *const T }
205    }
206}
207
208impl<T: Sized> Arc<T> {
209    pub fn new(x: T) -> Self {
210        unsafe {
211            let addr = alloc::<ArcCell<T>>();
212            ptr::write(addr, ArcCell { data: x, count: AtomicIsize::new(1) });
213            Self(addr)
214        }
215    }
216}
217
218impl<T: ?Sized> Drop for Arc<T> {
219    fn drop(&mut self) {
220        unsafe {
221            let s = &mut (*self.0);
222            if s.dec() == 1 {
223                ::core::ptr::drop_in_place(self.0);
224                let addr = self.0 as *mut u8;  // TODO: this is a hack to pass thin to fat type conversion error
225                free(addr);
226            }
227        }
228    }
229}
230
231impl<T: ?Sized> Clone for Arc<T> {
232    fn clone(&self) -> Self {
233        unsafe {
234            let s = &mut (*self.0);
235            s.inc();
236            Self(self.0)
237        }
238    }
239}
240
241
242impl<T: ?Sized> core::ops::Deref for Arc<T> {
243    type Target = T;
244    fn deref(&self) -> &Self::Target {
245        unsafe { &(*self.0).data }
246    }
247}
248
249impl<T: ?Sized> AsRef<T> for Arc<T> {
250    fn as_ref(&self) -> &T {
251        unsafe { &(*self.0).data }
252    }
253}
254
255unsafe impl<T: ?Sized> Send for Arc<T> {}
256unsafe impl<T: ?Sized> Sync for Arc<T> {}
257
258#[cfg(test)]
259mod tests {
260    use super::*;
261    extern crate std;
262
263    #[test]
264    fn testDrop() {
265        let _b0 = Box::new(1234);
266        let _b1 = Box::new(1234345);
267        let mut v = std::vec::Vec::new();
268        for i in 0..100 {
269            v.push(i);
270        }
271        let _bv = Box::new(v);
272    }
273
274    #[test]
275    fn testDropVecVec() {
276        let _b0 = Box::new(1234);
277        let _b1 = Box::new(1234345);
278        let mut v = std::vec::Vec::new();
279        for _ in 0..100 {
280            let mut vj = std::vec::Vec::new();
281            for j in 0..100 {
282                vj.push(j);
283            }
284            v.push(vj);
285        }
286        let _bv = Box::new(v);
287    }
288
289    #[test]
290    fn testBoxUnbox() {
291        let b = Box::new(1234);
292        let _v = b.unbox();
293    }
294
295    #[test]
296    fn testBoxUnboxVecVec() {
297        let _b0 = Box::new(1234);
298        let _b1 = Box::new(1234345);
299        let mut v = std::vec::Vec::new();
300        for _ in 0..100 {
301            let mut vj = std::vec::Vec::new();
302            for j in 0..100 {
303                vj.push(j);
304            }
305            v.push(vj);
306        }
307        let v2 = Box::new(v);
308        let _v3 = v2.unbox();
309    }
310
311    #[test]
312    fn testBoxFromToRaw() {
313        let b = Box::new(1234);
314        let r = Box::into_raw(b);
315        let _b = Box::from_raw(r);
316    }
317
318
319    trait TestTrait : Drop {
320        fn blabla(&self);
321    }
322
323    struct TestStruct {
324        a: std::vec::Vec<usize>
325    }
326
327    impl TestTrait for TestStruct {
328        fn blabla(&self) {}
329    }
330
331    impl Drop for TestStruct {
332        fn drop(&mut self) {
333        }
334    }
335
336    struct TestStruct2 {
337        t: Box<dyn TestTrait>
338    }
339
340    #[test]
341    fn testTrait() {
342        let mut v = std::vec::Vec::new();
343        v.push(123);
344        v.push(456);
345        let a = Box::new(TestStruct { a: v });
346        let _ = Box::from_raw(Box::into_raw(a) as *mut dyn TestTrait);
347    }
348
349    #[test]
350    fn testArc() {
351        let mut v = std::vec::Vec::new();
352        v.push(123);
353        v.push(456);
354        let _ = Arc::new(TestStruct { a: v });
355    }
356
357    #[test]
358    fn testArcRef() {
359        let mut v = std::vec::Vec::new();
360        v.push(123);
361        v.push(456);
362        let a = Arc::new(TestStruct { a: v });
363        let d = a.as_ref();
364        assert_eq!(d.a[0], 123);
365        assert_eq!(d.a[1], 456);
366        let f = &*a;
367        assert_eq!(f.a[0], 123);
368        assert_eq!(f.a[1], 456);
369    }
370}