|
20 | 20 | #![feature(nll)]
|
21 | 21 | #![feature(staged_api)]
|
22 | 22 | #![feature(rustc_attrs)]
|
| 23 | +#![cfg_attr( |
| 24 | + all(target_arch = "wasm32", not(target_os = "emscripten")), |
| 25 | + feature(integer_atomics, stdsimd) |
| 26 | +)] |
23 | 27 | #![cfg_attr(any(unix, target_os = "cloudabi", target_os = "redox"), feature(libc))]
|
24 | 28 | #![rustc_alloc_kind = "lib"]
|
25 | 29 |
|
@@ -331,29 +335,76 @@ mod platform {
|
331 | 335 | use core::alloc::{GlobalAlloc, Layout};
|
332 | 336 | use System;
|
333 | 337 |
|
334 |
| - // No need for synchronization here as wasm is currently single-threaded |
335 | 338 | static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::DLMALLOC_INIT;
|
336 | 339 |
|
337 | 340 | #[stable(feature = "alloc_system_type", since = "1.28.0")]
|
338 | 341 | unsafe impl GlobalAlloc for System {
|
339 | 342 | #[inline]
|
340 | 343 | unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
| 344 | + let _lock = lock::lock(); |
341 | 345 | DLMALLOC.malloc(layout.size(), layout.align())
|
342 | 346 | }
|
343 | 347 |
|
344 | 348 | #[inline]
|
345 | 349 | unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
|
| 350 | + let _lock = lock::lock(); |
346 | 351 | DLMALLOC.calloc(layout.size(), layout.align())
|
347 | 352 | }
|
348 | 353 |
|
349 | 354 | #[inline]
|
350 | 355 | unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
| 356 | + let _lock = lock::lock(); |
351 | 357 | DLMALLOC.free(ptr, layout.size(), layout.align())
|
352 | 358 | }
|
353 | 359 |
|
354 | 360 | #[inline]
|
355 | 361 | unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
|
| 362 | + let _lock = lock::lock(); |
356 | 363 | DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size)
|
357 | 364 | }
|
358 | 365 | }
|
| 366 | + |
| 367 | + #[cfg(target_feature = "atomics")] |
| 368 | + mod lock { |
| 369 | + use core::arch::wasm32; |
| 370 | + use core::sync::atomic::{AtomicI32, Ordering::SeqCst}; |
| 371 | + |
| 372 | + static LOCKED: AtomicI32 = AtomicI32::new(0); |
| 373 | + |
| 374 | + pub struct DropLock; |
| 375 | + |
| 376 | + pub fn lock() -> DropLock { |
| 377 | + loop { |
| 378 | + if LOCKED.swap(1, SeqCst) == 0 { |
| 379 | + return DropLock |
| 380 | + } |
| 381 | + unsafe { |
| 382 | + let r = wasm32::atomic::wait_i32( |
| 383 | + &LOCKED as *const AtomicI32 as *mut i32, |
| 384 | + 1, // expected value |
| 385 | + -1, // timeout |
| 386 | + ); |
| 387 | + debug_assert!(r == 0 || r == 1); |
| 388 | + } |
| 389 | + } |
| 390 | + } |
| 391 | + |
| 392 | + impl Drop for DropLock { |
| 393 | + fn drop(&mut self) { |
| 394 | + let r = LOCKED.swap(0, SeqCst); |
| 395 | + debug_assert_eq!(r, 1); |
| 396 | + unsafe { |
| 397 | + wasm32::atomic::wake( |
| 398 | + &LOCKED as *const AtomicI32 as *mut i32, |
| 399 | + 1, // only one thread |
| 400 | + ); |
| 401 | + } |
| 402 | + } |
| 403 | + } |
| 404 | + } |
| 405 | + |
| 406 | + #[cfg(not(target_feature = "atomics"))] |
| 407 | + mod lock { |
| 408 | + pub fn lock() {} // no atomics, no threads, that's easy! |
| 409 | + } |
359 | 410 | }
|
0 commit comments