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!