[comp.lang.c] re-entrant libraries - is C deficient?

alanf@bruce.cs.monash.OZ.AU (Alan Grant Finlay) (10/02/90)

I am writing a library of C procedures which need access to a global 
data structure.  I wish to write them in a portable manner (i.e. even
outside UNIX) and to be re-entrant.

Currently I am doing this by having a compulsary first parameter to all
the procedures which is a pointer to the global data structure (apart from
one procedure which allocates this data structure and returns the pointer).
This is fine but the inefficiency annoys me.  A lot of these procedures call
each other so the pointer is popped off and onto the stack all the time.  I 
know popping it off doesn't cost anything but pushing on again does.  What 
I would like to do (and could do in assembly) is to push it on the stack
once (i.e. implicitly or explicitly dedicate a register to the task of 
locating this pointer).

I'm sure there are other languages that provide a solution to this problem.
For example in Pascal I can have nested procedures (I know this is not quite
a solution since the application must be compiled in the scope of the nested
procedures - but it is part way to a solution).

My question is: have I overlooked something or do I need to descend into
assembly language to solve this problem in C (assuming a C compiler has a 
"base" register, can do without a register or provides some means to know
where the stack base is)?  I know there are solutions for each particular
operating system but I want a techique that can be ported without having to
worry about such matters (i.e if all else fails I'll stick with the wasted
parameter).

funkstr@ucscb.UCSC.EDU (Larry Hastings) (10/03/90)

+-In article <3154@bruce.cs.monash.OZ.AU>,
| alanf@bruce.cs.monash.OZ.AU (Alan Grant Finlay) wrote:
|
| I am writing a library of C procedures which need access to a global 
| data structure.  I wish to write them in a portable manner (i.e. even
| outside UNIX) and to be re-entrant.
| 
| Currently I am doing this by having a compulsary first parameter to all
| the procedures which is a pointer to the global data structure (apart from
| one procedure which allocates this data structure and returns the pointer).
| This is fine but the inefficiency annoys me.
|
+----------

First of all, I'm assuming that this global data structure is read from,
not written to.  (Otherwise, it could never be reentrant...)

Second of all, why not simply model it exactly like it really is --
global data?  If it's never written to, you don't need to worry about
other copies of the code trashing it when you weren't looking.  Or, if you
must use a pointer to point to it, have a global pointer.

There's nothing wrong, inelegant, or even non re-entrant to use global
read-only static data.  For instance, the functions (and macros) in <ctype.h>
are considered reentrant, and yet most implementations use a static table
for the isalpha(), iscntrl(), isascii() (and so on) macros.
--
larry hastings, the galactic funkster, funkstr@ucscb.ucsc.edu

I don't speak for Knowledge Dynamics or UC Santa Cruz, nor do they speak for me

The 4th law of Robotics (courtesy of Lore Shoberg):
"A robot must encourage proper dental hygiene, except where such encouragement
 would interfere with the 0th, 1st, 2nd, and 3rd laws."

tom@ssd.csd.harris.com (Tom Horsley) (10/03/90)

>>>>> Regarding re-entrant libraries - is C deficient?; alanf@bruce.cs.monash.OZ.AU (Alan Grant Finlay) adds:

alanf> I'm sure there are other languages that provide a solution to this
alanf> problem.  For example in Pascal I can have nested procedures (I know
alanf> this is not quite a solution since the application must be compiled
alanf> in the scope of the nested procedures - but it is part way to a
alanf> solution).

I would guess that the majority of all Pascal implementations (or any other
language that allows nested procedure definitions) implement nested
procedures via static links. When it comes right down to it, a static link
is nothing more that a hidden parameter passed in to every routine that
points to the lexically correct parent stack frame (which can be thought of
as a structure). In other words, just because Pascal hides all the mechanism
does not mean that it is any lower overhead.

I hasten to add (before I get flamed to death) that many compilers may
reduce this overhead considerably by passing the static link in a register
rather than on the stack, but then on most RISC machines these days, most
arguments are passed in registers anyway.

I also hasten to add that the above comment is not an endorsment of C over
Pascal - if you need nested procedures it is obviously simpler to use a
language that actually supports them directly rather than having to create
artificial structures with extra arguments, etc.

Back to the original point - the C library is definitely deficient when it
comes to being re-entrant. The standard AT&T and/or Berkely source is chock
full of global variables being used to pass junk around between internal
static routines, etc. This becomes a real drag when you try to implement
threads. The C library needs lots of work before it can be used safely from
multiple threads of control...
--
======================================================================
domain: tahorsley@csd.harris.com       USMail: Tom Horsley
  uucp: ...!uunet!hcx1!tahorsley               511 Kingbird Circle
                                               Delray Beach, FL  33444
+==== Censorship is the only form of Obscenity ======================+
|     (Wait, I forgot government tobacco subsidies...)               |
+====================================================================+

akcs.dgy@vpnet.chi.il.us (Donald Yuniskis) (10/05/90)

>Back to the original point - the C library is definitely deficient when it
>comes to being re-entrant. The standard AT&T and/or Berkely source is chock
>full of global variables being used to pass junk around between internal
>static routines, etc. This becomes a real drag when you try to implement
>threads. The C library needs lots of work before it can be used safely from
>multiple threads of control...

Having just re-invented most of the standard libraries (string, math, stdio,
etc) from scratch for a project, I can heartily confirm this observation.  A
simple examination of the man pages for each function (with a _little_ bit
of thought) should point out most of the routines at risk.  Don't even
_THINK_ of using a "store bought" library if you're developing in a
multi-threaded environment!