This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Using global files instead of thread-specific files for stdio


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__


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]