writing shared libraries

writing shared libraries

Post by Eri » Wed, 21 Nov 2001 03:57:28



If I write a shared library, do I need to protect static variables
against concurrency problems?

Example (code that might be compiled into a shared library):

---

#define MAGIC_CONSTANT 5

static int magic_number;

void
do_magic ()
{
  if (magic_number < MAGIC_CONSTANT)
    ++magic_number;
  else
    magic_number = 0;

Quote:}

---

Does (magic_number <= MAGIC_CONSTANT) always hold?

Thanks in advance,
Eric.

 
 
 

writing shared libraries

Post by Jens.Toerr.. » Wed, 21 Nov 2001 09:09:45



> If I write a shared library, do I need to protect static variables
> against concurrency problems?
> Example (code that might be compiled into a shared library):
> #define MAGIC_CONSTANT 5
> static int magic_number;
> void
> do_magic ()
> {
>   if (magic_number < MAGIC_CONSTANT)
>     ++magic_number;
>   else
>     magic_number = 0;
> }
> Does (magic_number <= MAGIC_CONSTANT) always hold?

As long as you don't have another function in this file that increments
magic_number you don't have to fear anything - the static keyword in the
definition of magic_numbers makes sure that it will never been seen out-
side the current translation unit (assuming this is C :-). It doesn't
matter if it's in a library or just in one of the files of a larger
project. A dlsym() on magic_number should fail (and nm lists such
variables as local). But if you have any doubts just write a short test
program and please tell me if I am wrong (wouldn't be the first time :-)

                                         Regards, Jens
--
      _  _____  _____

  _  | |  | |    | |          AG Moebius, Institut fuer Molekuelphysik
 | |_| |  | |    | |          Fachbereich Physik, Freie Universitaet Berlin
  \___/ens|_|homs|_|oerring   Tel: ++49 (0)30 838 - 53394 / FAX: - 56046

 
 
 

writing shared libraries

Post by Eri » Thu, 22 Nov 2001 00:41:34




> > If I write a shared library, do I need to protect static variables
> > against concurrency problems?
> > Example (code that might be compiled into a shared library):
> > #define MAGIC_CONSTANT 5
> > static int magic_number;
> > void
> > do_magic ()
> > {
> >   if (magic_number < MAGIC_CONSTANT)
> >     ++magic_number;
> >   else
> >     magic_number = 0;
> > }
> > Does (magic_number <= MAGIC_CONSTANT) always hold?

> As long as you don't have another function in this file that increments
> magic_number you don't have to fear anything - the static keyword in the
> definition of magic_numbers makes sure that it will never been seen out-
> side the current translation unit (assuming this is C :-). It doesn't
> matter if it's in a library or just in one of the files of a larger
> project. A dlsym() on magic_number should fail (and nm lists such
> variables as local). But if you have any doubts just write a short test
> program and please tell me if I am wrong (wouldn't be the first time :-)

>                                          Regards, Jens

This all makes sense but still doesn't quite answer (what I meant by)
my question.  I will try to make it more clear:  There is only one
copy of the shared library object code in memory and I would therefore
assume only one copy of magic_number.  Now, suppose two separate
processes are using the shared library concurrently and both call
foo().  Now, here is the catch:  Suppose magic_number is 4.  Process A
checks (magic_number < MAGIC_CONSTANT) and then is context-switched
out before it gets to increment magic_number.  Process B then checks
(magic_number < MAGIC_CONSTANT) and increments magic_number to 5.
When process A comes back it increments magic_number to 6 making
(magic_number > MAGIC_CONSTANT).
  Is this sequence of events possible?  Maybe only one process may
execute foo() at a time or maybe Linux protects against this
`automagically'.  I am just looking for assurance that I don't have to
protect against such races manually.  Thanks again...

Eric.

 
 
 

writing shared libraries

Post by David Konerdi » Thu, 22 Nov 2001 01:00:14


Quote:

> This all makes sense but still doesn't quite answer (what I meant by)
> my question.  I will try to make it more clear:  There is only one
> copy of the shared library object code in memory and I would therefore
> assume only one copy of magic_number.  Now, suppose two separate
> processes are using the shared library concurrently and both call
> foo().  Now, here is the catch:  Suppose magic_number is 4.  Process A
> checks (magic_number < MAGIC_CONSTANT) and then is context-switched
> out before it gets to increment magic_number.  Process B then checks
> (magic_number < MAGIC_CONSTANT) and increments magic_number to 5.
> When process A comes back it increments magic_number to 6 making
> (magic_number > MAGIC_CONSTANT).

I believe you are incorrect in assuming that when two seperate
processes dlopen a shared library, that they both processes share a
common data section from the shared library.  That is not correct- they
share the text (function/code) section but each gets a unique copy of
the data, so there is no need to protect the static variable.
 
 
 

writing shared libraries

Post by Ben Hutching » Fri, 23 Nov 2001 01:29:29


<snip>

Quote:> I believe you are incorrect in assuming that when two seperate
> processes dlopen a shared library, that they both processes share a
> common data section from the shared library.  That is not correct- they
> share the text (function/code) section but each gets a unique copy of
> the data, so there is no need to protect the static variable.

On the other hand, if multiple threads in a process use the library,
such protection may be needed.  However, it may be sufficient to
document that this function is not thread-safe and to allow the
library user to make it so if necessary.
 
 
 

writing shared libraries

Post by Phil Adam » Sat, 24 Nov 2001 16:30:41



> This all makes sense but still doesn't quite answer (what I meant by)
> my question.  I will try to make it more clear:  There is only one
> copy of the shared library object code in memory and I would therefore
> assume only one copy of magic_number.  Now, suppose two separate
> processes are using the shared library concurrently and both call
> foo().  Now, here is the catch:  Suppose magic_number is 4.  Process A
> checks (magic_number < MAGIC_CONSTANT) and then is context-switched
> out before it gets to increment magic_number.  Process B then checks
> (magic_number < MAGIC_CONSTANT) and increments magic_number to 5.
> When process A comes back it increments magic_number to 6 making
> (magic_number > MAGIC_CONSTANT).
>   Is this sequence of events possible?  Maybe only one process may
> execute foo() at a time or maybe Linux protects against this
> `automagically'.  I am just looking for assurance that I don't have to
> protect against such races manually.  Thanks again...

As someone already pointed out, each process gets its own copy of the
data. You also might want to initialize the static variable to 0 or some
other appropriate value.   Otherwise, there's no guarantee what initial
value it has.

--
Phil Adams
WebSphere Development
IBM Austin, TX