Revert "Revert "Remove __sinit and __sdidinit.""
This reverts commit c8bae05f3ff9f1c736f7be70fa17d02795d748bb.
We were breaking init (ueventd) because we initialize system properties
before we initialize stdio. The new system property implementation uses
stdio to read from /property_contexts, so we end up touching stdio data
structures before they've been initialized.
This second attempt takes things further by removing the stdio initialization
function altogether. The data structures for stdin/stdout/stderr can be
statically initialized as data, and -- since we already had to give the
atexit implementation a backdoor for stdio -- we can just admit that we
need to clean up stdio, and that we always do so last.
This patch also removes the 17 statically pre-allocated file structures,
so the first fopen will now allocate a block of 10 (the usual overflow
behavior). I did this just to make my life simpler, but it's not actually
necessary to remove it if we want it back.
Change-Id: I936b2eb5e88e4ebaf5516121872b71fc88e5609c
diff --git a/libc/stdio/findfp.c b/libc/stdio/findfp.c
index 2696cfd..35de072 100644
--- a/libc/stdio/findfp.c
+++ b/libc/stdio/findfp.c
@@ -44,37 +44,35 @@
#define ALIGNBYTES (sizeof(uintptr_t) - 1)
#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) &~ ALIGNBYTES)
-int __sdidinit;
-
#define NDYNAMIC 10 /* add ten more whenever necessary */
#define std(flags, file) \
{0,0,0,flags,file,{0,0},0,__sF+file,__sclose,__sread,__sseek,__swrite, \
{(unsigned char *)(__sFext+file), 0},NULL,0,{0},{0},{0,0},0,0}
- /* the usual - (stdin + stdout + stderr) */
-static FILE usual[FOPEN_MAX - 3];
-static struct __sfileext usualext[FOPEN_MAX - 3];
-static struct glue uglue = { 0, FOPEN_MAX - 3, usual };
-static struct glue *lastglue = &uglue;
_THREAD_PRIVATE_MUTEX(__sfp_mutex);
-static struct __sfileext __sFext[3];
+static struct __sfileext __sFext[3] = {
+ { { NULL, 0 }, {}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, false },
+ { { NULL, 0 }, {}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, false },
+ { { NULL, 0 }, {}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, false },
+};
// __sF is exported for backwards compatibility. Until M, we didn't have symbols
// for stdin/stdout/stderr; they were macros accessing __sF.
FILE __sF[3] = {
- std(__SRD, STDIN_FILENO), /* stdin */
- std(__SWR, STDOUT_FILENO), /* stdout */
- std(__SWR|__SNBF, STDERR_FILENO) /* stderr */
+ std(__SRD, STDIN_FILENO),
+ std(__SWR, STDOUT_FILENO),
+ std(__SWR|__SNBF, STDERR_FILENO),
};
-struct glue __sglue = { &uglue, 3, __sF };
-
FILE* stdin = &__sF[0];
FILE* stdout = &__sF[1];
FILE* stderr = &__sF[2];
+struct glue __sglue = { NULL, 3, __sF };
+static struct glue* lastglue = &__sglue;
+
static struct glue *
moreglue(int n)
{
@@ -114,9 +112,6 @@
int n;
struct glue *g;
- if (!__sdidinit)
- __sinit();
-
_THREAD_PRIVATE_MUTEX_LOCK(__sfp_mutex);
for (g = &__sglue; g != NULL; g = g->next) {
for (fp = g->iobs, n = g->niobs; --n >= 0; fp++)
@@ -149,48 +144,7 @@
return (fp);
}
-/*
- * exit() and abort() call _cleanup() through the callback registered
- * with __atexit_register_cleanup(), set whenever we open or buffer a
- * file. This chicanery is done so that programs that do not use stdio
- * need not link it all in.
- *
- * The name `_cleanup' is, alas, fairly well known outside stdio.
- */
-void
-_cleanup(void)
-{
+__LIBC_HIDDEN__ void __libc_stdio_cleanup(void) {
/* (void) _fwalk(fclose); */
(void) _fwalk(__sflush); /* `cheating' */
}
-
-/*
- * __sinit() is called whenever stdio's internal variables must be set up.
- */
-void
-__sinit(void)
-{
- _THREAD_PRIVATE_MUTEX(__sinit_mutex);
-
- _THREAD_PRIVATE_MUTEX_LOCK(__sinit_mutex);
- if (__sdidinit) {
- /* bail out if caller lost the race */
- _THREAD_PRIVATE_MUTEX_UNLOCK(__sinit_mutex);
- return;
- }
-
- /* Initialize stdin/stdout/stderr (for the recursive mutex). http://b/18208568. */
- for (size_t i = 0; i < 3; ++i) {
- _FILEEXT_SETUP(__sF+i, __sFext+i);
- }
- /* Initialize the pre-allocated (but initially unused) streams. */
- for (size_t i = 0; i < FOPEN_MAX - 3; ++i) {
- _FILEEXT_SETUP(usual+i, usualext+i);
- }
-
- /* make sure we clean up on exit */
- __atexit_register_cleanup(_cleanup); /* conservative */
- __sdidinit = 1;
-
- _THREAD_PRIVATE_MUTEX_UNLOCK(__sinit_mutex);
-}
diff --git a/libc/stdio/local.h b/libc/stdio/local.h
index 3ae7059..6dcd3ae 100644
--- a/libc/stdio/local.h
+++ b/libc/stdio/local.h
@@ -153,10 +153,8 @@
__LIBC32_LEGACY_PUBLIC__ int __swsetup(FILE*);
/* These were referenced by a couple of different pieces of middleware and the Crystax NDK. */
-__LIBC32_LEGACY_PUBLIC__ extern int __sdidinit;
__LIBC32_LEGACY_PUBLIC__ int __sflags(const char*, int*);
__LIBC32_LEGACY_PUBLIC__ FILE* __sfp(void);
-__LIBC32_LEGACY_PUBLIC__ void __sinit(void);
__LIBC32_LEGACY_PUBLIC__ void __smakebuf(FILE*);
/* These are referenced by the Greed for Glory franchise. */
@@ -170,7 +168,6 @@
#pragma GCC visibility push(hidden)
int __sflush_locked(FILE *);
-void _cleanup(void);
int __swhatbuf(FILE *, size_t *, int *);
wint_t __fgetwc_unlock(FILE *);
wint_t __ungetwc(wint_t, FILE *);
@@ -179,8 +176,6 @@
int __vfwprintf(FILE * __restrict, const wchar_t * __restrict, __va_list);
int __vfwscanf(FILE * __restrict, const wchar_t * __restrict, __va_list);
-extern void __atexit_register_cleanup(void (*)(void));
-
/*
* Return true if the given FILE cannot be written now.
*/
@@ -237,6 +232,10 @@
extern int __sfvwrite(FILE *, struct __suio *);
wint_t __fputwc_unlock(wchar_t wc, FILE *fp);
+/* Remove the if (!__sdidinit) __sinit() idiom from untouched upstream stdio code. */
+extern void __sinit(void); // Not actually implemented.
+#define __sdidinit 1
+
#pragma GCC visibility pop
__END_DECLS
diff --git a/libc/stdio/refill.c b/libc/stdio/refill.c
index e87c7b9..5b0811f 100644
--- a/libc/stdio/refill.c
+++ b/libc/stdio/refill.c
@@ -51,11 +51,6 @@
int
__srefill(FILE *fp)
{
-
- /* make sure stdio is set up */
- if (!__sdidinit)
- __sinit();
-
fp->_r = 0; /* largely a convenience for callers */
#if !defined(__ANDROID__)