Skip to main content

hotg_runicos_base_wasm/
lib.rs

1#![cfg(target_arch = "wasm32")]
2#![no_std]
3// Note: The WebAssembly bindings need to provide alloc error handling.
4#![feature(core_intrinsics, lang_items, alloc_error_handler)]
5
6extern crate alloc;
7
8pub mod allocator;
9mod buf_writer;
10mod capability;
11mod guards;
12pub mod intrinsics;
13mod logging;
14mod model;
15mod resources;
16pub mod serial;
17mod stats_allocator;
18pub mod tensor_output;
19
20pub use crate::{
21    capability::Capability,
22    guards::{SetupGuard, PipelineGuard},
23    logging::Logger,
24    model::Model,
25    serial::Serial,
26    resources::{Resource, ResourceError},
27    tensor_output::TensorOutput,
28    buf_writer::BufWriter,
29};
30
31use core::{alloc::Layout, fmt::Write, panic::PanicInfo};
32use crate::allocator::Allocator;
33use dlmalloc::GlobalDlmalloc;
34
35#[global_allocator]
36pub static ALLOCATOR: Allocator<GlobalDlmalloc> =
37    Allocator::new(GlobalDlmalloc);
38
39#[panic_handler]
40fn on_panic(info: &PanicInfo) -> ! {
41    static mut PANICKING: bool = false;
42
43    unsafe {
44        // We need to guard against the possiblity that logging a panic may
45        // in turn trigger a panic (e.g. due to OOM), causing infinite
46        // recursion.
47        if !PANICKING {
48            PANICKING = true;
49
50            // First we try to log the panic at the ERROR level. This should
51            // be translated into a runtime trap, so under most circumstances
52            // the log call won't return and our user will get a nice error
53            // message.
54            log::error!("{}", info);
55        }
56
57        // However, some times the runtime won't receive the log message (e.g.
58        // log level filtering or because an OOM in logging recursively
59        // triggered the panic handler). If that is the case, we still try to
60        // send *some* message to the runtime so they know the world is broken.
61
62        // Safety: We need our own buffer for panic messages in case the
63        // allocator is fubar. Runes are single-threaded, so we can
64        // guarantee we'll never have aliased mutation.
65        static mut DEBUG_BUFFER: [u8; 1024] = [0; 1024];
66        let mut w = BufWriter::new(&mut DEBUG_BUFFER);
67
68        if write!(w, "{}", info).is_ok() {
69            let written = w.written();
70            intrinsics::_debug(written.as_ptr(), written.len() as u32);
71        }
72
73        // And now we've done everything we can, we ungracefully crash.
74        core::arch::wasm32::unreachable()
75    }
76}
77
78#[alloc_error_handler]
79fn on_alloc_error(layout: Layout) -> ! {
80    panic!(
81        "memory allocation of {} bytes failed ({:?})",
82        layout.size(),
83        ALLOCATOR.stats()
84    );
85}