Using global files instead of thread-specific files for stdio
Christoph Stoidner
c.stoidner@web.de
Sat Mar 27 21:31:00 GMT 2010
Hello,
currently every reent-struct instance allocates a separate set of files for stdio (see CHECK_INIT() and __sinit() that initializes the stdio file objects).
That means when my program creates three threads, and all of them do stdio, it opens 9 files. Each of these files requires some resources, e.g. locks.
To save some resources I have modified __sinit() in that way, that it creates once a global set of three files for stdin, stdout and stderr. These three files are allocated on the _GLOBAL_REENT instance. After that every thread-specific reent-struct could reference to these file objects.
Do you see any problems here? Do you think it would be useful to accept the modification to the official newlib-source ?
Below you can find the patch that includes my modification.
The modification will be enabled by setting the define _STDIO_SINGLETON.
--- /c/tmp/std/newlib/libc/stdio/findfp.c Tue Jul 31 21:49:40 2007
+++ libc/stdio/findfp.c Fri Mar 26 14:56:01 2010
@@ -171,11 +171,11 @@
#endif
/*
- * __sinit() is called whenever stdio's internal variables must be set up.
+ * __sinit_allocate() is called whenever stdio's object have to be allocated.
*/
-_VOID
-_DEFUN(__sinit, (s),
+static _VOID
+_DEFUN(__sinit_allocate, (s),
struct _reent *s)
{
__sinit_lock_acquire ();
@@ -221,6 +221,51 @@
std (s->_stderr, __SRW | __SNBF, 2, s);
__sinit_lock_release ();
+}
+
+/*
+ * __sinit() is called whenever stdio's internal variables must be set up.
+ */
+
+_VOID
+_DEFUN(__sinit, (s),
+ struct _reent *s)
+{
+#ifndef _STDIO_SINGLETON
+ __sinit_allocate(s);
+#else
+ __sinit_lock_acquire ();
+
+ if (s->__sdidinit)
+ {
+ __sinit_lock_release ();
+ return;
+ }
+
+ /* ensure that global reenrance structure's stdio is initialized */
+ __sinit_allocate(_GLOBAL_REENT);
+
+ s->__sdidinit = 1;
+ s->__sglue._next = NULL;
+
+#ifndef _REENT_SMALL
+ s->__sglue._niobs = 3;
+ /* link global stdio file objects to that reentrance structure */
+ s->__sglue._iobs = &_GLOBAL_REENT->__sf[0];
+ s->_stdin = _GLOBAL_REENT->_stdin;
+ s->_stdout = _GLOBAL_REENT->_stdout;
+ s->_stderr = _GLOBAL_REENT->_stderr;
+#else
+ s->__sglue._niobs = 0;
+ s->__sglue._iobs = NULL;
+ /* link global stdio file objects to that reentrance structure */
+ s->_stdin = _GLOBAL_REENT->_stdin;
+ s->_stdout = _GLOBAL_REENT->_stdout;
+ s->_stderr = _GLOBAL_REENT->_stderr;
+#endif
+
+ __sinit_lock_release ();
+#endif
}
#ifndef __SINGLE_THREAD__
More information about the Newlib
mailing list