Skip to content

Commit 375aed1

Browse files
committed
sys/newlib_syscalls_default: fix race condition in __sinit()
This eagerly calls `__sinit()` instead of lazy initialization upon the first call to stdio (e.g. `puts()`, `printf()`). The issue is that without locking (as is currently the case for all RIOT platforms but ESP) two concurrent "first calls" may result in concurrent initialization of the same structure and data corruption. Fixes #20067
1 parent ef0e3fb commit 375aed1

File tree

1 file changed

+26
-15
lines changed

1 file changed

+26
-15
lines changed

sys/newlib_syscalls_default/syscalls.c

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,32 +24,27 @@
2424
* @}
2525
*/
2626

27-
#include <unistd.h>
28-
#include <reent.h>
2927
#include <errno.h>
3028
#include <malloc.h>
29+
#include <reent.h>
30+
#include <stdint.h>
3131
#include <stdio.h>
32-
#include <stdlib.h>
33-
#include <string.h>
3432
#include <sys/stat.h>
33+
#include <sys/times.h>
3534
#include <sys/unistd.h>
36-
#include <stdint.h>
35+
#include <unistd.h>
3736

38-
#include "cpu.h"
39-
#include "board.h"
40-
#include "sched.h"
41-
#include "thread.h"
42-
#include "irq.h"
4337
#include "log.h"
38+
#include "modules.h"
4439
#include "periph/pm.h"
40+
#include "sched.h"
41+
#include "stdio_base.h"
42+
#include "thread.h"
43+
4544
#if MODULE_VFS
4645
#include "vfs.h"
4746
#endif
4847

49-
#include "stdio_base.h"
50-
51-
#include <sys/times.h>
52-
5348
#ifdef MODULE_XTIMER
5449
#include <sys/time.h>
5550
#include "div.h"
@@ -149,7 +144,23 @@ static const struct heap heaps[NUM_HEAPS] = {
149144
*/
150145
void _init(void)
151146
{
152-
/* nothing to do here */
147+
/* Definition copied from newlib/libc/stdio/local.h */
148+
extern void __sinit (struct _reent *);
149+
150+
/* When running multiple threads: Initialize reentrant structure before the
151+
* scheduler starts. This normally happens upon the first stdio function
152+
* called. However, if no boot message happens this can result in two
153+
* concurrent "first calls" to stdio in data corruption, if no locking is
154+
* used. Except for ESP (which is using its own syscalls.c anyway), this
155+
* currently is the case in RIOT. */
156+
if (MAXTHREADS > 1) {
157+
/* Also, make an exception for riotboot, which does not use stdio
158+
* at all. This would pull in stdio and increase .text size
159+
* significantly there */
160+
if (!IS_USED(MODULE_RIOTBOOT)) {
161+
__sinit(_REENT);
162+
}
163+
}
153164
}
154165

155166
/**

0 commit comments

Comments
 (0)