From 4b281af0f73297ef675f0aba0b1d3f3f13ffa623 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 24 Aug 2016 18:09:51 +0800 Subject: [PATCH] newlib locking: Turns out the "hack" is the way to make stdout thread-safe in newlib --- components/esp32/syscalls.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/components/esp32/syscalls.c b/components/esp32/syscalls.c index 8978154240..92bc33374a 100644 --- a/components/esp32/syscalls.c +++ b/components/esp32/syscalls.c @@ -138,12 +138,20 @@ int _open_r(struct _reent *r, const char * path, int flags, int mode) { ssize_t _write_r(struct _reent *r, int fd, const void * data, size_t size) { const char* p = (const char*) data; if (fd == STDOUT_FILENO) { - /* THIS IS A HACK!!! The stdout "file" should be locked while - this code is called (it's locked fflush.c:280 before - __sflush_r is called.) It shouldn't be necessary to - re-lock, but due to some unknown bug it is... + static _lock_t stdout_lock; /* lazily initialised */ + /* Even though newlib does stream locking on stdout, we need + a dedicated stdout UART lock... + + This is because each task has its own _reent structure with + unique FILEs for stdin/stdout/stderr, so these are + per-thread (lazily initialised by __sinit the first time a + stdio function is used, see findfp.c:235. + + It seems like overkill to allocate a FILE-per-task and lock + a thread-local stream, but I see no easy way to fix this + (pre-__sinit_, tasks have "fake" FILEs ie __sf_fake_stdout + which aren't fully valid.) */ - static _lock_t stdout_lock; _lock_acquire_recursive(&stdout_lock); while(size--) { #if CONFIG_NEWLIB_STDOUT_ADDCR -- 2.40.0