Swift standard library on platforms without threading support?

stdlib
webassembly
avr
cross-compilation

(Max Desiatov) #1

I'm very interested know if there's an easy way to get existing Swift standard library working on platforms that don't support threading, like AVR and WebAssembly.

From what I saw in the standard library and runtime source code, there's a strong assumption of threading support in stdlib, e.g. all reference counting code relies on working <atomic> header, which can't be imported on platforms without threading:

#ifdef _LIBCPP_HAS_NO_THREADS
#error <atomic> is not supported on this single threaded system
#endif

Maybe someone have already done some work to port the standard library and runtime to an environment without threading support or maybe there's some preprocessor or build script configuration flag that I missed?

Thanks.


(Amir Abbas Mousavian) #2

I'm not a developer of Swift or stdlib but I think there is a good chance that move-only types proposed for Swift 5 would solve this issue.


(Joe Groff) #3

@carlos4242 has been working on an alternative standard library implementation for AVR:

It would be interesting to add a configuration flag to disable threading support in the "normal" runtime and standard library. Nobody's done that yet to my knowledge. For that specific issue, though, it is incorrect to avoid using <atomic> in a single-threaded system; I'm not sure why that #if is there. <atomic> is still meaningful for a single-threaded system for atomicity relative to signals and other preemption mechanisms.


#4

As far as I understand move only types will not be introduced with Swift 5, there is no such proposal, but there is consensus that they should come eventually someday and somehow. Current proposals that mention and are motivated by the introduction of move only types aim to avoid post Swift 5 ABI breakage, when they really become an issue…


(Joe Groff) #5

Move-only types won't impact whether the runtime needs to be thread safe on multithreaded platforms.


(Carl Peto) #6

My uStdlib is very, very basic and is almost more of a research project than anything else. I'm very happy to share what I have and the progress/thoughts I'm making but I'm wondering where is best to put it? It's not production ready in any way (and may never be any time soon). Also it's currently fairly heavily slanted to the sort of things i personally want in my AVR code.

What would be a good way to share it?

(The 16 bit pointer fixes for the compiler will come as a separate PR which I think will be mergeable. The PR for AVR support on it's own will be a different patch!)


(Max Desiatov) #7

Well, that's what libcxx has there at the moment ¯\_(ツ)_/¯

I'm not quite sure though if signals make any sense on WebAssembly or AVR, especially if programs for the latter are supposed to run on bare metal?

What would be the best approach for this then? My initial plan was to do something like

#ifndef __wasm__ 
#include <atomic> 
#endif

in Swift runtime headers and to reimplement all users of <atomic> with a nonatomic #ifdefed version? Or maybe it's worth implementing something like SingleThreadedAtomic.{h,cpp} that would stub all required atomic primitives with single-threaded "no-op" implementation?


(Joe Groff) #8

I’m not familiar enough with wasm, but on bare metal hardware platforms, interrupts could still be a concern. It’s unfortunate libc++ doesn’t have a single-threaded atomic implementation, but having a stubbed-out version of atomic, mutex, and other synchronization primitives would be nice to minimize the amount of conditional code we need in the runtime itself.


(Andrew Bennett) #9

Just FYI, JavaScript has Atomics in its spec, but it has more or less been stalled for the last 3 years, probably due to security vulnerabilities (Spectre and Meltdown). https://tc39.github.io/ecma262/#sec-atomics-object

Discussions suggest it’s only temporarily disabled, but I wouldn’t hold my breath https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer

There currently isn’t good browser support https://caniuse.com/#feat=sharedarraybuffer

I think it’s intended that WebAssembly gets a similar implementation after MVP. But I imagine it will have the same implementation complexities. https://github.com/WebAssembly/threads/blob/master/proposals/threads/Overview.md

Overall with that in mind I think this is the most pragmatic, expedient, maintainable, and future proof solution:


(Joe Groff) #10

It seems like those Atomics would primarily be for use with shared memory among web workers, since Javascript is not normally multithreaded. The Swift runtime would probably not allocate runtime data structures for a process into shared memory, so it doesn't seem immediately necessary to use those.


(Andrew Bennett) #11

Yeah, I don’t think there’s any immediate need for trying to use WASM atomics, especially as the equivalent is barely supported in JavaScript.

I just wanted to make sure those resources were known, as there seemed to be some uncertainty in this thread about WASM’s current and future threading capabilities.

Those are the only atomics in WASM. The last link describes their use well, but it’s only for shared memory. From that link;

All atomic memory accesses require a shared linear memory

There’s precedent for implementing malloc in linear memory in asm.js, but I’m not suggesting we do that here, they had other reasons for doing that (ie. mixing gc with manual memory management).

For context: how to implement this for Swift is still an ongoing discussion on GitHub.


(Simon Evans) #12

Do you have a link to the discussion on Github?


(Andrew Bennett) #13

The conversation tracks WASM implementation progress in general, the atomics part starts roughly here https://github.com/emscripten-core/emscripten/issues/2427#issuecomment-462747606

It’s more or less the most active discussion of progress on WASM with Swift that I’m aware of.


(Ladislas de Toldi) #14

could you share a github repo? I'd be more than happy to look at it and help if I can :)


(Ladislas de Toldi) #15

AVR does not support libc++ nor STL.

as with atomic, it is indeed needed on bare metal AVR as soon as you're dealing with 16bit or more variables* that are shared with ISR and/or threads if you're using a RTOS.

*for 8-bit AVR MCU