You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Paul Sutton <pa...@ukweb.com> on 1997/09/04 14:26:25 UTC

OS abstraction, inlining functions

Here is a patch which adds support for OS specific "inline" functions. 
These lets use abstract "small" functionality such as
ap_is_path_absolute() without the overhead of a system call (at least with
GCC) and without side-effects.

This patch:

 a.  Adds an os-inline.c file in os/unix
 b.  Builds libos.a to include both os.c and os-inline.c (but on
     GCC os-inline.c will translate to an empty file)
 c.  Makes os/unix/Makefile responsible for copying required headers
     to main (os.h and os-inline.c in this case)
 d.  Adds a #include "os.h" to main/conf.h so all source modules see
     the OS specific data/functions/inlines
 e.  re-orders the libs on the httpd link to put libos.a at the end so it
     is accessable from libmain.a

and finally

 f.  Provides an ap_is_path_absolute() OS abstraction, implemented as
     an inlineable function and updates mod_alias and http_request to
     use this abstraction rather than #ifdef/#else/#endif sections

I would like someone familiar with inlining (e.g. Dean?) to check that the
including logic is OK. It seems to compile fine here (linux2) when _GNUC_
is set and when it isn't. 

If this is ok and accepted, the next stage would be to

 a.  Make win32 compile by adding ap_is_path_absolute to os/win32/os.c
     and building it into ApacheCore (or ApacheOS.lib)
 b.  Move os specific stuff from conf.h into os/*/os.h (e.g. the large
     #ifdef WIN32 section to os/win32/os.h)
 c.  Add other #defines into the abstractions (e.g. #define HAVE_SYMLINKS
     on Unix) and functions

One question: should we call the abstraction functions ap_XXX() or
os_XXX(). Previously ap_XXX() has been used throughout (ap_signal,
ap_select etc). Now os_canonical_filename has been added. Shouldn't that
be renamed ap_canonical_filname?

//pcs

Index: Configure
===================================================================
RCS file: /export/home/cvs/apachen/src/Configure,v
retrieving revision 1.145
diff -u -r1.145 Configure
--- Configure	1997/09/03 08:30:04	1.145
+++ Configure	1997/09/04 09:43:02
@@ -893,8 +893,6 @@
 echo >> Makefile.config
 echo "#### End of Configure created section ####">> Makefile.config
 
-cp $OSDIR/os.h main/os.h
-
 ####################################################################
 # Use TestCompile to see if $(CC) is ANSI and as a "final" sanity
 # check
Index: Makefile.tmpl
===================================================================
RCS file: /export/home/cvs/apachen/src/Makefile.tmpl,v
retrieving revision 1.61
diff -u -r1.61 Makefile.tmpl
--- Makefile.tmpl	1997/09/03 08:30:04	1.61
+++ Makefile.tmpl	1997/09/04 09:43:02
@@ -11,8 +11,8 @@
 OBJS= \
   modules.o \
   $(MODULES) \
-  $(OSDIR)/libos.a \
-  main/libmain.a
+  main/libmain.a \
+  $(OSDIR)/libos.a
 
 SUBDIRS=main $(OSDIR) modules
 
Index: main/conf.h
===================================================================
RCS file: /export/home/cvs/apachen/src/main/conf.h,v
retrieving revision 1.130
diff -u -r1.130 conf.h
--- conf.h	1997/08/28 01:36:59	1.130
+++ conf.h	1997/09/04 09:43:06
@@ -55,6 +55,8 @@
  * See README for a listing of what they mean
  */
 
+#include "os.h"
+
 #if !defined(QNX) && !defined(MPE) && !defined(WIN32)
 #include <sys/param.h>
 #endif
Index: main/http_request.c
===================================================================
RCS file: /export/home/cvs/apachen/src/main/http_request.c,v
retrieving revision 1.81
diff -u -r1.81 http_request.c
--- http_request.c	1997/08/31 21:28:53	1.81
+++ http_request.c	1997/09/04 09:43:11
@@ -281,12 +281,7 @@
      * for the moment, that's not worth the trouble.
      */
 
-#if defined(__EMX__) || defined(WIN32)
-    /* Add OS/2 drive name support */
-    if ((test_filename[0] != '/') && (test_filename[1] != ':'))
-#else
-    if (test_filename[0] != '/')
-#endif
+    if (!ap_is_path_absolute(test_filename))
     {
 /* fake filenames (i.e. proxy:) only match Directory sections */
         void *this_conf, *entry_config;
Index: modules/standard/mod_alias.c
===================================================================
RCS file: /export/home/cvs/apachen/src/modules/standard/mod_alias.c,v
retrieving revision 1.23
diff -u -r1.23 mod_alias.c
--- mod_alias.c	1997/08/18 13:12:08	1.23
+++ mod_alias.c	1997/09/04 09:43:14
@@ -323,12 +323,7 @@
     char *ret;
     int status;
 
-#if defined(__EMX__) || defined(WIN32)
-    /* Add support for OS/2 drive names */
-    if ((r->uri[0] != '/' && r->uri[0] != '\0') && r->uri[1] != ':')
-#else    
-    if (r->uri[0] != '/' && r->uri[0] != '\0') 
-#endif    
+    if (r->uri[0] != '\0' && !ap_is_path_absolute(r->uri)) 
         return DECLINED;
 
     if ((ret = try_alias_list (r, serverconf->redirects, 1, &status)) != NULL) {
Index: os/unix/Makefile.tmpl
===================================================================
RCS file: /export/home/cvs/apachen/src/os/unix/Makefile.tmpl,v
retrieving revision 1.3
diff -u -r1.3 Makefile.tmpl
--- Makefile.tmpl	1997/09/03 08:30:07	1.3
+++ Makefile.tmpl	1997/09/04 09:43:14
@@ -4,14 +4,15 @@
 LFLAGS=$(LFLAGS1) $(EXTRA_LFLAGS)
 INCDIR=../../main
 
-OBJS=	os.o
+OBJS=	os.o os-inline.o
 
 LIB=	libos.a
 
-all: $(LIB) 
+all:	$(LIB)
+	cp os.h ../../main
+	cp os-inline.c ../../main
 
-$(LIB): $(OBJS)
-	rm -f $@
+$(LIB):	$(OBJS)
 	ar crv $@ $(OBJS)
 	$(RANLIB) $@
 
@@ -20,8 +21,6 @@
 
 clean:
 	rm -f $(OBJS)
-
-$(OBJS): Makefile
 
 # DO NOT REMOVE
 os.o:	os.c
Index: os/unix/os.c
===================================================================
RCS file: /export/home/cvs/apachen/src/os/unix/os.c,v
retrieving revision 1.1
diff -u -r1.1 os.c
--- os.c	1997/08/10 13:33:18	1.1
+++ os.c	1997/09/04 09:43:14
@@ -0,0 +1,6 @@
+/*
+ * This file will include OS specific functions which are not inlineable.
+ * Any inlineable functions should be defined in os-inline.c instead.
+ */
+
+#include "os.h"
Index: os/unix/os.h
===================================================================
RCS file: /export/home/cvs/apachen/src/os/unix/os.h,v
retrieving revision 1.1
diff -u -r1.1 os.h
--- os.h	1997/08/10 13:33:19	1.1
+++ os.h	1997/09/04 09:43:14
@@ -0,0 +1,20 @@
+/*
+ * This file in included in all Apache source code. It contains definitions
+ * of facilities available on _this_ operating system (HAVE_* macros),
+ * and prototypes of OS specific functions defined in os.c or os-inline.c
+ */
+
+#if defined(__GNUC__) && !defined(INLINE)
+/* Compiler supports inline, so include the inlineable functions as
+ * part of the header
+ */
+#define INLINE extern inline
+#include "os-inline.c"
+#endif
+
+#ifndef INLINE
+/* Compiler does not support inline, so prototype the inlineable functions
+ * as normal
+ */
+extern int ap_is_path_absolute(char *f);
+#endif

===================================
os/unix/os-inline.c:

/*
 * This file contains functions which can be inlined if the compiler
 * has an "inline" modifier. Because of this, this file is both a
 * header file and a compilable module.
 *
 * Only inlineable functions should be defined in here. They must all
 * include the INLINE modifier. 
 *
 * If the compiler supports inline, this file will be #included as a
 * header file from os.h to create all the inline function
 * definitions. INLINE will be defined to whatever is required on
 * function definitions to make them inline declarations.
 *
 * If the compiler does not support inline, this file will be compiled
 * as a normal C file into libos.a (along with os.c). In this case
 * INLINE will _not_ be set so we can use this to test if we are
 * compiling this source file.  
 */

#ifndef INLINE
#define INLINE

/* Anything required only when compiling */

#endif

INLINE int ap_is_path_absolute(char *file)
{
  return (file && file[0] == '/' ? 1 : 0);
}



Re: OS abstraction, inlining functions

Posted by Ben Laurie <be...@algroup.co.uk>.
Paul Sutton wrote:
> 
> On Thu, 4 Sep 1997, Ben Laurie wrote:
> > Paul Sutton wrote:
> > > Here is a patch which adds support for OS specific "inline" functions.
> > > These lets use abstract "small" functionality such as
> > > ap_is_path_absolute() without the overhead of a system call (at least with
> > > GCC) and without side-effects.
> >
> > I presume you mean "function call", not "system call". But this isn't a
> > very good example, as it can be done with a #define, and thus avoid the
> > overhead on non-inlining compilers.
> 
> Umm, that was my original intention but Dean pointed out the problem of
> side effects. It is a good point: consider
> 
>   #define ap_is_path_absolute(f)      /* nb: for illustration only */ \
>                 ((f[1]==':'&&f[2]=='\\')      /* C:\ style */  \
>               || (f[0]=='\\'&&f[1]=='\\'))   /* \\SERVER\ style */
> 
> when called with
> 
>   ap_is_path_absolute(somestring++);   or
>   ap_is_path_absolute(server_root_relative(p, fname));
> 
> Macros should be used where side-effects are not possible but in this case
> a function (or inline) must be used, surely. Annoyingly VC++ 5.0 does not
> support inline functions in C code.

Good point, but toupper() and friends have existed as macros with side
effects since the year dot.

Cheers,

Ben.

-- 
Ben Laurie            |Phone: +44 (181) 994 6435|Apache Group member
Freelance Consultant  |Fax:   +44 (181) 994 6472|http://www.apache.org
and Technical Director|Email: ben@algroup.co.uk |Apache-SSL author
A.L. Digital Ltd,     |http://www.algroup.co.uk/Apache-SSL
London, England.      |"Apache: TDG" http://www.ora.com/catalog/apache

Re: OS abstraction, inlining functions

Posted by Paul Sutton <pa...@ukweb.com>.
On Thu, 4 Sep 1997, Ben Laurie wrote:
> Paul Sutton wrote:
> > Here is a patch which adds support for OS specific "inline" functions.
> > These lets use abstract "small" functionality such as
> > ap_is_path_absolute() without the overhead of a system call (at least with
> > GCC) and without side-effects.
> 
> I presume you mean "function call", not "system call". But this isn't a
> very good example, as it can be done with a #define, and thus avoid the
> overhead on non-inlining compilers.

Umm, that was my original intention but Dean pointed out the problem of
side effects. It is a good point: consider

  #define ap_is_path_absolute(f)      /* nb: for illustration only */ \
                ((f[1]==':'&&f[2]=='\\')      /* C:\ style */  \
              || (f[0]=='\\'&&f[1]=='\\'))   /* \\SERVER\ style */

when called with

  ap_is_path_absolute(somestring++);   or
  ap_is_path_absolute(server_root_relative(p, fname));

Macros should be used where side-effects are not possible but in this case
a function (or inline) must be used, surely. Annoyingly VC++ 5.0 does not
support inline functions in C code.

> ap_ is for functions that replace standard ones, os_ is for OS specific
> functions (that may do different things on different platforms).
> 
> So, ap_is_path_absolute should be os_is_path_absolute.

This does sound reasonable, so I'm happy with this os_/ap_ distinction.

//pcs



Re: OS abstraction, inlining functions

Posted by Ben Laurie <be...@algroup.co.uk>.
Paul Sutton wrote:
> 
> Here is a patch which adds support for OS specific "inline" functions.
> These lets use abstract "small" functionality such as
> ap_is_path_absolute() without the overhead of a system call (at least with
> GCC) and without side-effects.

I presume you mean "function call", not "system call". But this isn't a
very good example, as it can be done with a #define, and thus avoid the
overhead on non-inlining compilers.

> One question: should we call the abstraction functions ap_XXX() or
> os_XXX(). Previously ap_XXX() has been used throughout (ap_signal,
> ap_select etc). Now os_canonical_filename has been added. Shouldn't that
> be renamed ap_canonical_filname?

Actually, the os_ notation predates the ap_ notation - it was introduced
way back for os_escape_path (or whatever it is called).

ap_ is for functions that replace standard ones, os_ is for OS specific
functions (that may do different things on different platforms).

So, ap_is_path_absolute should be os_is_path_absolute.

Cheers,

Ben.

-- 
Ben Laurie            |Phone: +44 (181) 994 6435|Apache Group member
Freelance Consultant  |Fax:   +44 (181) 994 6472|http://www.apache.org
and Technical Director|Email: ben@algroup.co.uk |Apache-SSL author
A.L. Digital Ltd,     |http://www.algroup.co.uk/Apache-SSL
London, England.      |"Apache: TDG" http://www.ora.com/catalog/apache

Re: OS abstraction, inlining functions

Posted by Dean Gaudet <dg...@arctic.org>.
This looks fine ...

note that in conf.h I added code to "#define inline" on non-GCC compilers. 
Feel free to change that to use INLINE or whatever ... but note that I've
actually used inline a few places -- where I'm using it for static
inlines. 

Dean

On Thu, 4 Sep 1997, Paul Sutton wrote:

> Here is a patch which adds support for OS specific "inline" functions. 
> These lets use abstract "small" functionality such as
> ap_is_path_absolute() without the overhead of a system call (at least with
> GCC) and without side-effects.
> 
> This patch:
> 
>  a.  Adds an os-inline.c file in os/unix
>  b.  Builds libos.a to include both os.c and os-inline.c (but on
>      GCC os-inline.c will translate to an empty file)
>  c.  Makes os/unix/Makefile responsible for copying required headers
>      to main (os.h and os-inline.c in this case)
>  d.  Adds a #include "os.h" to main/conf.h so all source modules see
>      the OS specific data/functions/inlines
>  e.  re-orders the libs on the httpd link to put libos.a at the end so it
>      is accessable from libmain.a
> 
> and finally
> 
>  f.  Provides an ap_is_path_absolute() OS abstraction, implemented as
>      an inlineable function and updates mod_alias and http_request to
>      use this abstraction rather than #ifdef/#else/#endif sections
> 
> I would like someone familiar with inlining (e.g. Dean?) to check that the
> including logic is OK. It seems to compile fine here (linux2) when _GNUC_
> is set and when it isn't. 
> 
> If this is ok and accepted, the next stage would be to
> 
>  a.  Make win32 compile by adding ap_is_path_absolute to os/win32/os.c
>      and building it into ApacheCore (or ApacheOS.lib)
>  b.  Move os specific stuff from conf.h into os/*/os.h (e.g. the large
>      #ifdef WIN32 section to os/win32/os.h)
>  c.  Add other #defines into the abstractions (e.g. #define HAVE_SYMLINKS
>      on Unix) and functions
> 
> One question: should we call the abstraction functions ap_XXX() or
> os_XXX(). Previously ap_XXX() has been used throughout (ap_signal,
> ap_select etc). Now os_canonical_filename has been added. Shouldn't that
> be renamed ap_canonical_filname?
> 
> //pcs
> 
> Index: Configure
> ===================================================================
> RCS file: /export/home/cvs/apachen/src/Configure,v
> retrieving revision 1.145
> diff -u -r1.145 Configure
> --- Configure	1997/09/03 08:30:04	1.145
> +++ Configure	1997/09/04 09:43:02
> @@ -893,8 +893,6 @@
>  echo >> Makefile.config
>  echo "#### End of Configure created section ####">> Makefile.config
>  
> -cp $OSDIR/os.h main/os.h
> -
>  ####################################################################
>  # Use TestCompile to see if $(CC) is ANSI and as a "final" sanity
>  # check
> Index: Makefile.tmpl
> ===================================================================
> RCS file: /export/home/cvs/apachen/src/Makefile.tmpl,v
> retrieving revision 1.61
> diff -u -r1.61 Makefile.tmpl
> --- Makefile.tmpl	1997/09/03 08:30:04	1.61
> +++ Makefile.tmpl	1997/09/04 09:43:02
> @@ -11,8 +11,8 @@
>  OBJS= \
>    modules.o \
>    $(MODULES) \
> -  $(OSDIR)/libos.a \
> -  main/libmain.a
> +  main/libmain.a \
> +  $(OSDIR)/libos.a
>  
>  SUBDIRS=main $(OSDIR) modules
>  
> Index: main/conf.h
> ===================================================================
> RCS file: /export/home/cvs/apachen/src/main/conf.h,v
> retrieving revision 1.130
> diff -u -r1.130 conf.h
> --- conf.h	1997/08/28 01:36:59	1.130
> +++ conf.h	1997/09/04 09:43:06
> @@ -55,6 +55,8 @@
>   * See README for a listing of what they mean
>   */
>  
> +#include "os.h"
> +
>  #if !defined(QNX) && !defined(MPE) && !defined(WIN32)
>  #include <sys/param.h>
>  #endif
> Index: main/http_request.c
> ===================================================================
> RCS file: /export/home/cvs/apachen/src/main/http_request.c,v
> retrieving revision 1.81
> diff -u -r1.81 http_request.c
> --- http_request.c	1997/08/31 21:28:53	1.81
> +++ http_request.c	1997/09/04 09:43:11
> @@ -281,12 +281,7 @@
>       * for the moment, that's not worth the trouble.
>       */
>  
> -#if defined(__EMX__) || defined(WIN32)
> -    /* Add OS/2 drive name support */
> -    if ((test_filename[0] != '/') && (test_filename[1] != ':'))
> -#else
> -    if (test_filename[0] != '/')
> -#endif
> +    if (!ap_is_path_absolute(test_filename))
>      {
>  /* fake filenames (i.e. proxy:) only match Directory sections */
>          void *this_conf, *entry_config;
> Index: modules/standard/mod_alias.c
> ===================================================================
> RCS file: /export/home/cvs/apachen/src/modules/standard/mod_alias.c,v
> retrieving revision 1.23
> diff -u -r1.23 mod_alias.c
> --- mod_alias.c	1997/08/18 13:12:08	1.23
> +++ mod_alias.c	1997/09/04 09:43:14
> @@ -323,12 +323,7 @@
>      char *ret;
>      int status;
>  
> -#if defined(__EMX__) || defined(WIN32)
> -    /* Add support for OS/2 drive names */
> -    if ((r->uri[0] != '/' && r->uri[0] != '\0') && r->uri[1] != ':')
> -#else    
> -    if (r->uri[0] != '/' && r->uri[0] != '\0') 
> -#endif    
> +    if (r->uri[0] != '\0' && !ap_is_path_absolute(r->uri)) 
>          return DECLINED;
>  
>      if ((ret = try_alias_list (r, serverconf->redirects, 1, &status)) != NULL) {
> Index: os/unix/Makefile.tmpl
> ===================================================================
> RCS file: /export/home/cvs/apachen/src/os/unix/Makefile.tmpl,v
> retrieving revision 1.3
> diff -u -r1.3 Makefile.tmpl
> --- Makefile.tmpl	1997/09/03 08:30:07	1.3
> +++ Makefile.tmpl	1997/09/04 09:43:14
> @@ -4,14 +4,15 @@
>  LFLAGS=$(LFLAGS1) $(EXTRA_LFLAGS)
>  INCDIR=../../main
>  
> -OBJS=	os.o
> +OBJS=	os.o os-inline.o
>  
>  LIB=	libos.a
>  
> -all: $(LIB) 
> +all:	$(LIB)
> +	cp os.h ../../main
> +	cp os-inline.c ../../main
>  
> -$(LIB): $(OBJS)
> -	rm -f $@
> +$(LIB):	$(OBJS)
>  	ar crv $@ $(OBJS)
>  	$(RANLIB) $@
>  
> @@ -20,8 +21,6 @@
>  
>  clean:
>  	rm -f $(OBJS)
> -
> -$(OBJS): Makefile
>  
>  # DO NOT REMOVE
>  os.o:	os.c
> Index: os/unix/os.c
> ===================================================================
> RCS file: /export/home/cvs/apachen/src/os/unix/os.c,v
> retrieving revision 1.1
> diff -u -r1.1 os.c
> --- os.c	1997/08/10 13:33:18	1.1
> +++ os.c	1997/09/04 09:43:14
> @@ -0,0 +1,6 @@
> +/*
> + * This file will include OS specific functions which are not inlineable.
> + * Any inlineable functions should be defined in os-inline.c instead.
> + */
> +
> +#include "os.h"
> Index: os/unix/os.h
> ===================================================================
> RCS file: /export/home/cvs/apachen/src/os/unix/os.h,v
> retrieving revision 1.1
> diff -u -r1.1 os.h
> --- os.h	1997/08/10 13:33:19	1.1
> +++ os.h	1997/09/04 09:43:14
> @@ -0,0 +1,20 @@
> +/*
> + * This file in included in all Apache source code. It contains definitions
> + * of facilities available on _this_ operating system (HAVE_* macros),
> + * and prototypes of OS specific functions defined in os.c or os-inline.c
> + */
> +
> +#if defined(__GNUC__) && !defined(INLINE)
> +/* Compiler supports inline, so include the inlineable functions as
> + * part of the header
> + */
> +#define INLINE extern inline
> +#include "os-inline.c"
> +#endif
> +
> +#ifndef INLINE
> +/* Compiler does not support inline, so prototype the inlineable functions
> + * as normal
> + */
> +extern int ap_is_path_absolute(char *f);
> +#endif
> 
> ===================================
> os/unix/os-inline.c:
> 
> /*
>  * This file contains functions which can be inlined if the compiler
>  * has an "inline" modifier. Because of this, this file is both a
>  * header file and a compilable module.
>  *
>  * Only inlineable functions should be defined in here. They must all
>  * include the INLINE modifier. 
>  *
>  * If the compiler supports inline, this file will be #included as a
>  * header file from os.h to create all the inline function
>  * definitions. INLINE will be defined to whatever is required on
>  * function definitions to make them inline declarations.
>  *
>  * If the compiler does not support inline, this file will be compiled
>  * as a normal C file into libos.a (along with os.c). In this case
>  * INLINE will _not_ be set so we can use this to test if we are
>  * compiling this source file.  
>  */
> 
> #ifndef INLINE
> #define INLINE
> 
> /* Anything required only when compiling */
> 
> #endif
> 
> INLINE int ap_is_path_absolute(char *file)
> {
>   return (file && file[0] == '/' ? 1 : 0);
> }
> 
> 
> 


Re: OS abstraction, inlining functions

Posted by Alexei Kosut <ak...@organic.com>.
On Thu, 4 Sep 1997, Paul Sutton wrote:

> One question: should we call the abstraction functions ap_XXX() or
> os_XXX(). Previously ap_XXX() has been used throughout (ap_signal,
> ap_select etc). Now os_canonical_filename has been added. Shouldn't that
> be renamed ap_canonical_filname?

Well, os_canonical_filename was named after os_escape_path(), which has
been around for a long while. But maybe we should change them. I dunno.

-- Alexei Kosut <ak...@organic.com>