Skip to content
This repository has been archived by the owner on Aug 1, 2024. It is now read-only.

[WIP] Adding a tokio example #2

Closed
wants to merge 2 commits into from
Closed

Conversation

TilCreator
Copy link

@TilCreator TilCreator commented Dec 14, 2020

This example uses my Tokio fork, because Tokio doesn't know that xtensa doesn't support native atomic u64.
This example also currently still fails with:

Hello, world from Rust!
More complex print ["foo", "bar"]
Rust main thread: Thread { id: ThreadId(1), name: None }
This is thread number 1, Thread { id: ThreadId(3), name: None }
This is thread number 0, Thread { id: ThreadId(2), name: None }
This is thread number 2, Thread { id: ThreadId(4), name: None }
This is thread number 3, Thread { id: ThreadId(5), name: None }
This is thread number 4, Thread { id: ThreadId(6), name: None }
About to join the threads. If ESP-IDF was patched successfully, joining will NOT crash
Joins were successful.
Jessie: Prepare for trouble
thread 'tokio-runtime-worker' panicked at 'assertion failed: r == libc::ETIMEDOUT || r == 0', /root/projects/esp32-ivmarkov/rust/library/std/src/sys/unix/condvar.rs:102:9

(r is EINVAL in ESP-IDF components/pthread/pthread_cond_var.c:94)

I'm currently working on this from time to time, maybe someone want's to help?
(Also I don't have a Jtag debugger, so I'm doing print "debugging" on a microcontroller...)

@ivmarkov
Copy link
Owner

ESP-IDF returns EINVAL because - apparently - the condition variable is not actually initialized (that's a problem in my implementation of condvar.rs for the ESP).

When the condition variable is created, it goes via the following route:

pub const fn new() -> Condvar {
        // Might be moved and address is changing it is better to avoid
        // initialization of potentially opaque OS data before it landed
        Condvar { inner: UnsafeCell::new(libc::PTHREAD_COND_INITIALIZER) }
    }

    #[cfg(any(
        target_os = "macos",
        target_os = "ios",
        target_os = "l4re",
        target_os = "android",
        target_os = "redox",
        target_os = "none"
    ))]
    pub unsafe fn init(&mut self) {}

(NOTE: the "os" platform is set to "none" for the ESP-IDF case.)

So the point is, the "init" method does nothing on the ESP and we rely on the libc::PTHREAD_COND_INITIALIZER to do its magic. However, I cannot even find the definition of this macro in the ESP-IDF source-code, so it is very likely that it is not doing anything meaningful for that platform. We should call pthread's pthread_cond_init explicitly then, or in other words, we should direct the execution (for the ESP-IDF case) to the other init block which looks like this:

   #[cfg(not(any(
        target_os = "macos",
        target_os = "ios",
        target_os = "l4re",
        target_os = "android",
        target_os = "redox",
        target_os = "none"
    )))]
    pub unsafe fn init(&mut self) {
        use crate::mem::MaybeUninit;
        let mut attr = MaybeUninit::<libc::pthread_condattr_t>::uninit();
        let r = libc::pthread_condattr_init(attr.as_mut_ptr());
        assert_eq!(r, 0);
        let r = libc::pthread_condattr_setclock(attr.as_mut_ptr(), libc::CLOCK_MONOTONIC);
        assert_eq!(r, 0);
        let r = libc::pthread_cond_init(self.inner.get(), attr.as_ptr());
        assert_eq!(r, 0);
        let r = libc::pthread_condattr_destroy(attr.as_mut_ptr());
        assert_eq!(r, 0);
    }

Since all functions called in the above block are stubs on the ESP-IDF except the important pthread_cond_init, we might also hit an assertion where some of these functions is not returning 0 and then we'll have to conditionalize some of those calls for os = "none" and vendor = "espressif".

But I think roughly that's the way forward.

@ivmarkov
Copy link
Owner

By the way - with my toolchain, you can try doing the fixes to std's condvar.rs I suggested above and then just recompile your project with xargo clean and then xargo build --release. It should automatically grab your changes and re-build std with those. No need to re-build the whole compiler toolchain.

@ivmarkov ivmarkov marked this pull request as ready for review December 16, 2020 11:05
@TilCreator
Copy link
Author

THX! (I didn't really expected an answer, just wanted to document what I was doing somewhere. ^^)
I will try the suggested changes and write here then.

@ivmarkov
Copy link
Owner

JFYI - the condvar issue is fixed in the latest STD Rust (branch "stable").

@TilCreator
Copy link
Author

I'm currently not very active in esp rust stuff (surprising, I know ^^).
Maybe I will find time for continuing this, but I would first find my ESPs again ^^
(Anyone is of course welcome to continue work on this pr or test stuff)

@ivmarkov
Copy link
Owner

I'm closing this in light of the discussion here.

The thing is, I don't see how tokyo would work on the ESP-IDF given that ESP-IDF does not currently support neither kqueue nor epoll, which are a requirement for mio.

We might have a better luck with smol-rs in that there is a chance that it will support poll, which is also supported by the ESP-IDF.

@ivmarkov ivmarkov closed this Aug 17, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants