rs_alloc/
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 mod hash;
42pub mod vec;
43pub mod hashmap;
44pub mod string;
45
46pub use vec::*;
47pub use hashmap::*;
48pub use string::*;
49
50pub unsafe fn realloc_fallback(
51    alloc: &System,
52    ptr: *mut u8,
53    old_layout: Layout,
54    new_size: usize,
55) -> *mut u8 {
56    // Docs for GlobalAlloc::realloc require this to be valid:
57    let new_layout = Layout::from_size_align_unchecked(new_size, old_layout.align());
58
59    let new_ptr = GlobalAlloc::alloc(alloc, new_layout);
60    if !new_ptr.is_null() {
61        let size = cmp::min(old_layout.size(), new_size);
62        ptr::copy_nonoverlapping(ptr, new_ptr, size);
63        GlobalAlloc::dealloc(alloc, ptr, old_layout);
64    }
65    new_ptr
66}
67
68pub const sysalloc : System = System;
69
70pub unsafe fn alloc<T>() -> *mut T {
71     sysalloc.alloc(Layout::new::<T>()) as *mut rs_ctypes::c_void as *mut T
72}
73
74pub unsafe fn free<T>(t: *mut T) {
75    sysalloc.dealloc(t as *mut u8, Layout::new::<T>());
76}
77
78// TODO: change this to const generics when they become stable and return a slice
79pub unsafe fn alloc_array<T>(res_count: usize) -> *mut T {
80    let l = Layout::array::<T>(res_count);
81    match l {
82        Ok(layout) => sysalloc.alloc(layout) as *mut T,
83        _ => panic!("unable to create layout")
84    }
85}
86
87pub unsafe fn alloc_array_zeroed<T>(res_count: usize) -> *mut T {
88    let l = Layout::array::<T>(res_count);
89    match l {
90        Ok(layout) => sysalloc.alloc_zeroed(layout) as *mut T,
91        _ => panic!("unable to create layout")
92    }
93}
94
95// TODO: change this to slice once const generics stable
96pub unsafe fn free_array<T>(ptr: *mut T, count: usize, res_count: usize) {
97    if count > res_count {
98        panic!("count exceeded reserved count")
99    }
100
101    let arr      = core::slice::from_raw_parts_mut(ptr, count); // this will keep a pointer (will not free it)
102    for i in 0..count {
103        ::core::ptr::drop_in_place(&arr[i] as *const T as *mut T);
104    }
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// TODO: change this to slice once const generics stable
113pub unsafe fn free_array_ptr<T>(ptr: *mut T, count: usize) {
114    let l = Layout::array::<T>(count);
115    match l {
116        Ok(layout) => sysalloc.dealloc(ptr as *mut u8, layout),
117        _ => panic!("unable to create layout")
118    }
119}
120
121
122////////////////////////////////////////////////////////////////////////////////
123/// TODO: remove these when the alloc handler stabilize in alloc
124////////////////////////////////////////////////////////////////////////////////
125#[repr(C)]
126pub struct Unique<T: ?Sized> {
127    ptr         : *mut T,
128    _marker     : ::core::marker::PhantomData<T>,
129}
130
131impl<T: ?Sized> Unique<T> {
132    pub fn new(ptr: *mut T) -> Self { Self { ptr : ptr, _marker: ::core::marker::PhantomData } }
133    pub fn get_mut_ptr(&mut self) -> *mut T { self.ptr }
134    pub fn get_ptr(&self) -> *const T { self.ptr }
135}
136
137#[repr(C)]
138pub struct Box<T: ?Sized>{
139    uptr: Unique<T>
140}
141
142impl<T: ?Sized> Drop for Box<T> {
143    fn drop(&mut self) {
144        unsafe {
145            ::core::ptr::drop_in_place(self.uptr.get_mut_ptr());
146            let addr = self.uptr.get_mut_ptr() as *mut u8;  // TODO: this is a hack to pass thin to fat type conversion error
147            free(addr);
148        }
149    }
150}
151
152impl<T: Sized> Box<T> {
153    #[inline(always)]
154    pub fn new(x: T) -> Self {
155        unsafe {
156            let addr = alloc::<T>();
157            ptr::write(addr, x);
158            Self { uptr: Unique::new(addr) }
159        }
160    }
161
162    pub fn unbox(self) -> T {
163        unsafe {
164            let ptr = self.uptr.ptr;
165            let v = Self::into_raw(self).read();
166            free(ptr);
167            v
168        }
169    }
170
171    pub fn get_unique(&mut self) -> &mut Unique<T> {
172        &mut self.uptr
173    }
174}
175
176
177impl<T: ?Sized> Box<T> {
178    pub fn as_ref(&self) -> &T { unsafe { &(*self.uptr.get_ptr()) } }
179    pub fn as_mut(&mut self) -> &T { unsafe { &mut (*self.uptr.get_mut_ptr()) } }
180    pub fn into_raw(this: Self) -> *mut T {
181        let m = ::core::mem::ManuallyDrop::new(this);
182        m.uptr.ptr
183    }
184
185    pub fn from_raw(raw: *mut T) -> Self {
186        Self { uptr: Unique::new(raw) }
187    }
188}
189
190
191#[repr(C)]
192struct ArcCell<T: ?Sized> {
193    count: AtomicIsize,
194    data: T,
195}
196
197impl<T: ?Sized> ArcCell<T> {
198    pub fn count(&self) -> isize {
199        self.count.load(Ordering::Relaxed)
200    }
201
202    pub fn inc(&mut self) {
203        self.count.fetch_add(1, Ordering::SeqCst);
204    }
205
206    pub fn dec(&mut self) -> isize { self.count.fetch_sub(1, Ordering::SeqCst) }
207}
208
209pub struct Arc<T: ?Sized>(*mut ArcCell<T>);
210
211impl<T: ?Sized> Arc<T> {
212    pub fn as_ptr(this: &Arc<T>) -> *const T {
213        unsafe { &(*this.0).data as *const T }
214    }
215}
216
217impl<T: Sized> Arc<T> {
218    pub fn new(x: T) -> Self {
219        unsafe {
220            let addr = alloc::<ArcCell<T>>();
221            ptr::write(addr, ArcCell { data: x, count: AtomicIsize::new(1) });
222            Self(addr)
223        }
224    }
225}
226
227impl<T: ?Sized> Drop for Arc<T> {
228    fn drop(&mut self) {
229        unsafe {
230            let s = &mut (*self.0);
231            if s.dec() == 1 {
232                ::core::ptr::drop_in_place(self.0);
233                let addr = self.0 as *mut u8;  // TODO: this is a hack to pass thin to fat type conversion error
234                free(addr);
235            }
236        }
237    }
238}
239
240impl<T: ?Sized> Clone for Arc<T> {
241    fn clone(&self) -> Self {
242        unsafe {
243            let s = &mut (*self.0);
244            s.inc();
245            Self(self.0)
246        }
247    }
248}
249
250
251impl<T: ?Sized> core::ops::Deref for Arc<T> {
252    type Target = T;
253    fn deref(&self) -> &Self::Target {
254        unsafe { &(*self.0).data }
255    }
256}
257
258impl<T: ?Sized> AsRef<T> for Arc<T> {
259    fn as_ref(&self) -> &T {
260        unsafe { &(*self.0).data }
261    }
262}
263
264unsafe impl<T: ?Sized> Send for Arc<T> {}
265unsafe impl<T: ?Sized> Sync for Arc<T> {}
266
267#[cfg(test)]
268mod tests {
269    use super::*;
270    extern crate std;
271
272    #[test]
273    fn testDrop() {
274        let _b0 = Box::new(1234);
275        let _b1 = Box::new(1234345);
276        let mut v = std::vec::Vec::new();
277        for i in 0..100 {
278            v.push(i);
279        }
280        let _bv = Box::new(v);
281    }
282
283    #[test]
284    fn testDropVecVec() {
285        let _b0 = Box::new(1234);
286        let _b1 = Box::new(1234345);
287        let mut v = std::vec::Vec::new();
288        for _ in 0..100 {
289            let mut vj = std::vec::Vec::new();
290            for j in 0..100 {
291                vj.push(j);
292            }
293            v.push(vj);
294        }
295        let _bv = Box::new(v);
296    }
297
298    #[test]
299    fn testBoxUnbox() {
300        let b = Box::new(1234);
301        let _v = b.unbox();
302    }
303
304    #[test]
305    fn testBoxUnboxVecVec() {
306        let _b0 = Box::new(1234);
307        let _b1 = Box::new(1234345);
308        let mut v = std::vec::Vec::new();
309        for _ in 0..100 {
310            let mut vj = std::vec::Vec::new();
311            for j in 0..100 {
312                vj.push(j);
313            }
314            v.push(vj);
315        }
316        let v2 = Box::new(v);
317        let _v3 = v2.unbox();
318    }
319
320    #[test]
321    fn testBoxFromToRaw() {
322        let b = Box::new(1234);
323        let r = Box::into_raw(b);
324        let _b = Box::from_raw(r);
325    }
326
327
328    trait TestTrait : Drop {
329        fn blabla(&self);
330    }
331
332    struct TestStruct {
333        a: std::vec::Vec<usize>
334    }
335
336    impl TestTrait for TestStruct {
337        fn blabla(&self) {}
338    }
339
340    impl Drop for TestStruct {
341        fn drop(&mut self) {
342        }
343    }
344
345    struct TestStruct2 {
346        t: Box<dyn TestTrait>
347    }
348
349    #[test]
350    fn testTrait() {
351        let mut v = std::vec::Vec::new();
352        v.push(123);
353        v.push(456);
354        let a = Box::new(TestStruct { a: v });
355        let _ = Box::from_raw(Box::into_raw(a) as *mut dyn TestTrait);
356    }
357
358    #[test]
359    fn testArc() {
360        let mut v = std::vec::Vec::new();
361        v.push(123);
362        v.push(456);
363        let _ = Arc::new(TestStruct { a: v });
364    }
365
366    #[test]
367    fn testArcRef() {
368        let mut v = std::vec::Vec::new();
369        v.push(123);
370        v.push(456);
371        let a = Arc::new(TestStruct { a: v });
372        let d = a.as_ref();
373        assert_eq!(d.a[0], 123);
374        assert_eq!(d.a[1], 456);
375        let f = &*a;
376        assert_eq!(f.a[0], 123);
377        assert_eq!(f.a[1], 456);
378    }
379}