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]

Re: False syscall dependencies [PATCH]


2005/12/14, Shaun Jackman <sjackman@gmail.com>:
> Due to the rather elegant super-function, __svfscanf_r, depending on
> __sinit and thus _write, I don't see a simple way of avoiding sscanf
> sucking in the syscalls. One idea is to replace __sinit with
> __sinit_without_syscalls and __sinit_with_syscalls (named
> extra-verbosely for clarity), and remove the call to __sinit in
> __svfscanf_r, and have sscanf call __sinit_without_syscalls, whereas
> fscanf would call __sinit_with_syscalls.

This patch factors out the portion of __sinit that depends on syscalls
into its own source file, sinit.c. The portion of __sinit that does
not depend on syscalls is left in findfp.c in the function
__sinitnostd. This factorization allows the developer compiling newlib
to modify CHECK_INIT to call __sinitnostd instead of __sinit. The next
step would be to create a new macro, CHECK_INIT_NOSTD, and modify the
functions that do not require the standard streams to be initialized
to call CHECK_INIT_NOSTD instead of CHECK_INIT.

makebuf uses stat to set the buffering to line mode if the stream is a
teletype. In the existing __sinit, this code is armoured in an #ifdef
HAVE_FCNTL. I did the same thing in makebuf to prevent makebuf
depending on stat if HAVE_FCNTL is not defined. Presumably HAVE_STAT
would be a better name, but there's currently no such define used in
newlib.

Is this patch suitable for application? I grant that this
functionality is somewhat of a special need; however, giving newlib
the ability to produce binaries that do not depend on system calls is
a nice feature for embedded systems.

Cheers,
Shaun

2005-12-15  Shaun Jackman  <sjackman@gmail.com>

	* libc/stdio/Makefile.am (GENERAL_SOURCES): Add sinit.c.
	* libc/stdio/findfp.c (std, __sinit): Move this function to sinit.c.
	(__sinitnostd): New function.
	(__sfp): Call CHECK_INIT instead of __sinit.
	* libc/stdio/local.h (__sinitnostd): New function declaration.
	* libc/stdio/makebuf.c: Armour the calls to stat in HAVE_FCNTL.
	* libc/stdio/sinit.c: New file.

Index: libc/stdio/Makefile.am
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/Makefile.am,v
retrieving revision 1.20
diff -u -r1.20 Makefile.am
--- libc/stdio/Makefile.am	11 Oct 2005 23:59:32 -0000	1.20
+++ libc/stdio/Makefile.am	15 Dec 2005 16:49:26 -0000
@@ -61,6 +61,7 @@
 	setbuffer.c 			\
 	setlinebuf.c 			\
 	setvbuf.c 			\
+	sinit.c				\
 	siprintf.c 			\
 	siscanf.c 			\
 	sniprintf.c			\
Index: libc/stdio/findfp.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/findfp.c,v
retrieving revision 1.16
diff -u -r1.16 findfp.c
--- libc/stdio/findfp.c	8 Feb 2005 01:05:50 -0000	1.16
+++ libc/stdio/findfp.c	15 Dec 2005 16:49:26 -0000
@@ -26,40 +26,6 @@
 #include <sys/lock.h>
 #include "local.h"

-static _VOID
-_DEFUN(std, (ptr, flags, file, data),
-            FILE *ptr _AND
-            int flags _AND
-            int file  _AND
-            struct _reent *data)
-{
-  ptr->_p = 0;
-  ptr->_r = 0;
-  ptr->_w = 0;
-  ptr->_flags = flags;
-  ptr->_file = file;
-  ptr->_bf._base = 0;
-  ptr->_bf._size = 0;
-  ptr->_lbfsize = 0;
-  ptr->_cookie = ptr;
-  ptr->_read = __sread;
-  ptr->_write = __swrite;
-  ptr->_seek = __sseek;
-  ptr->_close = __sclose;
-#if !defined(__SINGLE_THREAD__) && !defined(_REENT_SMALL)
-  __lock_init_recursive (ptr->_lock);
-  /*
-   * #else
-   * lock is already initialized in __sfp
-   */
-#endif
-
-#ifdef __SCLE
-  if (__stextmode (ptr->_file))
-    ptr->_flags |= __SCLE;
-#endif
-}
-
 struct _glue *
 _DEFUN(__sfmoreglue, (d, n),
        struct _reent *d _AND
@@ -93,8 +59,7 @@

   __sfp_lock_acquire ();

-  if (!_GLOBAL_REENT->__sdidinit)
-    __sinit (_GLOBAL_REENT);
+  CHECK_INIT(_GLOBAL_REENT);
   for (g = &_GLOBAL_REENT->__sglue;; g = g->_next)
     {
       for (fp = g->_iobs, n = g->_niobs; --n >= 0; fp++)
@@ -156,11 +121,13 @@
 #endif

 /*
- * __sinit() is called whenever stdio's internal variables must be set up.
+ * __sinitnostd() is called whenever stdio's internal variables must
+ * be set up, but the standard streams, stdin, stdout, and stderr, are
+ * not required.
  */

 _VOID
-_DEFUN(__sinit, (s),
+_DEFUN(__sinitnostd, (s),
        struct _reent *s)
 {
   __sinit_lock_acquire ();
@@ -187,19 +154,6 @@
   s->_stderr = __sfp(s);
 #endif

-  std (s->_stdin,  __SRD, 0, s);
-
-  /* on platforms that have true file system I/O, we can verify whether stdout
-     is an interactive terminal or not.  For all other platforms, we will
-     default to line buffered mode here.  */
-#ifdef HAVE_FCNTL
-  std (s->_stdout, __SWR, 1, s);
-#else
-  std (s->_stdout, __SWR | __SLBF, 1, s);
-#endif
-
-  std (s->_stderr, __SWR | __SNBF, 2, s);
-
   __sinit_lock_release ();
 }

Index: libc/stdio/local.h
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/local.h,v
retrieving revision 1.16
diff -u -r1.16 local.h
--- libc/stdio/local.h	8 Feb 2005 01:33:17 -0000	1.16
+++ libc/stdio/local.h	15 Dec 2005 16:49:26 -0000
@@ -39,6 +39,7 @@
 extern _fpos_t _EXFUN(__sseek,(_PTR, _fpos_t, int));
 extern int    _EXFUN(__sclose,(_PTR));
 extern int    _EXFUN(__stextmode,(int));
+extern _VOID   _EXFUN(__sinitnostd,(struct _reent *));
 extern _VOID   _EXFUN(__sinit,(struct _reent *));
 extern _VOID   _EXFUN(_cleanup_r,(struct _reent *));
 extern _VOID   _EXFUN(__smakebuf,(FILE *));
Index: libc/stdio/makebuf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/makebuf.c,v
retrieving revision 1.5
diff -u -r1.5 makebuf.c
--- libc/stdio/makebuf.c	23 Apr 2004 20:01:55 -0000	1.5
+++ libc/stdio/makebuf.c	15 Dec 2005 16:49:26 -0000
@@ -46,7 +46,9 @@
       fp->_bf._size = 1;
       return;
     }
-#ifdef __USE_INTERNAL_STAT64
+#ifndef HAVE_FCNTL
+  if (1)
+#elif defined __USE_INTERNAL_STAT64
   if (fp->_file < 0 || _fstat64_r (_REENT, fp->_file, &st) < 0)
 #else
   if (fp->_file < 0 || _fstat_r (_REENT, fp->_file, &st) < 0)
@@ -57,6 +59,7 @@
       /* do not try to optimise fseek() */
       fp->_flags |= __SNPT;
     }
+#ifdef HAVE_FCNTL
   else
     {
       couldbetty = (st.st_mode & S_IFMT) == S_IFCHR;
@@ -81,6 +84,7 @@
       else
 	fp->_flags |= __SNPT;
     }
+#endif /* HAVE_FCNTL */
   if ((p = _malloc_r (_REENT, size)) == NULL)
     {
       fp->_flags |= __SNBF;
@@ -93,7 +97,9 @@
       fp->_flags |= __SMBF;
       fp->_bf._base = fp->_p = (unsigned char *) p;
       fp->_bf._size = size;
+#ifdef HAVE_FCNTL
       if (couldbetty && isatty (fp->_file))
 	fp->_flags |= __SLBF;
+#endif
     }
 }
--- /dev/null	2005-09-03 00:09:12.000000000 -0600
+++ libc/stdio/sinit.c	2005-12-15 09:46:40.000000000 -0700
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <_ansi.h>
+#include <stdio.h>
+#include "local.h"
+
+static _VOID
+_DEFUN(std, (ptr, flags, file, data),
+            FILE *ptr _AND
+            int flags _AND
+            int file  _AND
+            struct _reent *data)
+{
+  ptr->_p = 0;
+  ptr->_r = 0;
+  ptr->_w = 0;
+  ptr->_flags = flags;
+  ptr->_file = file;
+  ptr->_bf._base = 0;
+  ptr->_bf._size = 0;
+  ptr->_lbfsize = 0;
+  ptr->_cookie = ptr;
+  ptr->_read = __sread;
+  ptr->_write = __swrite;
+  ptr->_seek = __sseek;
+  ptr->_close = __sclose;
+#if !defined(__SINGLE_THREAD__) && !defined(_REENT_SMALL)
+  __lock_init_recursive (ptr->_lock);
+  /*
+   * #else
+   * lock is already initialized in __sfp
+   */
+#endif
+
+#ifdef __SCLE
+  if (__stextmode (ptr->_file))
+    ptr->_flags |= __SCLE;
+#endif
+}
+
+/*
+ * __sinit() is called whenever stdio's internal variables must be set up.
+ */
+
+_VOID
+_DEFUN(__sinit, (s),
+       struct _reent *s)
+{
+  __sinit_lock_acquire ();
+
+  __sinitnostd(s);
+
+  if (s->__sdidinit > 1)
+    {
+      __sinit_lock_release ();
+      return;
+    }
+  s->__sdidinit = 2;
+
+  std (s->_stdin,  __SRD, 0, s);
+
+  /* on platforms that have true file system I/O, we can verify whether stdout
+     is an interactive terminal or not.  For all other platforms, we will
+     default to line buffered mode here.  */
+#ifdef HAVE_FCNTL
+  std (s->_stdout, __SWR, 1, s);
+#else
+  std (s->_stdout, __SWR | __SLBF, 1, s);
+#endif
+
+  std (s->_stderr, __SWR | __SNBF, 2, s);
+
+  __sinit_lock_release ();
+}


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