/__w/smoldot/smoldot/repo/wasm-node/rust/src/allocator.rs
Line | Count | Source (jump to first uncovered line) |
1 | | // Smoldot |
2 | | // Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. |
3 | | // SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 |
4 | | |
5 | | // This program is free software: you can redistribute it and/or modify |
6 | | // it under the terms of the GNU General Public License as published by |
7 | | // the Free Software Foundation, either version 3 of the License, or |
8 | | // (at your option) any later version. |
9 | | |
10 | | // This program is distributed in the hope that it will be useful, |
11 | | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | | // GNU General Public License for more details. |
14 | | |
15 | | // You should have received a copy of the GNU General Public License |
16 | | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | | |
18 | | //! This module contains the `#[global_allocator]` used by the wasm node. This allocator is very |
19 | | //! simple, apart from the fact that it counts the total number of bytes that have been allocated. |
20 | | //! This value can then be retrieved by calling [`total_alloc_bytes`]. |
21 | | |
22 | | use core::{alloc, sync::atomic}; |
23 | | |
24 | | /// Returns the total number of bytes that have been allocated through the Rust `alloc` crate |
25 | | /// throughout the entire Wasm node. |
26 | 0 | pub fn total_alloc_bytes() -> usize { |
27 | 0 | ALLOCATOR.total.load(atomic::Ordering::Relaxed) |
28 | 0 | } |
29 | | |
30 | | struct AllocCounter { |
31 | | /// Use the `dlmalloc` allocator. This is the library that the Rust standard library uses in |
32 | | /// the context of Wasm. |
33 | | /// See <https://github.com/rust-lang/rust/tree/1.47.0/library/std/src/sys/wasm>. |
34 | | inner: dlmalloc::GlobalDlmalloc, |
35 | | |
36 | | /// Total number of bytes allocated. |
37 | | total: atomic::AtomicUsize, |
38 | | } |
39 | | |
40 | | #[global_allocator] |
41 | 298 | static ALLOCATOR: AllocCounter = AllocCounter { Line | Count | Source | 41 | 148 | static ALLOCATOR: AllocCounter = AllocCounter { |
Line | Count | Source | 41 | 147 | static ALLOCATOR: AllocCounter = AllocCounter { |
Line | Count | Source | 41 | 3 | static ALLOCATOR: AllocCounter = AllocCounter { |
Unexecuted instantiation: __rust_alloc_zeroed |
42 | | inner: dlmalloc::GlobalDlmalloc, |
43 | | total: atomic::AtomicUsize::new(0), |
44 | | }; |
45 | | |
46 | | unsafe impl alloc::GlobalAlloc for AllocCounter { |
47 | 148 | unsafe fn alloc(&self, layout: alloc::Layout) -> *mut u8 { |
48 | 148 | let ret = self.inner.alloc(layout); |
49 | 148 | if !ret.is_null() { |
50 | 148 | self.total |
51 | 148 | .fetch_add(layout.size(), atomic::Ordering::Relaxed); |
52 | 148 | }0 |
53 | 148 | ret |
54 | 148 | } |
55 | | |
56 | 147 | unsafe fn dealloc(&self, ptr: *mut u8, layout: alloc::Layout) { |
57 | 147 | self.total |
58 | 147 | .fetch_sub(layout.size(), atomic::Ordering::Relaxed); |
59 | 147 | self.inner.dealloc(ptr, layout); |
60 | 147 | } |
61 | | |
62 | 0 | unsafe fn alloc_zeroed(&self, layout: alloc::Layout) -> *mut u8 { |
63 | 0 | let ret = self.inner.alloc_zeroed(layout); |
64 | 0 | if !ret.is_null() { |
65 | 0 | self.total |
66 | 0 | .fetch_add(layout.size(), atomic::Ordering::Relaxed); |
67 | 0 | } |
68 | 0 | ret |
69 | 0 | } |
70 | | |
71 | 3 | unsafe fn realloc(&self, ptr: *mut u8, layout: alloc::Layout, new_size: usize) -> *mut u8 { |
72 | 3 | let ret = self.inner.realloc(ptr, layout, new_size); |
73 | 3 | if !ret.is_null() { |
74 | 3 | if new_size >= layout.size() { |
75 | 3 | self.total |
76 | 3 | .fetch_add(new_size - layout.size(), atomic::Ordering::Relaxed); |
77 | 3 | } else { |
78 | 0 | self.total |
79 | 0 | .fetch_sub(layout.size() - new_size, atomic::Ordering::Relaxed); |
80 | 0 | } |
81 | 0 | } |
82 | 3 | ret |
83 | 3 | } |
84 | | } |